是否有任何 LAME C++ 包装器\简化器(从纯代码在 Linux Mac 和 Win 上工作)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2495420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there any LAME C++ wrapper\simplifier (working on Linux Mac and Win from pure code)?
提问by Rella
I want to create simple pcm to mp3 C++ project. I want it to use LAME. I love LAME but it's really big. so I need some kind of OpenSource working from pure code with pure lame code workflow simplifier. So to say I give it File with PCM and DEST file. Call something like:
我想创建简单的 pcm 到 mp3 C++ 项目。我希望它使用 LAME。我喜欢 LAME,但它真的很大。所以我需要某种开源的纯代码和纯代码工作流简化器。所以说我给了它带有 PCM 和 DEST 文件的文件。调用类似:
LameSimple.ToMP3(file with PCM, File with MP3 , 44100, 16, MP3, VBR);
LameSimple.ToMP3(file with PCM, File with MP3 , 44100, 16, MP3, VBR);
ore such thing in 4 - 5 lines (examples of course should exist) and I have vhat I needed It should be light, simple, powerfool, opensource, crossplatform.
在 4 - 5 行中找到这样的东西(当然应该存在示例)并且我有我需要的东西它应该是轻量级的,简单的,傻瓜式的,开源的,跨平台的。
Is there any thing like this?
有这样的事情吗?
回答by Mike Seymour
Lame really isn't difficult to use, although there are a lot of optional configuration functions if you need them. It takes slightly more than 4-5 lines to encode a file, but not much more. Here is a working example I knocked together (just the basic functionality, no error checking):
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;
}
回答by trodevel
inspired by Mike Seymour's answer I created a pure C++ wrapper which allows to encode / decode WAV and MP3 files in just 2 lines of code
受 Mike Seymour 回答的启发,我创建了一个纯 C++ 包装器,它允许仅用 2 行代码对 WAV 和 MP3 文件进行编码/解码
convimp3::Codec::encode( "test.wav", "test.mp3" );
convimp3::Codec::decode( "test.mp3", "test_decoded.wav" );
no need to bother about sample rate, byte rate and number of channels - this info is obtained from WAV or MP3 file during encoding / decoding.
无需担心采样率、字节率和通道数——这些信息是在编码/解码过程中从 WAV 或 MP3 文件中获得的。
The library doesn't use old C i/o functions, but C++ streams only. I find it more elegant.
该库不使用旧的 C i/o 函数,而仅使用 C++ 流。我觉得它更优雅。
For convinience I created a very thin C++ wrapper over LAME and called it lameplus and a small library for extraction of sampling information from WAV files.
为方便起见,我在 LAME 上创建了一个非常薄的 C++ 包装器并将其称为 lameplus 和一个用于从 WAV 文件中提取采样信息的小型库。
All files can be found here:
所有文件都可以在这里找到:
encoding/decoding: https://github.com/trodevel/convimp3
编码/解码:https: //github.com/trodevel/convimp3
lameplus: https://github.com/trodevel/lameplus
lameplus:https: //github.com/trodevel/lameplus
wav handling: also on github, repository is wave
wav 处理:也在 github 上,存储库是wave
回答by keghn
I got this to work by changing 41000 to around 8000:
我通过将 41000 更改为 8000 左右来实现此目的:
lame_set_in_samplerate(lame, 44100);
to
到
lame_set_in_samplerate(lame, 8000);
And compiled prog.c with:
并使用以下命令编译 prog.c:
gcc prog.c -lmp3lame -o prog
The file.pcm does not sound good as file.mp3. I got a perfect conversion when I used this bash command:
file.pcm 听起来不如 file.mp3。当我使用这个 bash 命令时,我得到了一个完美的转换:
lame -V 5 file.wav file.mp3
回答by user142295
I have successfully used libmp3lame in the way mike seymour proposed. I am now trying to use the same approach using posix threads to speed up encoding. I am greating one lame_t pointer, and have several threads doing bits of the conversion, taking care that each thread has a unique bit of the pcm track that it transcodes.
我已经按照 Mike seymour 建议的方式成功地使用了 libmp3lame。我现在尝试使用 posix 线程使用相同的方法来加速编码。我正在使用一个 lame_t 指针,并且有几个线程在做一些转换,注意每个线程都有一个独特的 pcm 轨道,它可以转码。
I use one global lame_t structure that is used for the encoding in each thread. My code works for 1 thread (no parallel execution), it also works if I delay the thread creation in parallel mode (such that there is no parallel execution, but the data structures are arrays).
我使用一个全局 lame_t 结构,用于每个线程中的编码。我的代码适用于 1 个线程(没有并行执行),如果我在并行模式下延迟线程创建(这样没有并行执行,但数据结构是数组),它也可以工作。
When I run my code in parallel mode, I get a lot of errors such as
当我以并行模式运行我的代码时,我收到很多错误,例如
Internal buffer inconsistency. flushbits <> ResvSizebit reservtheitroad error:
l3_side->main_data_begin: 5440
Resvtheitroad 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
For referernce, I attach the code that I am using, that compiles just fine.
作为参考,我附上了我正在使用的代码,它编译得很好。
#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);
}
Maybe someone knows if lame can not be used in this way in parallel code. I did not find any hints if this is possible or not.
也许有人知道在并行代码中是否不能以这种方式使用跛脚。如果这可能或不可能,我没有找到任何提示。
The problem seems to be that the global lame_t structure is accessed by several threads at the same time. I thought that this would only be reading, so no problem, but I seem to be mistaken.
问题似乎是多个线程同时访问全局 lame_t 结构。我以为这只是阅读,所以没问题,但我似乎弄错了。
I also thought that a workaround might be to create a lame_t object for each thread. I tried that, using the threads to encode mutually exclusive bits of the original wav file.
我还认为一种解决方法可能是为每个线程创建一个 lame_t 对象。我试过了,使用线程对原始 wav 文件的互斥位进行编码。
The code compiles and runs without problems, but the resulting file contains no sound.
代码编译和运行没有问题,但生成的文件不包含任何声音。
If anyone is interested, I can add the code. It is just a minor modification of the above code with lame_t being an array of size NTHREADS.
如果有人感兴趣,我可以添加代码。它只是对上述代码的一个小修改,其中 lame_t 是一个大小为 NTHREADS 的数组。