数码之家

 找回密码
 立即注册
搜索
查看: 136|回复: 1

[STM] 关于单片机用ADPCM编解码与A-Law编解码

[复制链接]
发表于 2024-2-29 10:55:19 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
编码已在STM32F103上进行 IIS输入-编码-无线传输-解码-送出DAC 或者 IIS
ADPCM可以把16BIT的数据压缩到4BIT

-----------ADPCM.H------------------
uint8_t ADPCM_Encode(int32_t sample);//编码
int16_t ADPCM_Decode(uint8_t code);//解码

-----------ADPCM.C------------------
#include "adpcm.h"
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};
const int8_t IndexTable[16]={0xff,0xff,0xff,0xff,2,4,6,8,0xff,0xff,0xff,0xff,2,4,6,8};
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];
  diff = sample-predsample;
  if (diff < 0)  
  {
    code=8;
    diff = -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);
  }
  
  if (code & 8)
  {
    predsample -= diffq;
  }
  else
  {
    predsample += diffq;
  }  

  if (predsample > 32767)
  {
    predsample = 32767;
  }
  else if (predsample < -32768)
  {
    predsample = -32768;
  }
  index += IndexTable[code];
  if (index <0)
  {
    index = 0;
  }
  else if (index > 88)
  {
    index = 88;
  }
  return (code & 0x0f);
}

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];
  diffq = step>> 3;
  if (code&4)
  {
    diffq += step;
  }
  
  if (code&2)
  {
    diffq += step>>1;
  }
  
  if (code&1)
  {
    diffq += step>>2;
  }
  if (code&8)
  {
    predsample -= diffq;
  }
  else
  {
    predsample += diffq;
  }
  if (predsample > 32767)
  {
    predsample = 32767;
  }
  else if (predsample < -32768)
  {
    predsample = -32768;
  }
  index += IndexTable [code];
  if (index < 0)
  {
    index = 0;
  }
  if (index > 88)
  {
    index = 88;
  }
  return ((int16_t)predsample);
}
--------------------------------------------------------------------
下面是A_Law  比ADPCM效果好,但是数据长度更大
--------------------------------------------------------------------

#include "stdio.h"

#define SIGN_BIT    (0x80)
#define QUANT_MASK  (0xf)   
#define NSEGS       (8)      
#define SEG_SHIFT   (4)        
#define SEG_MASK    (0x70)   

static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,  0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};  //分成不均匀的8个分段,算上负数,总共是16个分段
  

unsigned char _u2a[128] = {
    1,  1,  2,  2,  3,  3,  4,  4,  
    5,  5,  6,  6,  7,  7,  8,  8,  
    9,  10, 11, 12, 13, 14, 15, 16,  
    17, 18, 19, 20, 21, 22, 23, 24,  
    25, 27, 29, 31, 33, 34, 35, 36,  
    37, 38, 39, 40, 41, 42, 43, 44,  
    46, 48, 49, 50, 51, 52, 53, 54,  
    55, 56, 57, 58, 59, 60, 61, 62,  
    64, 65, 66, 67, 68, 69, 70, 71,  
    72, 73, 74, 75, 76, 77, 78, 79,  
    81, 82, 83, 84, 85, 86, 87, 88,  
    89, 90, 91, 92, 93, 94, 95, 96,  
    97, 98, 99, 100,101,102,103,104,  
    105,106,107,108,109,110,111,112,  
    113,114,115,116,117,118,119,120,  
    121,122,123,124,125,126,127,128  
};  
  
unsigned char _a2u[128] = {
    1,  3,  5,  7,  9,  11, 13, 15,  
    16, 17, 18, 19, 20, 21, 22, 23,  
    24, 25, 26, 27, 28, 29, 30, 31,  
    32, 32, 33, 33, 34, 34, 35, 35,  
    36, 37, 38, 39, 40, 41, 42, 43,  
    44, 45, 46, 47, 48, 48, 49, 49,  
    50, 51, 52, 53, 54, 55, 56, 57,  
    58, 59, 60, 61, 62, 63, 64, 64,  
    65, 66, 67, 68, 69, 70, 71, 72,  
    73, 74, 75, 76, 77, 78, 79, 79,  
    80, 81, 82, 83, 84, 85, 86, 87,  
    88, 89, 90, 91, 92, 93, 94, 95,  
    96, 97, 98, 99, 100,101,102,103,  
    104,105,106,107,108,109,110,111,  
    112,113,114,115,116,117,118,119,  
    120,121,122,123,124,125,126,127  
};  
  
static int search(int val,short *table,int size)  
{  
    int     i;  
    for (i = 0; i < size; i++) {  
        if (val <= *table++)  
            return (i);  
    }  
    return (size);  
}  

/*********************************************************************

编码
* 输入参数范围 :-32768~32767
* 返回8位无符号整数
/*********************************************************************
unsigned char linear2alaw(int pcm_val)
{  
    int             mask;  
    int             seg;  
    unsigned char   aval;  
    if (pcm_val >= 0) {  
        mask = 0xD5;      
    } else {  
        mask = 0x55;     
        pcm_val = -pcm_val - 1;  
    }  
    seg = search(pcm_val, seg_end, 8);
    if (seg >= 8)        
        return (0x7F ^ mask);  
    else {  
        aval = seg << SEG_SHIFT;
        if (seg < 2)  
            aval |= (pcm_val >> 4) & QUANT_MASK;  
        else  
            aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
        return (aval ^ mask);   
    }  
}  

/*********************************************************************

解码
* 输入8位整数
* 返回16位无符号整数
/*********************************************************************

int alaw2linear(unsigned char a_val)  
{  
    int     t;  
    int     seg;  
  
    a_val ^= 0x55;  
  
    t = (a_val & QUANT_MASK) << 4;  
    seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;  
    switch (seg) {  
    case 0:  
        t += 8;  
        break;  
    case 1:  
        t += 0x108;  
        break;  
    default:  
        t += 0x108;  
        t <<= seg - 1;  
    }  
    return ((a_val & SIGN_BIT) ? t : -t);  
}

-------------------------------------------------------------------------

以上编码经过测试 ADPCM必须是连续性的才能保证还原,但是优点是转换速度极快
A_Law A率的方式,损失就比较小了,但是编解码速度低于ADPCM


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-29 09:42 , Processed in 0.156000 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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