⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adpcm.c

📁 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 + -