爱科技、爱创意、爱折腾、爱极致,我们都是技术控
您需要 登录 才可以下载或查看,没有账号?立即注册
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
|