1. 程式人生 > >音訊重取樣

音訊重取樣

取樣率轉換的開原始碼框架有resample、libresamplesndfile-resamplelibresample4j等。

libresample andsndfile-resample (fromlibsamplerate) (in the Planet CCRMA Distribution).

libsoxr, the SoX resampler libraryssrc (from Shibatch)There is a project combining ssrc andsoxNew in 2016 is a Python (Cython) implementation:resampy
Brick (onGithub).Smarc, available as a command-line program or C library.The resample software package contains free sampling-rate conversion and filter design utilities written in C. Erik de Castro Lopo's "SecretRabbitCode" libsamplerate

libresample based on `resample-1.7P

libresample4j is a 

Java port oflibresample.

Open Source Audio Library Project (OSALP) contains a C++ class based onresample.The Speex speech coder/decoder.More at another large list of implementations and their relative performance. 文字重點介紹libresample的使用方法。 轉換器型別 enum
{
 SRC_SINC_BEST_QUALITY  = 0,
 SRC_SINC_MEDIUM_QUALITY  = 1,
 SRC_SINC_FASTEST   = 2,
 SRC_ZERO_ORDER_HOLD   = 3,//零階取樣和保持器
 SRC_LINEAR     = 4,//插值
} ;
//簡單轉換函式
int src_simple (SRC_DATA *data, int converter_type, int channels) ;
具體參考samplerate.h標頭檔案。 呼叫例項: int convert2(unsigned char* bufferAAC, size_t buf_sizeAAC, unsigned char* bufferPCM, size_t & buf_sizePCM)
{
 unsigned char* pcm_data = NULL;
 if (!m_bNeAACDecInit)
 {
  //initialize decoder
  NeAACDecInit(decoder, bufferAAC, buf_sizeAAC, &samplerate, &channels);
  printf("samplerate %d, channels %d\n", samplerate, channels);
  m_bNeAACDecInit = true;
 }
 //decode ADTS frame
 pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, bufferAAC, buf_sizeAAC);
 if (frame_info.error > 0)
 {
  printf("%s\n", NeAACDecGetErrorMessage(frame_info.error));
  return -1;
 }
 else if (pcm_data && frame_info.samples > 0)
 {
  printf("frame info: bytesconsumed %d, channels %d, header_type %d\
             object_type %d, samples %d, samplerate %d\n",
          frame_info.bytesconsumed,
          frame_info.channels, frame_info.header_type,
          frame_info.object_type, frame_info.samples,
          frame_info.samplerate);
  buf_sizePCM = frame_info.samples * frame_info.channels;
  memcpy(bufferPCM,pcm_data,buf_sizePCM);
  //取樣率變成8000HZ
  float in[4096] = { 0 };
  float out[4096] = { 0 };
  int j = 0;
  for (j = 0; j < 4096 && j < buf_sizePCM; j++)
  {
   in[j] = pcm_data[j];
  }
  SRC_DATA dataResample;
  dataResample.data_in = in;
  dataResample.data_out = out;
  dataResample.input_frames = frame_info.samples;
  dataResample.output_frames = frame_info.samples;
  dataResample.src_ratio =  8000.0/frame_info.samplerate;
int nRetResample = 0;
//在測試過程中發現,如果是frame_info.samplerate%8000是非整數倍,用SRC_LINEAR方法轉換取樣率的話,效果很差。
if(frame_info.samplerate%8000 == 0)
{
nRetResample = src_simple(&dataResample,SRC_LINEAR, frame_info.channels);
}
else
{
nRetResample = src_simple(&dataResample,SRC_ZERO_ORDER_HOLD, frame_info.channels);
}


  /*
  buf_sizePCM = dataResample.output_frames_gen * frame_info.channels;
  for (j = 0; j < 4096 && j < buf_sizePCM; j++)
  {
   bufferPCM[j] = Float2UChar(dataResample.data_out[j]);
  }
  */
  //聲道變成單聲道
  buf_sizePCM = dataResample.output_frames_gen * frame_info.channels;
  if(frame_info.channels == 2)
  {
   //從雙聲道的資料中提取單通道 
   int i = 0;
   for (i = 0, j = 0; i<4096 && i<buf_sizePCM && j<2048; i += 4, j += 2)
   {
    bufferPCM[j] = Float2UChar(out[i]);
    bufferPCM[j + 1] = Float2UChar(out[i + 1]);
   }
   buf_sizePCM = buf_sizePCM/2;
  }
  else
  {
   memcpy(bufferPCM,out,buf_sizePCM);
  }
  /*
  //聲道變成單聲道
  if(frame_info.channels == 2)
  {
   //從雙聲道的資料中提取單通道 
   for (int i = 0, j = 0; i<4096 && i<buf_sizePCM && j<2048; i += 4, j += 2)
   {
    bufferPCM[j] = pcm_data[i];
    bufferPCM[j + 1] = pcm_data[i + 1];
   }
   buf_sizePCM = buf_sizePCM/2;
   memcpy(bufferPCM,bufferPCM,buf_sizePCM);
  }
  else
  {
   memcpy(bufferPCM,pcm_data,buf_sizePCM);
  }
  */
  return 0;
 }
 return -1;
}
resample-1.7:http://www-ccrma.stanford.edu/~jos/resample/