C++实现将PCM文件转换成MP3文件

找一个C++实现将PCM文件转换成MP3文件的代码,要求转换前后播放效果没有差异,能正常的播放,要能成功转换,使用第三方库或者自己编写代码实现都行,谢谢!


#include <stdio.h>
#include <lame/lame.h>

bool convertPcmToMp3(const char* pcmFilePath, const char* mp3FilePath, int sampleRate, int channels, int bitRate) {
    FILE *pcmFile = fopen(pcmFilePath, "rb");
    if (!pcmFile) {
        return false;
    }

    FILE *mp3File = fopen(mp3FilePath, "wb");
    if (!mp3File) {
        fclose(pcmFile);
        return false;
    }

    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;

    short pcmBuffer[PCM_SIZE * channels];
    unsigned char mp3Buffer[MP3_SIZE];

    lame_t lame = lame_init();
    lame_set_num_channels(lame, channels);
    lame_set_in_samplerate(lame, sampleRate);
    lame_set_out_samplerate(lame, sampleRate);
    lame_set_brate(lame, bitRate);
    lame_set_mode(lame, channels == 1 ? MONO : STEREO);
    lame_set_quality(lame, 2);
    lame_init_params(lame);

    bool success = true;
    int readSize = 0;
    int writeSize = 0;
    do {
        readSize = fread(pcmBuffer, sizeof(short) * channels, PCM_SIZE, pcmFile);
        if (readSize != 0) {
            if (channels == 1) {
                writeSize = lame_encode_buffer(lame, pcmBuffer, NULL, readSize, mp3Buffer, MP3_SIZE);
            } else {
                writeSize = lame_encode_buffer_interleaved(lame, pcmBuffer, readSize, mp3Buffer, MP3_SIZE);
            }
            fwrite(mp3Buffer, sizeof(unsigned char), writeSize, mp3File);
        } else {
            // Flush the last bit of data.
            writeSize = lame_encode_flush(lame, mp3Buffer, MP3_SIZE);
            fwrite(mp3Buffer, sizeof(unsigned char), writeSize, mp3File);
        }
    } while (readSize != 0);

    lame_close(lame);
    fclose(pcmFile);
    fclose(mp3File);

    return success;
}

int main() {
    const char* pcmFilePath = "input.pcm";
    const char* mp3FilePath = "output.mp3";
    int sampleRate = 44100;   // 采样率(Hz)
    int channels = 2;         // 声道数(1:单声道,2:立体声)
    int bitRate = 128;        // 比特率(kbps)

    bool success = convertPcmToMp3(pcmFilePath, mp3FilePath, sampleRate, channels, bitRate);
    if (success) {
        printf("PCM to MP3 conversion completed.\n");
    } else {
        printf("Failed to convert PCM to MP3.\n");
    }

    return 0;
}

【以下回答由 GPT 生成】

问题: 如何在C++中使用第三方库将PCM文件转换为MP3文件?

解决方案:

在C++中,我们可以使用libsndfile库来处理音频文件,然后使用lame库将PCM文件转换为MP3文件。

下面是解决该问题的步骤:

步骤1: 安装libsndfile库和lame

  • 首先,需要下载并安装libsndfile库:https://www.mega-nerd.com/libsndfile/
  • 然后,下载并安装lame库:https://lame.sourceforge.io/download.php

安装完成后,确保库的路径已正确配置,以便在编译时能够正确引用。

步骤2: 包含必要的头文件

在你的C++代码中,需要包含以下头文件:

#include <sndfile.h>
#include <lame/lame.h>

步骤3: 打开PCM文件和创建MP3文件

// 打开PCM文件
SF_INFO pcmInfo;
SNDFILE* pcmFile = sf_open("input.pcm", SFM_READ, &pcmInfo);
if (!pcmFile) {
    // 处理打开PCM文件失败的情况
}

// 创建MP3文件
FILE* mp3File = fopen("output.mp3", "wb");
if (!mp3File) {
    // 处理创建MP3文件失败的情况
}

步骤4: 读取PCM数据并进行转换

constexpr int PCM_BUFFER_SIZE = 8192;
short pcmBuffer[PCM_BUFFER_SIZE];
unsigned char mp3Buffer[PCM_BUFFER_SIZE];

// 初始化lame编码器
lame_t lameEncoder = lame_init();
if (!lameEncoder) {
    // 处理初始化编码器失败的情况
}

// 配置lame编码器参数(根据需要进行调整)
lame_set_in_samplerate(lameEncoder, pcmInfo.samplerate);
lame_set_out_samplerate(lameEncoder, pcmInfo.samplerate);
lame_set_num_channels(lameEncoder, pcmInfo.channels);
lame_set_VBR(lameEncoder, vbr_default);
lame_init_params(lameEncoder);

int readCount;
do {
    // 读取PCM数据
    readCount = sf_read_short(pcmFile, pcmBuffer, PCM_BUFFER_SIZE);

    // PCM转换为MP3
    int writeCount = lame_encode_buffer_interleaved(lameEncoder, pcmBuffer, readCount, mp3Buffer, PCM_BUFFER_SIZE);

    // 将MP3数据写入文件
    fwrite(mp3Buffer, sizeof(unsigned char), writeCount, mp3File);
} while (readCount > 0);


