您的位置:首页 > 运维架构

AMR 编码 PCM & WAV (opencore-amr-0.1.5)

2017-08-01 15:09 239 查看
AMR编码基于第三方opencore-amr-0.1.5库

支持PCM2AMR,WAV2AMR

test目录下:pcm2amr.c pcm2amr.c,linux环境下 调试通过,准备移植到安卓手机

资源下载链接:http://download.csdn.net/detail/yuanchunsi/9917689

//--------------------------------------------------------------------------------------------------------------------------//

pcm2amr.h代码如下:

#ifndef pcm2amr_h

#define pcm2amr_h

#include <stdio.h>

#include <stdint.h>

#include <interf_enc.h>

#include <unistd.h>

#include <stdlib.h>

//#include "wavreader.h"

#define AMR_MAGIC_NUMBER "#!AMR\n"

 

#define PCM_FRAME_SIZE 160 // 8khz 8000*0.02=160

#define MAX_AMR_FRAME_SIZE 32

#define AMR_FRAME_COUNT_PER_SECOND 50

//int amrEncodeMode[] = {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200}; // amr 编码方式

 

typedef struct

{

         char chChunkID[4];

         int nChunkSize;

}XCHUNKHEADER;

 

typedef struct

{

         short nFormatTag;

         short nChannels;

         int nSamplesPerSec;

         int nAvgBytesPerSec;

         short nBlockAlign;

         short nBitsPerSample;

}WAVEFORMAT;

 

typedef struct

{

         short nFormatTag;

         short nChannels;

         int nSamplesPerSec;

         int nAvgBytesPerSec;

         short nBlockAlign;

         short nBitsPerSample;

         short nExSize;

}WAVEFORMATX;

 

typedef struct

{

         char chRiffID[4];

         int nRiffSize;

         char chRiffFormat[4];

}RIFFHEADER;

 

typedef struct

{

         char chFmtID[4];

         int nFmtSize;

         WAVEFORMAT wf;

}FMTBLOCK;

 

// WAVE音频采样频率是8khz

// 音频样本单元数 = 8000*0.02 = 160 (由采样频率决定)

// 声道数 1 : 160

//        2 : 160*2 = 320

// bps决定样本(sample)大小

// bps = 8 --> 8位 unsigned char

//       16 --> 16位 unsigned short

//int EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample);

 

// 将AMR文件解码成WAVE文件

//int DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename);

 

#endif

pcm2amr.c代码如下:

#include "pcm2amr.h"

// 从WAVE文件中跳过WAVE文件头,直接到PCM音频数据

void SkipToPCMAudioData(FILE* fpwave)

{

  RIFFHEADER riff;

  FMTBLOCK fmt;

  XCHUNKHEADER chunk;

  WAVEFORMATX wfx;

  int bDataBlock = 0;

  // 1. 读RIFF头

  fread(&riff, 1, sizeof(RIFFHEADER), fpwave);

  // 2. 读FMT块 - 如果 fmt.nFmtSize>16 说明需要还有一个附属大小没有读

  fread(&chunk, 1, sizeof(XCHUNKHEADER), fpwave);

  if ( chunk.nChunkSize>16 )

  {

    fread(&wfx, 1, sizeof(WAVEFORMATX), fpwave);

  }

  else

  {

    memcpy(fmt.chFmtID, chunk.chChunkID, 4);

    fmt.nFmtSize = chunk.nChunkSize;

    fread(&fmt.wf, 1, sizeof(WAVEFORMAT), fpwave);

  }

  // 3.转到data块 - 有些还有fact块等。

  while(!bDataBlock)

  {

    fread(&chunk, 1, sizeof(XCHUNKHEADER), fpwave);

    if ( !memcmp(chunk.chChunkID, "data", 4) )

    {

      bDataBlock = 1;

      break;

    }

    // 因为这个不是data块,就跳过块数据

    fseek(fpwave, chunk.nChunkSize, SEEK_CUR);

  }

 

}

// 从WAVE文件读一个完整的PCM音频帧

// 返回值: 0-错误 >0: 完整帧大小

int ReadPCMFrame(short speech[], FILE* fpwave, int nChannels, int nBitsPerSample)

