QT開發(fā) pcm轉(zhuǎn)wav

// WAV文件頭(44字節(jié))
typedef struct {
    // RIFF chunk的id
    uint8_t riffChunkId[4] = {'R', 'I', 'F', 'F'};
    // RIFF chunk的data大小,即文件總長度減去8字節(jié)
    uint32_t riffChunkDataSize;

    // "WAVE"
    uint8_t format[4] = {'W', 'A', 'V', 'E'};

    /* fmt chunk */
    // fmt chunk的id
    uint8_t fmtChunkId[4] = {'f', 'm', 't', ' '};
    // fmt chunk的data大?。捍鎯CM數(shù)據(jù)時,是16
    uint32_t fmtChunkDataSize = 16;
    // 音頻編碼,1表示PCM,3表示Floating Point
    uint16_t audioFormat = AUDIO_FORMAT_PCM;
    // 聲道數(shù)
    uint16_t numChannels;
    // 采樣率
    uint32_t sampleRate;
    // 字節(jié)率 = sampleRate * blockAlign
    uint32_t byteRate;
    // 一個樣本的字節(jié)數(shù) = bitsPerSample * numChannels >> 3
    uint16_t blockAlign;
    // 位深度
    uint16_t bitsPerSample;

    /* data chunk */
    // data chunk的id
    uint8_t dataChunkId[4] = {'d', 'a', 't', 'a'};
    // data chunk的data大?。阂纛l數(shù)據(jù)的總長度,即文件總長度減去文件頭的長度(一般是44)
    uint32_t dataChunkDataSize;
} WAVHeader;

void FFmpegs::pcm2wav(WAVHeader &header,
                      const char *pcmFilename,
                      const char *wavFilename) {
    header.blockAlign = header.bitsPerSample * header.numChannels >> 3;
    header.byteRate = header.sampleRate * header.blockAlign;

    // 打開pcm文件
    QFile pcmFile(pcmFilename);
    if (!pcmFile.open(QFile::ReadOnly)) {
        qDebug() << "文件打開失敗" << pcmFilename;
        return;
    }
    header.dataChunkDataSize = pcmFile.size();
    header.riffChunkDataSize = header.dataChunkDataSize
                               + sizeof (WAVHeader)
                               - sizeof (header.riffChunkId)
                               - sizeof (header.riffChunkDataSize);

    // 打開wav文件
    QFile wavFile(wavFilename);
    if (!wavFile.open(QFile::WriteOnly)) {
        qDebug() << "文件打開失敗" << wavFilename;

        pcmFile.close();
        return;
    }

    // 寫入頭部
    wavFile.write((const char *) &header, sizeof (WAVHeader));

    // 寫入pcm數(shù)據(jù)
    char buf[1024];
    int size;
    while ((size = pcmFile.read(buf, sizeof (buf))) > 0) {
        wavFile.write(buf, size);
    }

    // 關(guān)閉文件
    pcmFile.close();
    wavFile.close();
}
 // 獲取輸入格式對象
    AVInputFormat *fmt = av_find_input_format(FMT_NAME);
    if (!fmt) {
        qDebug() << "獲取輸入格式對象失敗" << FMT_NAME;
        return;
    }

    // 格式上下文(將來可以利用上下文操作設備)
    AVFormatContext *ctx = nullptr;
    // 打開設備
    int ret = avformat_open_input(&ctx, DEVICE_NAME, fmt, nullptr);
    if (ret < 0) {
        char errbuf[1024];
        av_strerror(ret, errbuf, sizeof (errbuf));
        qDebug() << "打開設備失敗" << errbuf;
        return;
    }
    // 文件名
    QString filename = FILEPATH;
    filename += QDateTime::currentDateTime().toString("MM_dd_HH_mm_ss");
    QString wavFilename = filename;
    filename += ".pcm";
    wavFilename += ".wav";
    QFile file(filename);

    // 打開文件
    // WriteOnly:只寫模式。如果文件不存在,就創(chuàng)建文件;如果文件存在,就會清空文件內(nèi)容
    if (!file.open(QFile::WriteOnly)) {
        qDebug() << "文件打開失敗" << filename;

        // 關(guān)閉設備
        avformat_close_input(&ctx);
        return;
    }

    // 數(shù)據(jù)包
    AVPacket pkt;
    while (!isInterruptionRequested()) {
        // 不斷采集數(shù)據(jù)
        ret = av_read_frame(ctx, &pkt);

        if (ret == 0) { // 讀取成功
            // 將數(shù)據(jù)寫入文件
            file.write((const char *) pkt.data, pkt.size);
        } else if (ret == AVERROR(EAGAIN)) { // 資源臨時不可用
            continue;
        } else { // 其他錯誤
            char errbuf[1024];
            av_strerror(ret, errbuf, sizeof (errbuf));
            qDebug() << "av_read_frame error" << errbuf << ret;
            break;
        }
    }
    // 關(guān)閉文件
    file.close();

    // 獲取輸入流
    AVStream *stream = ctx->streams[0];
    // 獲取音頻參數(shù)
    AVCodecParameters *params = stream->codecpar;

    // pcm轉(zhuǎn)wav文件
    WAVHeader header;
    header.sampleRate = params->sample_rate;
    header.bitsPerSample = av_get_bits_per_sample(params->codec_id);
    header.numChannels = params->channels;
    if (params->codec_id >= AV_CODEC_ID_PCM_F32BE) {
        header.audioFormat = AUDIO_FORMAT_FLOAT;
    }
    FFmpegs::pcm2wav(header,
                     filename.toUtf8().data(),
                     wavFilename.toUtf8().data());

    // 關(guān)閉設備
    avformat_close_input(&ctx);

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

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