首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用C语言将PCM 8 8kHz 8位无符号转换为mp3

如何用C语言将PCM 8 8kHz 8位无符号转换为mp3
EN

Stack Overflow用户
提问于 2015-10-29 00:39:29
回答 1查看 2.8K关注 0票数 3

我是一个与编程音频处理相关的主题的新手,但我想将PCM音频数据转换为MP3。

我的音频是PCM格式,频率为8 8kHz,位宽为8,字节类型为无符号,信道为单通道。

我正在使用liblamemp3,通过执行以下命令行,我找到了通过lame.exe前端执行该操作的方法:

代码语言:javascript
运行
复制
$ ./lame -r -s 8 --bitwidth 8 --unsigned -m m ../../../../voice8K16bitmono.pcm output.mp3

结果是一个.mp3,我能很好地听到。(经过几次尝试)。

问题是我想要动态地做这件事,所以我试图在不调用前端的情况下编写一些源代码来完成它。

我的源代码是:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <lame/lame.h>

int main(int argc, char *argv[])
{
    int read, write;

    FILE *pcm = fopen(argv[1], "rb");
    FILE *mp3 = fopen("file.mp3", "wb");

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

    unsigned short pcm_buffer;
    unsigned short pcm_buffer_le;
    unsigned char mp3_buffer[MP3_SIZE];

    lame_t lame = lame_init();
    lame_set_num_samples(lame, 8000);
    lame_set_in_samplerate(lame, 8000);
    lame_set_out_samplerate(lame, 8000);
    lame_set_num_channels(lame, 1);
    lame_set_mode(lame, 3);
    lame_init_params(lame);
    lame_print_config(lame);
    //framesize is bits / channels = 8.
    do {
        read = fread(&pcm_buffer, sizeof(short), 1, pcm);
    pcm_buffer = (pcm_buffer>>8) | (pcm_buffer<<8);
    if (read == 0) {
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            fwrite(mp3_buffer, sizeof(char), write, mp3);
        break;
    }
    //pcm_buffer_le[0] = (pcm_buffer[0]>>8) | (pcm_buffer[0]<<8);
        write = lame_encode_buffer_interleaved(lame, &pcm_buffer, sizeof(short), mp3_buffer, MP3_SIZE);
        fwrite(mp3_buffer, sizeof(char), write, mp3);
    } while (1);

    lame_close(lame);
    fclose(mp3);
    fclose(pcm);

    return 0;
}

我以一个例子为例,尝试应用我需要的设置。但由此产生的.mp3听起来像个反应堆,听起来不太好。所以我遗漏了一些/很多代码。

我想这么做,有人能帮忙吗?

提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-29 20:58:27

  1. 每个示例仅为1字节,因此不应以sizeof(short)字节读取,而应以1字节进行读取。
  2. 您必须将未签名的8位PCM样本转换为签名的16位PCM示例(reference)。
  3. 由于输入是单输入,所以使用lame_encode_buffer()而不是lame_encode_buffer_interleaved(),并将buffer_r参数设置为NULL (reference)。

下面是修改后的代码工作版本:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <lame/lame.h>

int main(int argc, char *argv[])
{
    int read, write;

    FILE *pcm = fopen(argv[1], "rb");
    FILE *mp3 = fopen("file.mp3", "wb");

    const int MP3_SIZE = 8192;

    unsigned char pcm_buffer_c;
    short pcm_buffer;
    unsigned char mp3_buffer[MP3_SIZE];

    lame_t lame = lame_init();
    lame_set_num_samples(lame, 8000);
    lame_set_in_samplerate(lame, 8000);
    lame_set_out_samplerate(lame, 8000);
    lame_set_num_channels(lame, 1);
    lame_set_mode(lame, 3);
    lame_init_params(lame);
    lame_print_config(lame);
    //framesize is bits / channels = 8.
    do {
        read = fread(&pcm_buffer_c, sizeof(char), 1, pcm);
        pcm_buffer = (short)(pcm_buffer_c - 0x80) << 8;
        if (read == 0) {
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            fwrite(mp3_buffer, sizeof(char), write, mp3);
            break;
        }
        write = lame_encode_buffer(lame, &pcm_buffer, NULL, read, mp3_buffer, MP3_SIZE);
        fwrite(mp3_buffer, sizeof(char), write, mp3);
    } while (1);

    lame_close(lame);
    fclose(mp3);
    fclose(pcm);

    return 0;
}

上面的代码一次从输入文件中读取一个字节,效率不高。下面是您一次读取多个字节的方式(我还清理了一些代码,删除了一些不必要的函数)。此代码中没有错误检查,因此请确保添加对所有LAME库函数的返回值的检查。

代码语言:javascript
运行
复制
#include <stdio.h>
#include <lame/lame.h>

#define PCM_BUF_SIZE 1024
#define MP3_SIZE 8192

int main(int argc, char *argv[])
{
    FILE *pcm = fopen(argv[1], "rb");
    FILE *mp3 = fopen("file.mp3", "wb");

    int n_bytes_read;
    int n_bytes_write;
    int i;

    short pcm_buffer_s[PCM_BUF_SIZE];
    unsigned char pcm_buffer[PCM_BUF_SIZE];
    unsigned char mp3_buffer[MP3_SIZE];

    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 8000);
    lame_set_num_channels(lame, 1);
    lame_set_mode(lame, 3);
    lame_init_params(lame);
    lame_print_config(lame);
    do {
        n_bytes_read = fread(pcm_buffer, sizeof(char), PCM_BUF_SIZE, pcm);
        for (i = 0; i < n_bytes_read; i++) {
            pcm_buffer_s[i] = (short)(pcm_buffer[i] - 0x80) << 8;
        }
        if (n_bytes_read == 0) {
            n_bytes_write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
        } else {
            n_bytes_write = lame_encode_buffer(lame, pcm_buffer_s, NULL,
                    n_bytes_read, mp3_buffer, MP3_SIZE);
        }
        fwrite(mp3_buffer, sizeof(char), n_bytes_write, mp3);
    } while (n_bytes_read > 0);

    lame_close(lame);
    fclose(mp3);
    fclose(pcm);

    return 0;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33404063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档