44100_s16le_2
48000_f32le_2
48000_s32le_1
44100_s16le_2
相互轉(zhuǎn)換
void FFmpegs::resampleAudio(const char *inFilename,
int inSampleRate,
AVSampleFormat inSampleFmt,
int inChLayout,
const char *outFilename,
int outSampleRate,
AVSampleFormat outSampleFmt,
int outChLayout) {
// 文件名
QFile inFile(inFilename);
QFile outFile(outFilename);
// 輸入緩沖區(qū)
// 指向緩沖區(qū)的指針
uint8_t **inData = nullptr;
// 緩沖區(qū)的大小
int inLinesize = 0;
// 聲道數(shù)
int inChs = av_get_channel_layout_nb_channels(inChLayout);
// 一個樣本的大小
int inBytesPerSample = inChs * av_get_bytes_per_sample(inSampleFmt);
// 緩沖區(qū)的樣本數(shù)量
int inSamples = 1024;
// 讀取文件數(shù)據(jù)的大小
int len = 0;
// 輸出緩沖區(qū)
// 指向緩沖區(qū)的指針
uint8_t **outData = nullptr;
// 緩沖區(qū)的大小
int outLinesize = 0;
// 聲道數(shù)
int outChs = av_get_channel_layout_nb_channels(outChLayout);
// 一個樣本的大小
int outBytesPerSample = outChs * av_get_bytes_per_sample(outSampleFmt);
// 緩沖區(qū)的樣本數(shù)量
int outSamples = av_rescale_rnd(outSampleRate, inSamples, inSampleRate, AV_ROUND_UP);
qDebug() << "輸入緩沖區(qū)" << inSampleRate << inSamples;
qDebug() << "輸出緩沖區(qū)" << outSampleRate << outSamples;
// 返回結(jié)果
int ret = 0;
// 創(chuàng)建重采樣上下文
SwrContext *ctx = swr_alloc_set_opts(nullptr,
// 輸出參數(shù)
outChLayout, outSampleFmt, outSampleRate,
// 輸入?yún)?shù)
inChLayout, inSampleFmt, inSampleRate,
0, nullptr);
if (!ctx) {
qDebug() << "swr_alloc_set_opts error";
goto end;
}
// 初始化重采樣上下文
ret = swr_init(ctx);
if (ret < 0) {
ERROR_BUF(ret);
qDebug() << "swr_init error:" << errbuf;
goto end;
}
// 創(chuàng)建輸入緩沖區(qū)
ret = av_samples_alloc_array_and_samples(
&inData,
&inLinesize,
inChs,
inSamples,
inSampleFmt,
1);
if (ret < 0) {
ERROR_BUF(ret);
qDebug() << "av_samples_alloc_array_and_samples error:" << errbuf;
goto end;
}
// 創(chuàng)建輸出緩沖區(qū)
ret = av_samples_alloc_array_and_samples(
&outData,
&outLinesize,
outChs,
outSamples,
outSampleFmt,
1);
if (ret < 0) {
ERROR_BUF(ret);
qDebug() << "av_samples_alloc_array_and_samples error:" << errbuf;
goto end;
}
// 打開文件
if (!inFile.open(QFile::ReadOnly)) {
qDebug() << "file open error:" << inFilename;
goto end;
}
if (!outFile.open(QFile::WriteOnly)) {
qDebug() << "file open error:" << outFilename;
goto end;
}
// 讀取文件數(shù)據(jù)
// inData[0] == *inData
while ((len = inFile.read((char *) inData[0], inLinesize)) > 0) {
// 讀取的樣本數(shù)量
inSamples = len / inBytesPerSample;
// 重采樣(返回值轉(zhuǎn)換后的樣本數(shù)量)
ret = swr_convert(ctx,
outData, outSamples,
(const uint8_t **) inData, inSamples
);
if (ret < 0) {
ERROR_BUF(ret);
qDebug() << "swr_convert error:" << errbuf;
goto end;
}
// 將轉(zhuǎn)換后的數(shù)據(jù)寫入到輸出文件中
// outData[0] == *outData
outFile.write((char *) outData[0], ret * outBytesPerSample);
}
// 檢查一下輸出緩沖區(qū)是否還有殘留的樣本(已經(jīng)重采樣過的,轉(zhuǎn)換過的)
while ((ret = swr_convert(ctx,
outData, outSamples,
nullptr, 0)) > 0) {
outFile.write((char *) outData[0], ret * outBytesPerSample);
}
end:
// 釋放資源
// 關(guān)閉文件
inFile.close();
outFile.close();
// 釋放輸入緩沖區(qū)
if (inData) {
av_freep(&inData[0]);
}
av_freep(&inData);
// 釋放輸出緩沖區(qū)
if (outData) {
av_freep(&outData[0]);
}
av_freep(&outData);
// 釋放重采樣上下文
swr_free(&ctx);
}