我想创建简单的pcm到mp3 C ++项目。我希望它使用LAME。我喜欢LAME,但它真的很棒。所以我需要某种OpenSource,使用纯粹的代码和纯粹的蹩脚代码工作流简化器。所以说我用PCM和DEST文件给它文件。打电话给:
LameSimple.ToMP3(file with PCM, File with MP3 , 44100, 16, MP3, VBR);
有这样的事吗?
答案 0 :(得分:43)
Lame确实不难使用,虽然如果你需要它们有很多可选的配置功能。编码文件需要略多于4-5行,但不多。这是一个我碰到的工作示例(只是基本功能,没有错误检查):
#include <stdio.h>
#include <lame/lame.h>
int main(void)
{
int read, write;
FILE *pcm = fopen("file.pcm", "rb");
FILE *mp3 = fopen("file.mp3", "wb");
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_in_samplerate(lame, 44100);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
do {
read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
if (read == 0)
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
lame_close(lame);
fclose(mp3);
fclose(pcm);
return 0;
}
答案 1 :(得分:3)
convimp3::Codec::encode( "test.wav", "test.mp3" );
convimp3::Codec::decode( "test.mp3", "test_decoded.wav" );
无需担心采样率,字节速率和通道数量 - 此信息在编码/解码过程中从WAV或MP3文件中获取。
该库不使用旧的C i / o函数,但仅使用C ++流。我发现它更优雅。
为方便起见,我在LAME上创建了一个非常精简的C ++包装器,并将其称为lameplus和一个用于从WAV文件中提取采样信息的小型库。
所有文件都可以在这里找到:
编码/解码:https://github.com/trodevel/convimp3
lameplus:https://github.com/trodevel/lameplus
wav处理:同样在github上,存储库是wave
答案 2 :(得分:1)
我通过将41000改为8000左右来实现这一目标:
lame_set_in_samplerate(lame, 44100);
到
lame_set_in_samplerate(lame, 8000);
用prog编译prog.c:
gcc prog.c -lmp3lame -o prog
file.pcm听起来不像file.mp3。当我使用这个bash命令时,我获得了完美的转换:
lame -V 5 file.wav file.mp3
答案 3 :(得分:1)
我已经成功地使用了libke3lame,就像mike seymour提出的那样。 我现在尝试使用相同的方法使用posix线程来加速编码。 我正在讨论一个lame_t指针,并有几个线程做转换的位, 注意每个线程都有一个转码的pcm轨道的唯一位。
我使用一个全局lame_t结构,用于每个线程中的编码。 我的代码适用于1个线程(没有并行执行),如果我以并行模式延迟线程创建(这样就没有并行执行,但数据结构是数组),它也可以工作。
当我以并行模式运行代码时,我会遇到很多错误,例如
Internal buffer inconsistency. flushbits <> ResvSizebit reservoir error:
l3_side->main_data_begin: 5440
Resvoir size: 4088
resv drain (post) 1
resv drain (pre) 184
header and sideinfo: 288
data bits: 1085
total bits: 1374 (remainder: 6)
bitsperframe: 3336
This is a fatal error. It has several possible causes:90% LAME compiled with buggy version of gcc using advanced optimizations 9% Your system is overclocked 1% bug in LAME encoding libraryfinished encoding
Internal buffer inconsistency. flushbits <> ResvSizefinished encoding
对于引用,我附上我正在使用的代码,编译得很好。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <iostream>
#include <string>
#include <lame/lame.h>
#include <pthread.h>
#include <thread>
#include <chrono>
using namespace std;
typedef struct Data{
lame_t lame;
FILE * wav_file;
short int * pcm_buffer;
unsigned char * mp3_buffer;
unsigned long mp3_buffer_size;
unsigned long first_sample;
unsigned long n_samples;
unsigned long items_read;
unsigned long mp3_bytes_to_write;
pthread_mutex_t *mutexForReading;
} Data;
void *encode_chunk(void *arg)
{
Data * data = (Data *) arg;
unsigned long offset = 40 + 2 * 2 * data->first_sample;
pthread_mutex_lock(data->mutexForReading);
fseek(data->wav_file, offset, SEEK_SET);
data->items_read = fread(data->pcm_buffer, 2*sizeof(short int) , data->n_samples, data->wav_file);
cout << "first sample " << data->first_sample << " n_samples "<< data->n_samples << " items read " << data->items_read << " data address " << data << " mp3 a " << static_cast<void *> (data->mp3_buffer) << endl;
pthread_mutex_unlock(data->mutexForReading);
if (data->items_read != 0)
{
data->mp3_bytes_to_write = lame_encode_buffer_interleaved(data->lame,
data->pcm_buffer,
data->items_read,
data->mp3_buffer,
data->mp3_buffer_size);
}
cout << "finished encoding " << endl;
return NULL;
}
int main(int argc, char * argv[])
{
int read,write;
FILE *wav = fopen("test.wav", "rb");
FILE *mp3 = fopen("file.mp3", "wb");
fseek(wav,0,SEEK_END);
unsigned long file_size_wav = ftell(wav);
unsigned long bytes_PCM = file_size_wav - 40;
unsigned long n_total_samples = bytes_PCM / 4;
const unsigned long MAX_SAMPLE_NUMBER = pow(2,10);
const unsigned short NTHREADS = 2;
const unsigned long MAX_MP3_SIZE = int(MAX_SAMPLE_NUMBER * 1.25 + 7200) + 1;
short int pcm_buffer[NTHREADS][MAX_SAMPLE_NUMBER * 2]; // 2 channels
unsigned char mp3_buffer[NTHREADS][MAX_MP3_SIZE]; // according to libmp3lame api
lame_t lame = lame_init();
lame_set_in_samplerate(lame, 44100);
lame_set_VBR(lame, vbr_default);
// lame_set_brate(lame, 128); // only for CBR mode
// lame_set_quality(lame, 2);
// lame_set_mode(lame, JOINT_STEREO); // 1 joint stereo , 3 mono
lame_init_params(lame);
Data data_ptr[NTHREADS];
unsigned short n_main_loops = n_total_samples / MAX_SAMPLE_NUMBER / NTHREADS + 1;
cout << "total samples " << n_total_samples << endl;
cout << "Number of iterations in main loop : " << n_main_loops << endl;
unsigned long samples_remaining = n_total_samples;
unsigned long current_sample = 0;
pthread_t threadID[NTHREADS];
pthread_mutex_t mutexForReading = PTHREAD_MUTEX_INITIALIZER;
for (unsigned long i = 0 ; i < n_main_loops; i ++)
{
for (unsigned short j = 0; j < NTHREADS; j++ )
{
Data data;
data.lame = lame;
data.wav_file = wav;
data.pcm_buffer = pcm_buffer[j];
data.mp3_buffer = mp3_buffer[j];
data.first_sample = current_sample;
data.n_samples = min(MAX_SAMPLE_NUMBER, n_total_samples - current_sample);
data.mutexForReading = &mutexForReading;
current_sample += data.n_samples;
samples_remaining -= data.n_samples;
data_ptr[j] = data;
if (data_ptr[j].n_samples > 0)
{
cout << "creating " << i << " " << j << " " << data_ptr[j].first_sample << " " << data_ptr[j].n_samples << endl;
pthread_create( &threadID[j],
NULL,
encode_chunk,
(void *) (&data_ptr[j]));
}
}
for (unsigned short j = 0; j < NTHREADS; j++)
{
if (data_ptr[j].n_samples > 0)
{
pthread_join( threadID[j], NULL);
}
}
for (unsigned short j = 0; j< NTHREADS; j++)
if (data_ptr[j].n_samples > 0)
{
fwrite(data_ptr[j].mp3_buffer, data_ptr[j].mp3_bytes_to_write, 1, mp3);
}
else
{
data_ptr[j].mp3_bytes_to_write = lame_encode_flush(lame, data_ptr[j].mp3_buffer, data_ptr[j].mp3_buffer_size);
}
}
lame_close(lame);
fclose(mp3);
fclose(wav);
}
也许有人知道在并行代码中是否不能以这种方式使用lame。如果可能或没有,我没有找到任何提示。
问题似乎是全局lame_t结构同时被多个线程访问。我认为这只会是阅读,所以没问题,但我似乎错了。
我还认为解决方法可能是为每个线程创建一个lame_t对象。 我尝试过,使用线程编码原始wav文件的互斥位。
代码编译并运行没有问题,但生成的文件不包含声音。
如果有人有兴趣,我可以添加代码。它只是对上面代码的一个小修改,lame_t是一个大小为NTHREADS的数组。