引言
lame是优秀的音频库,引百度贴吧的话来说:LAME 是最好的MP3编码器,编码高品质MP3的最好也是唯一的选择。最近项目中需要用到mp3解码部分,遂用到了这个库。好了,废话不多说,进入正题。
lame库移植
lame库编译
- [lame源代码获取](http://sourceforge.net/projects/lame/files/lame/3.99/)
- linux开源库编译3步骤:
- . ./configure –prefix=XXX
- . make
- . make install
lame库 内容简介
lame库主要有3个目录:
- libmp3lame 集合了lame的核心,编码功能在这里面
- mpglib 解码功能在这里
- frontend 看字面意义吧 (^__^) 嘻嘻……
lame库的裁剪
好了,进入关键部分了。嵌入式系统各项资源有限(在这小小的吐槽一下O(∩_∩)O~),要用别人的东西而又不得不修剪一下。但不得不说,lame库写的很好,耦合性很低。想要直接使用lame库的编码部分的同学有福了,因为写lame的大神就遇见了这点,只需要在configure 的时候配置一下即可。如下:
./configure --host=$(HOST) --disable-shared --enable-static --disable-frontend --disable-decoder --prefix=$(INST) CC=$(CROSS_COMPILE)gcc CFLAGS=$(CFLAGS) CPPFLAGS=$(CPPFLAGS)
–disable-frontend –disable-decoder 是关键,其他配置选项自己酌情处理。
但撸主的需求恰恰相反,不是要lame的编码部分,而是需要他的解码部分。configure文件配置需要没有支持该功能,没办法只有硬着头皮裁吧。
在不裁剪的情况下,lame完全编译完成之后会有两个库生成,分别是
lame/mpglib/.libs/libmpgdecoder.a
lame/libmp3lame/.libs/libmp3lame.a
解码部分的代码编译成了 libmpgdecoder.a这个库。看到这里是不是有点惊喜,哇,直接把这个静态库拿来用不就OK了么?是啊,当发现这个,撸主也是高兴了好久呢~~~,可是好事多么,lame提供出来的API的实现基本上都在mpglib_interface.c这个文件中,而这个文件却恰恰又在libmp3lame.a这个库中。再就是直接使用libmpgdecoder.a这个库会发现有些地方链接不过,发现libmpgdecoder.a这个库使用了一些打印函数,和有些函数引用了libmp3lame.a库中的函数。没办法,一狠心,将mpglib中的所有文件提取出来,再将里面所有的打印函数屏蔽写成自己的。将libmp3lame.a中的VbrTag.c和tables.c两个文件拷过来(只发现引用了这两个文件中的函数)。再将所有头文件拷贝过来,集体打包编译。根据编译情况,酌情增删改查,最后编译通过。
lame库的使用
lame解码
/*
MP3帧体的大小由MPEG版本号、比特率、抽样率和填充位4个因素确定。计算公式为:
帧大小= ((MPEG版本号== 1?144:72) * 比特率)/抽样率 + 填充位
位率为64kbps,采样频率为44.1kHz,padding(帧长调节)为1时,帧长为210字节。
位率为128kbps,采样频率为44.1kHz,padding(帧长调节)为0时,帧长为418字节
*/
int mp3_frame_size(int verson,int baudrate, float samprate,int padding)
{
if(verson == 1 && baudrate == 64 && (samprate-44.1)<0.000001 && padding == 1)
return 210;
if(verson == 1 && baudrate == 128 && (samprate-44.1)<0.000001 && padding == 0)
return 418;
return (int)((((verson == 1)? 144:72) * baudrate)/samprate + padding);
}
unsigned char mp3_buf[MP3BUF_SIZE];
int main(int argc,char *argv[])
{
FILE * mp3fp = fopen("testcase.mp3", "rb");
if (!mp3fp)
{
printf("open mp3 file failed!\n");
return -1;
}
FILE * wavfp = fopen("out1.pcm", "wb");
if (!wavfp)
{
printf("create pcm file failed!\n");
return -1;
}
lame_decode_init();
mp3data_struct mp3str;
int samples;
int mp3_bytes;
int write_bytes;
int size = 0;
size = mp3_frame_size(1,64,44.1,1);
fprintf(stderr,"mp3 frame size:%d\n",size);
while ((mp3_bytes = fread(mp3_buf, 1, size, mp3fp)) > 0)
{
samples = lame_decode(mp3_buf, size, pcm_l, pcm_r);
if (samples > 0)
{
write_bytes = fwrite(pcm_l, sizeof(short), samples, wavfp);
}
}
lame_decode_exit();
fclose(wavfp);
return 0;
}
lame_decode_init lame解码初始化
lame_decode_exit lame解码退出
lame_decode 解码
另外在mpglib_interface.c这个文件中还有另一套hip开头的API,跟lame开头的大同小异。
lame编码
以下代码来自stackoverflow
#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;
}