📄 adpcm.c
字号:
#include "common.h"
#include <stdio.h>
/* Intel ADPCM step variation table */
short indexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};
// const short
short 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
};
/*======================================= Encode Part Begin ====================================*/
// these parameters are for encode
/* left channel parameters */
short LeftEncodePreVal; // save the previous value for left channel
short LeftEncodeIndex; // save the index for left channel
//short LeftEncodeDataIn[10]; // here is the 2 word bytes input audio data for left channel
//char LeftEncodeDataOut[60]; // store the compressed data
short LeftEncodeDataIn[10];
char LeftEncodeDataOut[512]; // store the compressed data 128
short RightEncodeDataIn[10]; // here is the 2 word bytes input audio data for right channel
char RightEncodeDataOut[512]; // store the compressed data 128
/* right channel parameters */
short RightEncodePreVal; // save the previous value for right channel
short RightEncodeIndex; // save the index for right channel
//short RightEncodeDataIn[10]; // here is the 2 word bytes input audio data for right channel
//char RightEncodeDataOut[60]; // store the compressed data
/* output pointer for left and right channel */
unsigned char EncodeOutPointer;
unsigned char tmp=0;
/*===============================================================================================
= Explain: =
= You can sample the audio data and stored it in xEncodeDataIn[](total 2 word every time), then =
= you can call ADPCM_Encode(), the audio data will be compressed and stored in xEncodeDataOut[],=
= 2 word will be compressed as 1 byte =
= Example: =
= Now LeftEncodeDataIn[0]=0xfd26,LeftEncodeDataIn[1]=0xfc6a,EncodeOutPointer=0, =
= after you call ADPCM_Encode(LeftChannel), then LeftEncodeDataOut[0] will be 0xff =
===============================================================================================*/
void ADPCM_Encode (unsigned char LeftRight)
{
unsigned char i;
short step;
short valpre;
short index;
short val;
short delta;
unsigned char sign;
short vpdiff;
unsigned char outbuffer;
if (LeftRight==LeftChannel)
{
valpre = LeftEncodePreVal;
index = LeftEncodeIndex;
}
else
{
valpre = RightEncodePreVal;
index = RightEncodeIndex;
}
step = stepsizeTable[index];
for (i=0;i<2;i++)
{
if (LeftRight==LeftChannel)
val = LeftEncodeDataIn[i];
else
val = RightEncodeDataIn[i];
// Step 1 --- compute difference with previous value
//delta = val - valpre;
//sign = (delta<0)?8:0;
//if (sign==8) delta=(-delta);
if (val<valpre)
{
sign = 8;
delta=valpre-val;
}
else
{
sign = 0;
delta=val-valpre;
}
// Step 2 --- Divide and clamp
/*
if (1)
{
delta = (delta<<2)/step;
if (delta>7) delta = 7;
vpdiff = (delta*step)>>2;
}
else
{*/
vpdiff = 0;
if (delta > step)
{
tmp = 4;
delta -= step;
vpdiff = step;
}
step >>= 1;
if (delta > step)
{
tmp |= 2;
delta -= step;
vpdiff += step;
}
step >>= 1;
if (delta > step)
{
tmp |= 1;
vpdiff += step;
}
delta = tmp;
//}
// Step 3 --- Update previous value
if (sign==8)
valpre -= vpdiff;
else
valpre += vpdiff;
// Step 4 --- Clamp previous value to 16 bits
if (valpre>32767)
valpre = 32767;
else if (valpre<-32768)
valpre = -32768;
// Step 5 --- Assemble value, update index and step values
delta |= sign;
index += indexTable[delta];
if (index<0) index = 0;
if (index>88) index = 88;
step = stepsizeTable[index];
// Step 6 --- Output value
if (i==0)
{
outbuffer = (delta<<4)&0xf0;
}
else // here 2 frame end, need save the valpre and index
{
if (LeftRight==LeftChannel)
{
LeftEncodeIndex = index;
LeftEncodePreVal = valpre;
LeftEncodeDataOut[EncodeOutPointer]=(delta&0x0f)|outbuffer;
}
else
{
RightEncodeIndex = index;
RightEncodePreVal = valpre;
RightEncodeDataOut[EncodeOutPointer]=(char)((delta&0x0f)|outbuffer);
}
}
}
}
/*======================================= Decode Part Begin ====================================*/
// these parameters are for Decode
/* left channel parameters */
short LeftDecodePreVal; // save the previous value for left channel
short LeftDecodeIndex; // save the index for left channel
char LeftDecodeDataIn[220 * 1024]; // input audio data compressed for left channel
short LeftDecodeDataOut[10]; // store the uncompressed data
/* right channel parameters */
short RightDecodePreVal; // save the previous value for right channel
short RightDecodeIndex; // save the index for right channel
char RightDecodeDataIn[220 * 1024]; // input audio data compressed for right channel
short RightDecodeDataOut[10]; // store the uncompressed data
/* output pointer for left and right channel */
unsigned char DecodeOutPointer;
/*===============================================================================================
= Explain: =
= You can get the audio data compressed and stored it in xDecodeDataIn[] (total 1 byte every =
= time), then you can call ADPCM_Decode(), the audio data will be uncompressed and stored in =
= xDecodeDataOut[],1 byte will be uncompressed as 2 words =
= Example: =
= Now LeftDecodeDataIn[0]=0xff,DecodeOutPointer=0, =
= after you call ADPCM_Encode(LeftChannel), =
= then LeftDecodeDataOut[0]=0xfff4, LeftDecodeDataOut[1]=0xffd8 =
===============================================================================================*/
void ADPCM_Decode (unsigned char LeftRight)
{
unsigned char i;
short step;
short index;
short valpre;
short delta;
unsigned char sign;
short vpdiff;
unsigned char inbuffer;
if (LeftRight==LeftChannel)
{
valpre=LeftDecodePreVal;
index=LeftDecodeIndex;
inbuffer=LeftDecodeDataIn[DecodeOutPointer];
}
else
{
valpre=RightDecodePreVal;
index=RightDecodeIndex;
inbuffer=RightDecodeDataIn[DecodeOutPointer];
}
step = stepsizeTable[index];
for (i=0;i<2;i++)
{
// Step 1 --- get the delta value and compute next index
if (i==0)
{
delta=(inbuffer>>4)&0x0f;
}
else
{
delta=inbuffer&0x0f;
}
// Step2 --- Find new index value (for later)
index += indexTable[delta];
if (index<0)
{
index = 0;
}
else if (index>88)
{
index = 88;
}
// Step 3 --- Separate sign and magnitude
sign = delta & 8;
delta = delta & 7;
// Step 4 --- update output value
/*
if (0)
{
vpdiff = (delta*step)>>2;
}
else
{*/
vpdiff = 0;
if (delta&4)
{
vpdiff = (step<<2);
}
if (delta&2)
{
vpdiff += (step<<1);
}
if (delta&1)
{
vpdiff += step;
}
vpdiff >>=2;
//}
if (sign) valpre -= vpdiff;
else valpre += vpdiff;
// Step 5 --- clamp output value
if (valpre>32767) valpre = 32767;
else if (valpre<-32768) valpre = -32768;
// Step 6 --- Update step value
step = stepsizeTable[index];
// Step 7 --- Output value
if (LeftRight==LeftChannel)
{
LeftDecodeDataOut[i]=valpre;
LeftDecodePreVal=valpre;
LeftDecodeIndex=index;
}
else
{
RightDecodeDataOut[i]=valpre;
RightDecodePreVal=valpre;
RightDecodeIndex=index;
}
}
}
/*==========================================================================================
You can test the result with the follow subroutine
===========================================================================================*/
void ADPCM_TEST (void)
{
EncodeOutPointer=0;
LeftEncodeDataIn[0]=0xfd26;
LeftEncodeDataIn[1]=0xfc6a;
ADPCM_Encode(LeftChannel);
// ===> here you will get the compressed data in LeftEncodeDataOut[EncodeOutPointer]=0xff
//EncodeOutPointer++;
LeftEncodeDataIn[0]=0xfca5;
LeftEncodeDataIn[1]=0x04dd;
ADPCM_Encode(LeftChannel);
// ===> here you will get the compressed data in LeftEncodeDataOut[EncodeOutPointer]=0xf7
EncodeOutPointer++;
LeftEncodeDataIn[0]=0xfe77;
LeftEncodeDataIn[1]=0xfdfa;
ADPCM_Encode(LeftChannel);
// ===> here you will get the compressed data in LeftEncodeDataOut[EncodeOutPointer]=0xfb
DecodeOutPointer=0;
LeftDecodeDataIn[0]=LeftEncodeDataOut[0];
ADPCM_Decode(LeftChannel);
// ===> here you will get the unpressed data in LeftDecodeDataOut[DecodeOutPointer]=0xfff4 0xffd8
DecodeOutPointer++;
//LeftDecodeDataIn[1]=LeftEncodeDataOut[1];
LeftDecodeDataIn[0]=LeftEncodeDataOut[1];
ADPCM_Decode(LeftChannel);
// ===> here you will get the unpressed data in LeftDecodeDataOut[DecodeOutPointer]=0xff9d 0x001c
DecodeOutPointer++;
LeftDecodeDataIn[2]=LeftEncodeDataOut[2];
ADPCM_Decode(LeftChannel);
// ===> here you will get the unpressed data in LeftDecodeDataOut[DecodeOutPointer]=0xff0a 0xfe0e
}
void main()
{
FILE *fd1;
FILE *fd2;
short buf[1024];
short dabuf[1024];
int cnt = 0;
int leftpt = 0;
int leftdapt = 0;
int i = 0;
int uu = 0;
char enoutL = 0;
char enoutR = 0;
short deout1L = 0,deout2L = 0;
short deout1R = 0,deout2R = 0;
int decodeL_in = 0;
int decodeR_in = 0;
fd1 = fopen("e:\\PUNCH.wav","rb+");
fd2 = fopen("e:\\test33.wav","wb+");
fread( buf, 1, 58, fd1);
fwrite(buf,1,58,fd2);
//fclose(fd2);
ADPCM_TEST();
//EncodeOutPointer = 0;
while((cnt = fread( buf, 1, 1024, fd1)) != 0)
{
EncodeOutPointer = 0;
while(i < cnt/4)
{
//左声道压
EncodeOutPointer = 0;
LeftEncodeDataIn[0]= buf[leftpt];
LeftEncodeDataIn[1]= buf[leftpt + 2];
ADPCM_Encode(LeftChannel);
// ===> here you will get the compressed data in LeftEncodeDataOut[EncodeOutPointer]=0xff
//解压
DecodeOutPointer = 0;
LeftDecodeDataIn[decodeL_in++] = LeftEncodeDataOut[0];
ADPCM_Decode(LeftChannel);
//写入另一个文件
dabuf[leftdapt] = LeftDecodeDataOut[0];
dabuf[leftdapt + 2] = LeftDecodeDataOut[1];
//
//右声道亚
EncodeOutPointer = 0;
RightEncodeDataIn[0]= buf[leftpt + 1];
RightEncodeDataIn[1]= buf[leftpt + 3];
ADPCM_Encode(RightChannel);
// ===> here you will get the compressed data in LeftEncodeDataOut[EncodeOutPointer]=0xff
//解压
DecodeOutPointer = 0;
RightDecodeDataIn[decodeR_in++] = RightEncodeDataOut[0];
ADPCM_Decode(RightChannel);
//写入另一个文件
dabuf[leftdapt + 1] = RightDecodeDataOut[0];
dabuf[leftdapt + 3] = RightDecodeDataOut[1];
leftpt += 4;
leftdapt += 4;
i++;
}
fwrite(dabuf,2,512,fd2);
}
fclose(fd1);
fclose(fd2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -