Android 编译Lame&简单使用

Posted 吴佳峻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 编译Lame&简单使用相关的知识,希望对你有一定的参考价值。

上一篇文章介绍了AndroidStudio2.0搭建Ndk环境&成功编译使用,这一篇我们开始实战编译一个项目,并使用它。那接下来要介绍一下这个项目Lame,来看看他的介绍

LAME是目前最好的MP3编码引擎。LAME编码出来的MP3音色纯厚、空间宽广、低音清晰、细节表现良好,它独创的心理音响模型技术保证了CD音频还原的真实性,配合VBR和ABR参数,音质几乎可以媲美CD音频,但文件体积却非常小。对于一个免费引擎,LAME的优势不言而喻。关于LAME的介绍可以在百度百科,维基百科中找到,我在这里不再赘述了,但是要知道LAME可以帮助我们将wav无损音频文件转码成mp3这种体积相对较小的音频格式文件。
当我们在跨平台上使用,mp3无疑是最好的音频选择,因为无论androidios都默认支持播放

那我们来看看怎么根据源码进行编译和使用吧
在官网http://lame.sourceforge.net/ 下载最新版的版本 lame-3.99.5 下载完进行解压,然后把libmp3lame目录下的文件拷贝到jni下面,去除i386文件夹,和非.c .h的文件

然后创建一个Activity,编写一个wav转换成mp3的本地方法

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    convertmp3("/sdcard/1KHz-stero.wav","/sdcard/bubugao.mp3");


static 
    System.loadLibrary("lalala");


/**
 * wav转换成mp3的本地方法
 *
 * @param wav
 * @param mp3
 */
public native void convertmp3(String wav, String mp3);

然后根据javah命令生成.h文件com_wjj_lame_MainActivity.h,然后根据新建一个.c的文件,实现定义头里面的方法函数

/**
 * wav转换mp3
 */
JNIEXPORT void JNICALL Java_com_wjj_lame_MainActivity_convertmp3
(JNIEnv * env, jobject obj, jstring jwav, jstring jmp3) 
   char* cwav =Jstring2CStr(env,jwav) ;
   char* cmp3=Jstring2CStr(env,jmp3);
   LOGI("amr = %s", cwav);
   LOGI("mp3 = %s", cmp3);

   //1.打开 wav,MP3文件
   FILE* fwav = fopen(cwav,"rb");
   FILE* fmp3 = fopen(cmp3,"wb");

   short int wav_buffer[8192*2];
   unsigned char mp3_buffer[8192];

   //1.初始化lame的编码器
   lame_t lame =  lame_init();
   //2. 设置lame mp3编码的采样率
   lame_set_in_samplerate(lame , 8000);
   lame_set_num_channels(lame,1);
   lame_set_out_samplerate(lame, 8000);
   lame_set_brate(lame, 8);
   lame_set_quality(lame, 7);
   // 3. 设置MP3的编码方式
   //lame_set_VBR(lame, vbr_default);
   lame_init_params(lame);
   LOGI("lame init finish");
   int read ; int write; //代表读了多少个次 和写了多少次
   int total=0; // 当前读的wav文件的byte数目
   do
      if(flag==404)
         return;
      
      read = fread(wav_buffer,sizeof(short int)*2, 8192,fwav);
      total +=  read* sizeof(short int)*2;
      LOGI("converting ....%d", total);
      if(read!=0)
         write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
         //把转化后的mp3数据写到文件里
         fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
      
      if(read==0)
         lame_encode_flush(lame,mp3_buffer,8192);
      
   while(read!=0);
   LOGI("convert  finish");

   lame_close(lame);
   fclose(fwav);
   fclose(fmp3);

下面是Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := lalala

LOCAL_SRC_FILES := bitstream.c com_wjj_lame_MainActivity.c encoder.c fft.c gain_analysis.c id3tag.c lame.c mpglib_interface.c newmdct.c presets.c psymodel.c quantize.c quantize_pvt.c reservoir.c set_get.c tables.c takehiro.c util.c vbrquantize.c VbrTag.c version.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

Application.mk文件

APP_ABI := all
APP_PLATFORM := android-8
APP_CFLAGS += -DSTDC_HEADERS

最下面的这个比较重要,当你去掉的时候,你试试会发生什么,可以试试

编译一下生成.so文件,然后运行一下,打印一下log信息

04-26 14:50:23.847 19249-19249/com.wjj.lame I/System.out.c: amr = /sdcard/1KHz-stero.wav
04-26 14:50:23.847 19249-19249/com.wjj.lame I/System.out.c: mp3 = /sdcard/bubugao.mp3
04-26 14:50:23.917 19249-19249/com.wjj.lame I/System.out.c: lame init finish
04-26 14:50:23.927 19249-19249/com.wjj.lame I/System.out.c: converting ....32768
04-26 14:50:24.037 19249-19249/com.wjj.lame I/System.out.c: converting ....65536
04-26 14:50:24.137 19249-19249/com.wjj.lame I/System.out.c: converting ....98304
04-26 14:52:40.207 19249-19249/com.wjj.lame I/System.out.c: convert  finish

然后在手机文件中也找到了我们所转换后的mp3文件,音乐的质量差不多,但是体积小了不少。

然后有人会问既然lame能够转换成mp3那能不能把amr数据也通过这种方式转换为mp3啊,听着还挺合理的,大家可以转转试试,结果呢,转换出来的文件声音很短,有问题,这是为什么呢?(这里要感谢 少-数字广播 的讲解支持)
原因呢是这样的,音频分为解码和编码,为什么wma可以直接通过方法转为mp3数据,而amr不行呢,因为wma就是原始的pcm数据加了一个数据头组成的,而amr的格式是pcm数据的压缩格式,并不能直接转为mp3数据,需要先对amr数据进行解码,生成pcm原始音频数据,然后对pcm进行mp3的编码过程,然后把编码后的mp3数据放到一个文件中,就可以了。

参考资料:
http://stackoverflow.com/questions/27893149/android-ndk-for-x86-64-has-no-reference-for-bcopy-and-index
http://www.cnblogs.com/ct2011/p/4080193.html
http://blog.csdn.net/allen315410/article/details/42456661

以上是关于Android 编译Lame&简单使用的主要内容,如果未能解决你的问题,请参考以下文章

ndk编译android的lame库

有没有办法将 NAudio.Lame 与 Xamarin (Android/iOS) 应用程序一起使用?

使用Lame编译音频文件

使用Lame编译音频文件

使用Lame编译音频文件

使用 exe 编译非托管 DLL