音訊重取樣
阿新 • • 發佈:2019-02-04
取樣率轉換的開原始碼框架有resample、libresample、sndfile-resample、libresample4j
等。
libresample andsndfile-resample
(fromlibsamplerate
)
(in the Planet CCRMA Distribution).
libsoxr
, the SoX resampler libraryssrc
(from Shibatch)There is a project combining ssrc
andsox
New in 2016 is a Python (Cython) implementation:resampylibsamplerate
libresample
based on
`resample-1.7P
libresample4j
is a Java port
oflibresample
.
resample
.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/