QT開發(fā) 音頻重采樣

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);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容