以前已經介紹過iOS下使用lamemp3將PCM壓縮爲mp3格式,今天介紹一下Android的使用。 java
至於lamemp3庫的下載就再也不介紹了,你們能夠直接把iOS的那個庫拷過來,或者使用我附件中的庫也能夠。 c++
下面我介紹一下整個使用步驟,我將按照由上到下的方式來說解: 數組
1. 編寫連接動態庫的java文件: app
package com.example.mp3encodedemo; 框架
publicclass JNIMp3Encode { ui
public native void init(int channel, int sampleRate, int brate); spa
public native void destroy(); code
public native byte[] encode(short[] buffer, int len); 內存
static{ get
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播放