之前已经介绍过iOS下使用lamemp3将PCM压缩为mp3格式,今天介绍一下Android的使用。
至于lamemp3库的下载就不再介绍了,大家可以直接把iOS的那个库拷过来,或者使用我附件中的库也可以。
下面我介绍一下整个使用步骤,我将按照由上到下的方式来讲解:
1. 编写链接动态库的java文件:
package com.example.mp3encodedemo;
publicclass JNIMp3Encode {
public native void init(int channel, int sampleRate, int brate);
public native void destroy();
public native byte[] encode(short[] buffer, int len);
static{
System.loadLibrary("mp3lame");
}
}
这里声明了3个native方法:init,destroy,encode,这些都是由c 、c++实现的。
init方法的参数:channel声道数,sampleRate采样率,brate压缩的比特率
encode方法的参数:short[] buffer, int len这个是录音的数据,注意是short类型
2. 根据java文件生成JNI的头文件
cd到工程目录下的bin/classes目录下
hejinlai_iMac:classes hejinlai$ pwd
/Users/hejinlai/Workspace/Android/Mp3EncodeDemo/bin/classes
调用javah生成jni头文件
hejinlai_iMac:classes hejinlai$ javah com.example.mp3encodedemo.JNIMp3Encode
3. 根据生成的头文件,实现里面的方法
/* DO NOT EDIT THIS FILE - it is machine generated */
#include<jni.h>
/* Header for class com_example_mp3encodedemo_JNIMp3Encode */
#ifndef _Included_com_example_mp3encodedemo_JNIMp3Encode
#define _Included_com_example_mp3encodedemo_JNIMp3Encode
#ifdef __cplusplus
extern"C" {
#endif
#include"libmp3lame/lame.h"
#define BUFFER_SIZE 4096
lame_t lame;
/*
* Class: com_example_mp3encodedemo_JNIMp3Encode
* Method: init
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_example_mp3encodedemo_JNIMp3Encode_init
(JNIEnv *env, jobject obj, jint channel, jint sampleRate, jint brate)
{
lame = lame_init();
lame_set_num_channels(lame, channel);
lame_set_in_samplerate(lame, sampleRate);
lame_set_brate(lame, brate);
lame_set_mode(lame, 1);
lame_set_quality(lame, 2);
lame_init_params(lame);
}
/*
* Class: com_example_mp3encodedemo_JNIMp3Encode
* Method: destroy
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_mp3encodedemo_JNIMp3Encode_destroy
(JNIEnv *env, jobject obj)
{
lame_close(lame);
}
/*
* Class: com_example_mp3encodedemo_JNIMp3Encode
* Method: encode
* Signature: ([SI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_example_mp3encodedemo_JNIMp3Encode_encode
(JNIEnv *env, jobject obj, jshortArray buffer, jint len)
{
int nb_write = 0;
char output[BUFFER_SIZE];
// 转换为本地数组
jshort *input = (*env)->GetShortArrayElements(env, buffer, NULL);
// 压缩mp3
nb_write = lame_encode_buffer(lame, input, input, len, output, BUFFER_SIZE);
// 局部引用,创建一个byte数组
jbyteArray result = (*env)->NewByteArray(env, nb_write);
// 给byte数组设置值
(*env)->SetByteArrayRegion(env, result, 0, nb_write, (jbyte *)output);
// 释放本地数组(避免内存泄露)
(*env)->ReleaseShortArrayElements(env, buffer, input, 0);
return result;
}
#ifdef __cplusplus
}
#endif
#endif
这里调用到了lame的方法,使用到了很多JNI的知识,不是很了解的大家可以参考相关资料。
4. 将整个libmp3lame库拷贝到jni目录下,编写Android.mk文件
LOCAL_PATH := $(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE := libmp3lame
LOCAL_SRC_FILES := \
./libmp3lame/bitstream.c \
./libmp3lame/encoder.c \
./libmp3lame/fft.c \
./libmp3lame/gain_analysis.c \
./libmp3lame/id3tag.c \
./libmp3lame/lame.c \
./libmp3lame/mpglib_interface.c \
./libmp3lame/newmdct.c \
./libmp3lame/presets.c \
./libmp3lame/psymodel.c \
./libmp3lame/quantize.c \
./libmp3lame/quantize_pvt.c \
./libmp3lame/reservoir.c \
./libmp3lame/set_get.c \
./libmp3lame/tables.c \
./libmp3lame/takehiro.c \
./libmp3lame/util.c \
./libmp3lame/vbrquantize.c \
./libmp3lame/VbrTag.c \
./libmp3lame/version.c \
lamemp3_wrapper.c
LOCAL_LDLIBS := -llog
include$(BUILD_SHARED_LIBRARY)
5. 调用ndk-build进行编译,生成so文件
hejinlai_iMac:jni hejinlai$ ndk-build
........
Compile thumb : mp3lame <= version.c
SharedLibrary : libmp3lame.so
Install : libmp3lame.so => libs/armeabi/libmp3lame.so
到这里,整个调用的框架都搭建完成了,只需要在java中调用JNIMp3Encode中的方法即可,剩下的步骤就不在介绍了。
说明:
1. 我录音的格式为:16位 16k的pcm,这个要和lamemp3设置时的参数保持一致
2. 打开应用后,点击底部按钮的“开始说话”进行录音,再点击“说完了”停止录音,压缩后的MP3
文件保存在sdcard下mp3_recording目录下的recording.mp3中,读者可以将它拷贝出来用一般的播放器播放,或者调用MediaPlayer播放