搜索
bottom↓
回复: 9

单片机录音与播声音ADPCM算法

[复制链接]

出0入0汤圆

发表于 2014-2-24 16:01:28 | 显示全部楼层 |阅读模式
用16BIT 单片机AD 各DA,的ADPCM的编码与解码做录音方案,出来的音质还过得去!!算法如下:

/* Includes ------------------------------------------------------------------*/
#include "adpcm.h"

/* Private define ------------------------------------------------------------*/
/* Quantizer step size lookup table */
const uint16_t StepSizeTable[89]={7,8,9,10,11,12,13,14,16,17,
                            19,21,23,25,28,31,34,37,41,45,
                            50,55,60,66,73,80,88,97,107,118,
                            130,143,157,173,190,209,230,253,279,307,
                            337,371,408,449,494,544,598,658,724,796,
                            876,963,1060,1166,1282,1411,1552,1707,1878,2066,
                            2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,
                            5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,
                            15289,16818,18500,20350,22385,24623,27086,29794,32767};
/* Table of index changes */
const int8_t IndexTable[16]={0xff,0xff,0xff,0xff,2,4,6,8,0xff,0xff,0xff,0xff,2,4,6,8};

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  ADPCM_Encode.
  * @param sample: a 16-bit PCM sample
  * @retval : a 4-bit ADPCM sample
  */
uint8_t ADPCM_Encode(int32_t sample)
{
  static int16_t  index = 0;
  static int32_t predsample = 0;
  uint8_t code=0;
  uint16_t tmpstep=0;
  int32_t diff=0;
  int32_t diffq=0;
  uint16_t step=0;
  
  step = StepSizeTable[index];

  /* 2. compute diff and record sign and absolut value */
  diff = sample-predsample;
  if (diff < 0)  
  {
    code=8;
    diff = -diff;
  }   
  
  /* 3. quantize the diff into ADPCM code */
  /* 4. inverse quantize the code into a predicted diff */
  tmpstep = step;
  diffq = (step >> 3);

  if (diff >= tmpstep)
  {
    code |= 0x04;
    diff -= tmpstep;
    diffq += step;
  }
  
  tmpstep = tmpstep >> 1;

  if (diff >= tmpstep)
  {
    code |= 0x02;
    diff -= tmpstep;
    diffq+=(step >> 1);
  }
  
  tmpstep = tmpstep >> 1;
  
  if (diff >= tmpstep)
  {
    code |=0x01;
    diffq+=(step >> 2);
  }
  
  /* 5. fixed predictor to get new predicted sample*/
  if (code & 8)
  {
    predsample -= diffq;
  }
  else
  {
    predsample += diffq;
  }  

  /* check for overflow*/
  if (predsample > 32767)
  {
    predsample = 32767;
  }
  else if (predsample < -32768)
  {
    predsample = -32768;
  }
  
  /* 6. find new stepsize index */
  index += IndexTable[code];
  /* check for overflow*/
  if (index <0)
  {
    index = 0;
  }
  else if (index > 88)
  {
    index = 88;
  }
  
  /* 8. return new ADPCM code*/
  return (code & 0x0f);
}



/**
  * @brief  ADPCM_Decode.
  * @param code: a byte containing a 4-bit ADPCM sample.
  * @retval : 16-bit ADPCM sample
  */
int16_t ADPCM_Decode(uint8_t code)
{
  static int16_t  index = 0;
  static int32_t predsample = 0;
  uint16_t step=0;
  int32_t diffq=0;
  
  step = StepSizeTable[index];

  /* 2. inverse code into diff */
  diffq = step>> 3;
  if (code&4)
  {
    diffq += step;
  }
  
  if (code&2)
  {
    diffq += step>>1;
  }
  
  if (code&1)
  {
    diffq += step>>2;
  }

  /* 3. add diff to predicted sample*/
  if (code&8)
  {
    predsample -= diffq;
  }
  else
  {
    predsample += diffq;
  }
  
  /* check for overflow*/
  if (predsample > 32767)
  {
    predsample = 32767;
  }
  else if (predsample < -32768)
  {
    predsample = -32768;
  }

  /* 4. find new quantizer step size */
  index += IndexTable [code];
  /* check for overflow*/
  if (index < 0)
  {
    index = 0;
  }
  if (index > 88)
  {
    index = 88;
  }
  
  /* 5. save predict sample and index for next iteration */
  /* done! static variables */
  
  /* 6. return new speech sample*/
  return ((int16_t)predsample);
}

//////=========================================
但后来项目用10BIT单片机 的AD与DA做,我采用移位把10BIT移成16BIT做编码,然后解码后16BIT移成10BIT,同上面算法,出来声音噪声很大!
不知怎么改想把上面的算法改成10BIT的编码与解码的算法!!
有没有做过类似东西的大哥哥出来支招啊!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2014-2-24 20:49:13 | 显示全部楼层
请注意有符号数跟无符号数的区别,有符号数不能简单移位的。

出0入0汤圆

 楼主| 发表于 2014-2-24 21:31:50 | 显示全部楼层
谢谢!我想想看符号怎么处理!

出0入4汤圆

发表于 2022-1-8 18:00:00 来自手机 | 显示全部楼层
如果是用于STC8H系列的带12位ADC,12-16位PWM,那么以上程序里要改什么参数?

出1315入193汤圆

发表于 2022-1-9 10:20:06 | 显示全部楼层
kundi 发表于 2022-1-8 18:00
如果是用于STC8H系列的带12位ADC,12-16位PWM,那么以上程序里要改什么参数?

这篇文章可以参考  在STM32开发板下输出PWM及使用DAC功能完成你模拟音频文件波形输出

出100入312汤圆

发表于 2022-1-9 10:47:35 来自手机 | 显示全部楼层
不错,收藏

出10入0汤圆

发表于 2022-1-9 12:57:15 来自手机 | 显示全部楼层
收藏一下!谢谢分享。

出0入4汤圆

发表于 2022-1-23 11:42:11 来自手机 | 显示全部楼层
对了,楼主的这代码感觉是只对1个样值编解码。网上看到的其他adpcm代码是可以一次编解码多个样值的。实际上是一组只有一个样值也可吗?(我感觉编码很多个样值再存储,可能在一些无DMA的平台上造成语音不连续)

出0入0汤圆

发表于 2022-1-27 16:14:50 | 显示全部楼层
收藏,谢谢分享。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-29 04:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表