{

  int nRead = 0;

  int x = 0, y=0;

  unsigned short ush1=0, ush2=0, ush=0;

  // 原始PCM音频帧数据

  unsigned char pcmFrame_8b1[PCM_FRAME_SIZE];

  unsigned char pcmFrame_8b2[PCM_FRAME_SIZE<<1];

  unsigned short pcmFrame_16b1[PCM_FRAME_SIZE];

  unsigned short pcmFrame_16b2[PCM_FRAME_SIZE<<1];

  if (nBitsPerSample==8 && nChannels==1)

  {

    nRead = fread(pcmFrame_8b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave);

    for(x=0; x<PCM_FRAME_SIZE; x++)

    {

      speech[x] =(short)((short)pcmFrame_8b1[x] << 7);

    }

  }

  else

    if (nBitsPerSample==8 && nChannels==2)

    {

      nRead = fread(pcmFrame_8b2, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave);

      for( x=0, y=0; y<PCM_FRAME_SIZE; y++,x+=2 )

      {

        // 1 - 取两个声道之左声道

        speech[y] =(short)((short)pcmFrame_8b2[x+0] << 7);

        // 2 - 取两个声道之右声道

        //speech[y] =(short)((short)pcmFrame_8b2[x+1] << 7);

        // 3 - 取两个声道的平均值

        //ush1 = (short)pcmFrame_8b2[x+0];

        //ush2 = (short)pcmFrame_8b2[x+1];

        //ush = (ush1 + ush2) >> 1;

        //speech[y] = (short)((short)ush << 7);

      }

    }

    else

      if (nBitsPerSample==16 && nChannels==1)

      {

        nRead = fread(pcmFrame_16b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave);

        if (nRead == PCM_FRAME_SIZE*nChannels) {

          for(x=0; x<PCM_FRAME_SIZE; x++)

          {

            speech[x] = (short)pcmFrame_16b1[x+0];

          }

        }

      }

      else

        if (nBitsPerSample==16 && nChannels==2)

        {

          nRead = fread(pcmFrame_16b2, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave);

          for( x=0, y=0; y<PCM_FRAME_SIZE; y++,x+=2 )

          {

            //speech[y] = (short)pcmFrame_16b2[x+0];

            speech[y] = (short)((int)((int)pcmFrame_16b2[x+0] + (int)pcmFrame_16b2[x+1])) >> 1;

          }

        }

  if (nRead != PCM_FRAME_SIZE*nChannels)  return -1;

  printf("ReadPCMFrame done\n");

  return nRead;

}

// WAVE音频采样频率是8khz

// 音频样本单元数 = 8000*0.02 = 160 (由采样频率决定)

// 声道数 1 : 160

//        2 : 160*2 = 320

// bps决定样本(sample)大小

// bps = 8 --> 8位 unsigned char

//       16 --> 16位 unsigned short

//int EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample)

int main ()

{

  FILE* fpwave;

  FILE* fpamr;

  /* input speech vector */

  short speech[160];

  /* counters */

  int byte_counter, frames = 0, bytes = 0;

  /* pointer to encoder state structure */

  int *enstate;

  /* requested mode */

  enum Mode req_mode = MR122;

  int dtx = 0;

  /* bitstream filetype */

  unsigned char amrFrame[MAX_AMR_FRAME_SIZE];

#if 0

//WAV和PCM数据区别仅仅是wav多了数据头

  fpwave = fopen("./input.wav", "rb");

#else

  fpwave = fopen("./audio.pcm", "rb");

#endif

  if (fpwave == NULL)

  {

    return 0;

  }

  // 创建并初始化amr文件

  fpamr = fopen("./out.amr", "wb");

  if (fpamr == NULL)

  {

    fclose(fpwave);

    return 0;

  }

  /* write magic number to indicate single channel AMR file storage format */

  bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr);

#if 0

  /* skip to pcm audio data*/

  //跳过WAV数据包头既是PCM原始数据

  SkipToPCMAudioData(fpwave);

#endif

  enstate = Encoder_Interface_init(dtx);

  while(1)

  {

    // read one pcm frame

    //if (!ReadPCMFrame(speech, fpwave, nChannels, nBitsPerSample)) break;

    if (-1 == ReadPCMFrame(speech, fpwave, 1, 16)) {

      //printf("ReadPCMFrame failed\n");

      break;

    }

    frames++;

    /* call encoder */

    byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, amrFrame, 0);

    printf("byte_counter == %d\n",byte_counter);

    bytes += byte_counter;

    fwrite(amrFrame, sizeof (unsigned char), byte_counter, fpamr );

  }

  Encoder_Interface_exit(enstate);

  fclose(fpamr);

  fclose(fpwave);

  return frames;

}

//--------------------------------------------------------------------------------------------------------------------------//
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: