二、给个英文参考网址吧
这两个讲的很详细,请仔细阅读!通过阅读我发现细节在与adpcm格式的wav文件的block的特点,每一个block包含header和data两部分,
Typedefstruct{
shortsample0;//block中第一个采样值(未压缩)
BYTEindex;//上一个block最后一个index,第一个block的index=0;
BYTEreserved;//尚未使用
}MonoBlockHeader
关键是我们要抓住每一个block的header里面的信息,即sample0,运算的时候注意运用!
三、还是给个代码吧,多的也不说了!
1、adpcm.c文件代码
#include"adpcm.h"
/*IntelADPCMstepvariationtable*/
staticintindexTable[16]={
-1,-1,-1,-1,2,4,6,8,
-1,-1,-1,-1,2,4,6,8,
};
staticintstepsizeTable[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
};
voidadpcm_decoder(char*inbuff,char*outbuff,intlen_of_in,structadpcm_state*state)
{
inti=0,j=0;
chartmp_data;
structadpcm_state*tmp_state=state;
longstep;/*Quantizerstepsize*/
signedlongpredsample;/*OutputofADPCMpredictor*/
signedlongdiffq;/*Dequantizedpredicteddifference*/
intindex;/*Indexintostepsizetable*/
intSamp;
unsignedcharSampH,SampL;
unsignedcharinCode;
/*Restorepreviousvaluesofpredictedsampleandquantizerstep
sizeindex
*/
predsample=state->valprev;
index=state->index;
for(i=0;i
{
tmp_data=inbuff[i/2];
if(i%2)
inCode=(tmp_data&0xf0)>>4;
else
inCode=tmp_data&0x0f;
step=stepsizeTable[index];
/*InversequantizetheADPCMcodeintoapredicteddifference
usingthequantizerstepsize
*/
diffq=step>>3;
if(inCode&4)
diffq+=step;
if(inCode&2)
diffq+=step>>1;
if(inCode&1)
diffq+=step>>2;
/*Fixedpredictorcomputesnewpredictedsamplebyaddingthe
oldpredictedsampletopredicteddifference
*/
if(inCode&8)
predsample-=diffq;
else
predsample+=diffq;
/*Checkforoverflowofthenewpredictedsample
*/
if(predsample>32767)
predsample=32767;
elseif(predsample
predsample=-32768;
/*Findnewquantizerstepsizeindexbyaddingtheoldindex
toatablelookupusingtheADPCMcode
*/
index+=indexTable[inCode];
/*Checkforoverflowofthenewquantizerstepsizeindex
*/
if(index<0)
index=0;
if(index>88)
index=88;
/*ReturnthenewADPCMcode*/
Samp=predsample;
if(Samp>=0)
{
SampH=Samp/256;
SampL=Samp-256*SampH;
}
else
{
Samp=32768+Samp;
SampH=Samp/256;
SampL=Samp-256*SampH;
SampH+=0x80;
}
outbuff[j++]=SampL;
outbuff[j++]=SampH;
}
/*Savethepredictedsampleandquantizerstepsizeindexfor
nextiteration
*/
state->valprev=(short)predsample;
state->index=(char)index;
}
2、adpcm.h文件代码
#ifndefADPCM_H
#defineADPCM_H
#ifdef__cplusplus
extern"C"{
#endif
structadpcm_state{
shortvalprev;/*Previousoutputvalue*/
charindex;/*Indexintostepsizetable*/
};
voidadpcm_decoder(char*inbuff,char*outbuff,intlen_of_in,structadpcm_state*state);
#ifdef__cplusplus
}/*extern"C"*/
#endif
#endif/*ADPCM_H*/
3、main.c文件代码
#include"stdio.h"
#include"stdlib.h"
#include"adpcm.h"
#defineCFG_BlkSize256
charch[CFG_BlkSize];//用来存储wav文件的头信息
charsavedata[CFG_BlkSize*4];
unsignedcharRiffHeader[]={
'R','I','F','F',//ChunkID(RIFF)
0x70,0x70,0x70,0x70,//Chunkpayloadsize(calculateafterrec!)
'W','A','V','E',//RIFFresourceformattype
'f','m','t','',//ChunkID(fmt)
0x10,0x00,0x00,0x00,//Chunkpayloadsize(0x14=20bytes)
0x01,0x00,//FormatTag()
0x01,0x00,//Channels(1)
0x40,0x1f,0x00,0x00,//SampleRate,=16.0kHz
0x80,0x3e,0x00,0x00,//Byterate32.0K
0x02,0x00,//BlockAlign==NumChannels*BitsPerSample/8
0x10,0x00//BitsPerSample
};
unsignedcharRIFFHeader504[]={
'd','a','t','a',//ChunkID(data)
0x70,0x70,0x70,0x70//Chunkpayloadsize(calculateafterrec!)
};
/****************************************************************
函数名称:main
功能描述:
输入参数:none
输出参数:none
****************************************************************/
voidmain(void)
{
FILE*fpi,*fpo;
unsignedlongiLen,temp;
structadpcm_stateADPCMstate;
unsignedlongi=0;
unsignedlongj;
fpi=fopen("f:\\lk\\test.adpcm","rb");//为读,打开一个wav文件
if((fpi=fopen("f:\\lk\\test.adpcm","rb"))==NULL)//若打开文件失败,退出
{
printf("can'topenthisfile\n");
printf("\nreaderror!\n");
printf("\n%d\n",i);
exit(0);
}
fseek(fpi,0,SEEK_END);
iLen=ftell(fpi);
printf("\n======================================================\n");
printf("\n========================%d========================\n",iLen);
printf("\n======================================================\n");
if((iLen-44)%CFG_BlkSize)
iLen=(iLen-44)/CFG_BlkSize+1;
else
iLen=(iLen-44)/CFG_BlkSize;
fpo=fopen("f:\\lk\\new.pcm","rb+");//为写,打开一个wav文件
if((fpo=fopen("f:\\lk\\new.pcm","rb+"))==NULL)//若打开文件失败,退出
{
printf("can'topenthisfile\n");
printf("\nwriteerror!\n");
exit(0);
}
fseek(fpo,0,SEEK_SET);
fwrite(RiffHeader,sizeof(RiffHeader),1,fpo);//写文件riff
fwrite(RIFFHeader504,sizeof(RIFFHeader504),1,fpo);//写data块头
while(i
{
fseek(fpi,48+i*CFG_BlkSize,SEEK_SET);
fread(ch,1,CFG_BlkSize,fpi);
printf("\n======================================================\n");
for(j=0;j<100;j++)
printf("|%d|",ch[j]);
printf("\n======================================================\n");
添加读取BlockHeader部分开始
if(i==0)
{
ADPCMstate.index=0;//第一个block的index为0当前的BlockSize为256即采样点数为(256-4)*2+1=505
}
else
{
ADPCMstate.index=ch[2];
}
ADPCMstate.valprev=(short)ch[0]+((short)(ch[1]))*256;//每一个block里面帧头有一个未压缩的数据存储时先低后高
savedata[0]=ch[0];//存储第一个没有被压缩的数据
savedata[1]=ch[1];//存储第一个没有被压缩的数据
添加读取BlockHeader部分结束
adpcm_decoder(&ch[4],&savedata[2],CFG_BlkSize-4,&ADPCMstate);//解码出来了(256-4)*4个字节
temp=(CFG_BlkSize-4)*4+2;
fseek(fpo,44+i*temp,SEEK_SET);//开始写声音数据
fwrite(savedata,temp,1,fpo);
i++;
}
temp*=i;
RiffHeader[4]=(unsignedchar)((40+temp)&0x000000ff);
RiffHeader[5]=(unsignedchar)(((40+temp)&0x0000ff00)>>8);
RiffHeader[6]=(unsignedchar)(((40+temp)&0x00ff0000)>>16);
RiffHeader[7]=(unsignedchar)(((40+temp)&0xff000000)>>24);
fseek(fpo,4,SEEK_SET);
fwrite(&RiffHeader[4],4,1,fpo);
RiffHeader[40]=(unsignedchar)(temp&0x000000ff);
RiffHeader[41]=(unsignedchar)((temp&0x0000ff00)>>8);
RiffHeader[42]=(unsignedchar)((temp&0x00ff0000)>>16);
RiffHeader[43]=(unsignedchar)((temp&0xff000000)>>24);
fseek(fpo,40,SEEK_SET);
fwrite(&RiffHeader[40],4,1,fpo);
fclose(fpi);
fclose(fpo);
printf("\n==========================OK!=========================\n");
}
四、以上是给出的代码,绝对管用,读者在实验时候请在vc++6.0环境下建立工程,实验时候请在f:\\lk\\下放置一个adpcm格式的文件和一个空的pcm格式文件,当然了这个pcm和adpcm其实都是wav格式的,试验者可以随意命名格式,我为了区分才这样命名后缀的,希望我总结的能够读者带来帮助,谢谢您的阅读!
如果觉得《java pcm转adpcm_音频编码(PCM ADPCM WAVE文件)》对你有帮助,请点赞、收藏,并留下你的观点哦!