// 刷新lame编码器并收尾工作
int writeCount = lame_encode_flush(lameEncoder, mp3Buffer, PCM_BUFFER_SIZE);
if (writeCount > 0) {
    fwrite(mp3Buffer, sizeof(unsigned char), writeCount, mp3File);
}
lame_close(lameEncoder);

步骤5: 关闭文件和释放资源

// 关闭PCM文件
sf_close(pcmFile);

// 关闭MP3文件
fclose(mp3File);

通过以上步骤,你可以使用第三方库将PCM文件转换为MP3文件。

请注意,此解决方案仅为一个示例,并未进行错误处理和完整的参数配置。在实际应用中,你可能需要根据自己的需求进行调整和优化。同时,确保在运行代码之前,正确配置库的路径以及相关依赖项。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

#include <iostream>
#include <lame/lame.h>

int main(int argc, char *argv[]) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " input.pcm output.mp3" << std::endl;
        return 1;
    }

    FILE *pcmFile = fopen(argv[1], "rb");
    if (!pcmFile) {
        std::cerr << "Error opening input PCM file" << std::endl;
        return 1;
    }

    FILE *mp3File = fopen(argv[2], "wb");
    if (!mp3File) {
        std::cerr << "Error opening output MP3 file" << std::endl;
        fclose(pcmFile);
        return 1;
    }

    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 44100);  // 设置采样率
    lame_set_num_channels(lame, 2);       // 设置通道数
    lame_set_brate(lame, 128);            // 设置比特率
    lame_set_quality(lame, 2);            // 设置质量
    lame_init_params(lame);

    const int PCM_SIZE = 8192;
    short int pcm_buffer[PCM_SIZE];
    unsigned char mp3_buffer[PCM_SIZE];

    int read, write;
    do {
        read = fread(pcm_buffer, sizeof(short int), PCM_SIZE, pcmFile);
        if (read == 0)
            write = lame_encode_flush(lame, mp3_buffer, PCM_SIZE);
        else
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, PCM_SIZE);
        fwrite(mp3_buffer, sizeof(unsigned char), write, mp3File);
    } while (read != 0);

    lame_close(lame);
    fclose(mp3File);
    fclose(pcmFile);

    std::cout << "Conversion complete." << std::endl;
    return 0;
}

帮你查了你可以参考一下:
这篇博客(https://blog.csdn.net/weixin_42578963/article/details/129575777)介绍了如何使用LAME中的lame命令行工具来将PCM文件转换为MP3文件,以及如何使用其他工具,如ffmpeg、Audacity等来进行转换。




#include <stdio.h>
#include <lame/lame.h>
bool convertPcmToMp3(const char* pcmFilePath, const char* mp3FilePath, int sampleRate, int channels, int bitRate) {
    FILE *pcmFile = fopen(pcmFilePath, "rb");
    if (!pcmFile) {
        return false;
    }
    FILE *mp3File = fopen(mp3FilePath, "wb");
    if (!mp3File) {
        fclose(pcmFile);
        return false;
    }
    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;
    short pcmBuffer[PCM_SIZE * channels];
    unsigned char mp3Buffer[MP3_SIZE];
    lame_t lame = lame_init();
    lame_set_num_channels(lame, channels);
    lame_set_in_samplerate(lame, sampleRate);
    lame_set_out_samplerate(lame, sampleRate);
    lame_set_brate(lame, bitRate);
    lame_set_mode(lame, channels == 1 ? MONO : STEREO);
    lame_set_quality(lame, 2);
    lame_init_params(lame);
    bool success = true;
    int readSize = 0;
    int writeSize = 0;
    do {
        readSize = fread(pcmBuffer, sizeof(short) * channels, PCM_SIZE, pcmFile);
        if (readSize != 0) {
            if (channels == 1) {
                writeSize = lame_encode_buffer(lame, pcmBuffer, NULL, readSize, mp3Buffer, MP3_SIZE);
            } else {
                writeSize = lame_encode_buffer_interleaved(lame, pcmBuffer, readSize, mp3Buffer, MP3_SIZE);
            }
            fwrite(mp3Buffer, sizeof(unsigned char), writeSize, mp3File);
        } else {
            // Flush the last bit of data.
            writeSize = lame_encode_flush(lame, mp3Buffer, MP3_SIZE);
            fwrite(mp3Buffer, sizeof(unsigned char), writeSize, mp3File);
        }
    } while (readSize != 0);
    lame_close(lame);
    fclose(pcmFile);
    fclose(mp3File);
    return success;
}
int main() {
    const char* pcmFilePath = "input.pcm";
    const char* mp3FilePath = "output.mp3";
    int sampleRate = 44100;   // 采样率(Hz)
    int channels = 2;         // 声道数(1:单声道,2:立体声)
    int bitRate = 128;        // 比特率(kbps)
    bool success = convertPcmToMp3(pcmFilePath, mp3FilePath, sampleRate, channels, bitRate);
    if (success) {
        printf("PCM to MP3 conversion completed.\n");
    } else {
        printf("Failed to convert PCM to MP3.\n");
    }
    return 0;
}

我来说正确答案吧: pcm不能直接转换mp3
第一:pcm首先要转成wav,参考:https://blog.csdn.net/u013113678/article/details/122268109
第二:再然后再把wav转成mp3,wav转mp3参考:https://blog.csdn.net/King1425/article/details/100172681/