生活随笔
收集整理的這篇文章主要介紹了
Android MP3录音实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?? ?給APP做語(yǔ)音功能,必須考慮到IOS和Android平臺(tái)的通用性。wav錄音質(zhì)量高,文件太大,AAC和AMR格式在IOS平臺(tái)卻不支持,所以采用libmp3lame把AudioRecord音頻流直接轉(zhuǎn)換成MP3格式。
? ? ? ?聲明一下,代碼參考了http://blog.csdn.net/cboy017/article/details/8455629,這里只是借花獻(xiàn)佛,把整個(gè)流程寫(xiě)得更詳細(xì)。
? ? ? ?這里采用的是最新的lame-3.99.5.tar。
? ? ? ?可以去Lame官網(wǎng)下載,博文最后也有CSDN下載地址。官網(wǎng)地址:http://lame.sourceforge.net/
? ? ? ?如果你對(duì)JNI和NDK完全不熟悉的話,請(qǐng)看前一篇博文?Android?NDK開(kāi)發(fā)之入門(mén)教程
? ? ? 先看一下項(xiàng)目文件目錄:
? ? ? ?
? ? ? ?開(kāi)始Coding吧!
1 ?新建項(xiàng)目AndroidLameMP3。
2 ?創(chuàng)建JNI目錄。
3 下載lame-3.99.5.tar。
? ? ? ?解壓,把子文件夾libmp3lame中的非.h和.c格式的文件刪除后的剩余的所有文件和include下的lame.h放進(jìn)一個(gè)新建的lame-3.99.5_libmp3lame文件夾中,最后把整個(gè)lame-3.99.5_libmp3lame文件夾拷貝到JNI目錄下。
4 ?在com.example.lamemp3下創(chuàng)建MP3Recorder.class:
MP3Recorder.class
?
[java]?view plaincopy
public?class?MP3Recorder?{????????private?String?mFilePath?=?null;??????private?int?sampleRate?=?0;??????private?boolean?isRecording?=?false;??????private?boolean?isPause?=?false;??????private?Handler?handler?=?null;????????????public?static?final?int?MSG_REC_STARTED?=?1;????????????public?static?final?int?MSG_REC_STOPPED?=?2;????????????public?static?final?int?MSG_REC_PAUSE?=?3;????????????public?static?final?int?MSG_REC_RESTORE?=?4;????????????public?static?final?int?MSG_ERROR_GET_MIN_BUFFERSIZE?=?-1;????????????public?static?final?int?MSG_ERROR_CREATE_FILE?=?-2;????????????public?static?final?int?MSG_ERROR_REC_START?=?-3;????????????public?static?final?int?MSG_ERROR_AUDIO_RECORD?=?-4;????????????public?static?final?int?MSG_ERROR_AUDIO_ENCODE?=?-5;????????????public?static?final?int?MSG_ERROR_WRITE_FILE?=?-6;????????????public?static?final?int?MSG_ERROR_CLOSE_FILE?=?-7;????????public?MP3Recorder()?{??????????this.sampleRate?=?8000;??????}????????????public?void?start()?{??????????if?(isRecording)?{??????????????return;??????????}????????????new?Thread()?{??????????????@Override??????????????public?void?run()?{??????????????????String?fileDir?=?StorageUtil.getSDPath()?+?"LameMP3/Voice/";????????????????????File?dir?=?new?File(fileDir);??????????????????if?(!dir.exists())?{??????????????????????dir.mkdirs();??????????????????}????????????????????mFilePath?=?StorageUtil.getSDPath()?+?"LameMP3/Voice/"??????????????????????????+?System.currentTimeMillis()?+?".mp3";????????????????????System.out.println(mFilePath);??????????????????android.os.Process??????????????????????????.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);??????????????????????????????????final?int?minBufferSize?=?AudioRecord.getMinBufferSize(??????????????????????????sampleRate,?AudioFormat.CHANNEL_IN_MONO,??????????????????????????AudioFormat.ENCODING_PCM_16BIT);??????????????????if?(minBufferSize?<?0)?{??????????????????????if?(handler?!=?null)?{??????????????????????????handler.sendEmptyMessage(MSG_ERROR_GET_MIN_BUFFERSIZE);??????????????????????}??????????????????????return;??????????????????}??????????????????AudioRecord?audioRecord?=?new?AudioRecord(??????????????????????????MediaRecorder.AudioSource.MIC,?sampleRate,??????????????????????????AudioFormat.CHANNEL_IN_MONO,??????????????????????????AudioFormat.ENCODING_PCM_16BIT,?minBufferSize?*?2);????????????????????????????????????short[]?buffer?=?new?short[sampleRate?*?(16?/?8)?*?1?*?5];??????????????????byte[]?mp3buffer?=?new?byte[(int)?(7200?+?buffer.length?*?2?*?1.25)];????????????????????FileOutputStream?output?=?null;??????????????????try?{??????????????????????output?=?new?FileOutputStream(new?File(mFilePath));??????????????????}?catch?(FileNotFoundException?e)?{??????????????????????if?(handler?!=?null)?{??????????????????????????handler.sendEmptyMessage(MSG_ERROR_CREATE_FILE);??????????????????????}??????????????????????return;??????????????????}??????????????????MP3Recorder.init(sampleRate,?1,?sampleRate,?32);??????????????????isRecording?=?true;?????????????????isPause?=?false;?????????????????try?{??????????????????????try?{??????????????????????????audioRecord.startRecording();?????????????????????}?catch?(IllegalStateException?e)?{??????????????????????????????????????????????????if?(handler?!=?null)?{??????????????????????????????handler.sendEmptyMessage(MSG_ERROR_REC_START);??????????????????????????}??????????????????????????return;??????????????????????}????????????????????????try?{??????????????????????????????????????????????????if?(handler?!=?null)?{??????????????????????????????handler.sendEmptyMessage(MSG_REC_STARTED);??????????????????????????}????????????????????????????int?readSize?=?0;??????????????????????????boolean?pause?=?false;??????????????????????????while?(isRecording)?{??????????????????????????????????????????????????????????if?(isPause)?{??????????????????????????????????if?(!pause)?{??????????????????????????????????????handler.sendEmptyMessage(MSG_REC_PAUSE);??????????????????????????????????????pause?=?true;??????????????????????????????????}??????????????????????????????????continue;??????????????????????????????}??????????????????????????????if?(pause)?{??????????????????????????????????handler.sendEmptyMessage(MSG_REC_RESTORE);??????????????????????????????????pause?=?false;??????????????????????????????}??????????????????????????????????????????????????????????????????????????????????????readSize?=?audioRecord.read(buffer,?0,??????????????????????????????????????minBufferSize);??????????????????????????????if?(readSize?<?0)?{??????????????????????????????????if?(handler?!=?null)?{??????????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);??????????????????????????????????}??????????????????????????????????break;??????????????????????????????}?else?if?(readSize?==?0)?{??????????????????????????????????;??????????????????????????????}?else?{??????????????????????????????????int?encResult?=?MP3Recorder.encode(buffer,??????????????????????????????????????????buffer,?readSize,?mp3buffer);??????????????????????????????????if?(encResult?<?0)?{??????????????????????????????????????if?(handler?!=?null)?{??????????????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_AUDIO_ENCODE);??????????????????????????????????????}??????????????????????????????????????break;??????????????????????????????????}??????????????????????????????????if?(encResult?!=?0)?{??????????????????????????????????????try?{??????????????????????????????????????????output.write(mp3buffer,?0,?encResult);??????????????????????????????????????}?catch?(IOException?e)?{??????????????????????????????????????????if?(handler?!=?null)?{??????????????????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_WRITE_FILE);??????????????????????????????????????????}??????????????????????????????????????????break;??????????????????????????????????????}??????????????????????????????????}??????????????????????????????}??????????????????????????????????????????????????????}??????????????????????????????????????????????????int?flushResult?=?MP3Recorder.flush(mp3buffer);??????????????????????????if?(flushResult?<?0)?{??????????????????????????????if?(handler?!=?null)?{??????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_AUDIO_ENCODE);??????????????????????????????}??????????????????????????}??????????????????????????if?(flushResult?!=?0)?{??????????????????????????????try?{??????????????????????????????????output.write(mp3buffer,?0,?flushResult);??????????????????????????????}?catch?(IOException?e)?{??????????????????????????????????if?(handler?!=?null)?{??????????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_WRITE_FILE);??????????????????????????????????}??????????????????????????????}??????????????????????????}??????????????????????????try?{??????????????????????????????output.close();??????????????????????????}?catch?(IOException?e)?{??????????????????????????????if?(handler?!=?null)?{??????????????????????????????????handler.sendEmptyMessage(MSG_ERROR_CLOSE_FILE);??????????????????????????????}??????????????????????????}??????????????????????????????????????????????}?finally?{??????????????????????????audioRecord.stop();??????????????????????????audioRecord.release();??????????????????????}??????????????????}?finally?{??????????????????????MP3Recorder.close();??????????????????????isRecording?=?false;??????????????????}??????????????????if?(handler?!=?null)?{??????????????????????handler.sendEmptyMessage(MSG_REC_STOPPED);??????????????????}??????????????}??????????}.start();??????}????????public?void?stop()?{??????????isRecording?=?false;??????}????????public?void?pause()?{??????????isPause?=?true;??????}????????public?void?restore()?{??????????isPause?=?false;??????}????????public?boolean?isRecording()?{??????????return?isRecording;??????}????????public?boolean?isPaus()?{??????????if?(!isRecording)?{??????????????return?false;??????????}??????????return?isPause;??????}????????public?String?getFilePath()?{??????????return?mFilePath;??????}????????????public?void?setHandle(Handler?handler)?{??????????this.handler?=?handler;??????}????????????static?{??????????System.loadLibrary("mp3lame");??????}????????????public?static?void?init(int?inSamplerate,?int?outChannel,??????????????int?outSamplerate,?int?outBitrate)?{??????????init(inSamplerate,?outChannel,?outSamplerate,?outBitrate,?7);??????}????????????public?native?static?void?init(int?inSamplerate,?int?outChannel,??????????????int?outSamplerate,?int?outBitrate,?int?quality);????????????public?native?static?int?encode(short[]?buffer_l,?short[]?buffer_r,??????????????int?samples,?byte[]?mp3buf);????????????public?native?static?int?flush(byte[]?mp3buf);????????????public?native?static?void?close();??}?? ?
?
5 ?在JNI文件夾下創(chuàng)建com_example_lamemp3_MP3Recorder.h頭文件,在里面定義幾個(gè)方法,然后在
com_example_lamemp3_MP3Recorder.c中實(shí)現(xiàn)。
?
com_example_lamemp3_MP3Recorder.h:
?
[cpp]?view plaincopy
#include?<jni.h>????#ifndef?_Included_com_example_lamemp3_MP3Recorder??#define?_Included_com_example_lamemp3_MP3Recorder??#ifdef?__cplusplus??extern?"C"?{??#endif??JNIEXPORT?void?JNICALL?Java_com_example_lamemp3_MP3Recorder_init????(JNIEnv?*,?jclass,?jint,?jint,?jint,?jint,?jint);????JNIEXPORT?jint?JNICALL?Java_com_example_lamemp3_MP3Recorder_encode????(JNIEnv?*,?jclass,?jshortArray,?jshortArray,?jint,?jbyteArray);????JNIEXPORT?jint?JNICALL?Java_com_example_lamemp3_MP3Recorder_flush????(JNIEnv?*,?jclass,?jbyteArray);????JNIEXPORT?void?JNICALL?Java_com_example_lamemp3_MP3Recorder_close????(JNIEnv?*,?jclass);????#ifdef?__cplusplus??}??#endif??#endif?? com_example_lamemp3_MP3Recorder.c:
?
?
[cpp]?view plaincopy
#include?"lame-3.99.5_libmp3lame/lame.h"??#include?"com_example_lamemp3_MP3Recorder.h"????static?lame_global_flags?*glf?=?NULL;????JNIEXPORT?void?JNICALL?Java_com_example_lamemp3_MP3Recorder_init(??????????JNIEnv?*env,?jclass?cls,?jint?inSamplerate,?jint?outChannel,??????????jint?outSamplerate,?jint?outBitrate,?jint?quality)?{??????if?(glf?!=?NULL)?{??????????lame_close(glf);??????????glf?=?NULL;??????}??????glf?=?lame_init();??????lame_set_in_samplerate(glf,?inSamplerate);??????lame_set_num_channels(glf,?outChannel);??????lame_set_out_samplerate(glf,?outSamplerate);??????lame_set_brate(glf,?outBitrate);??????lame_set_quality(glf,?quality);??????lame_init_params(glf);??}????JNIEXPORT?jint?JNICALL?Java_com_example_lamemp3_MP3Recorder_encode(??????????JNIEnv?*env,?jclass?cls,?jshortArray?buffer_l,?jshortArray?buffer_r,??????????jint?samples,?jbyteArray?mp3buf)?{??????jshort*?j_buffer_l?=?(*env)->GetShortArrayElements(env,?buffer_l,?NULL);????????jshort*?j_buffer_r?=?(*env)->GetShortArrayElements(env,?buffer_r,?NULL);????????const?jsize?mp3buf_size?=?(*env)->GetArrayLength(env,?mp3buf);??????jbyte*?j_mp3buf?=?(*env)->GetByteArrayElements(env,?mp3buf,?NULL);????????int?result?=?lame_encode_buffer(glf,?j_buffer_l,?j_buffer_r,??????????????samples,?j_mp3buf,?mp3buf_size);????????(*env)->ReleaseShortArrayElements(env,?buffer_l,?j_buffer_l,?0);??????(*env)->ReleaseShortArrayElements(env,?buffer_r,?j_buffer_r,?0);??????(*env)->ReleaseByteArrayElements(env,?mp3buf,?j_mp3buf,?0);????????return?result;??}????JNIEXPORT?jint?JNICALL?Java_com_example_lamemp3_MP3Recorder_flush(??????????JNIEnv?*env,?jclass?cls,?jbyteArray?mp3buf)?{??????const?jsize?mp3buf_size?=?(*env)->GetArrayLength(env,?mp3buf);??????jbyte*?j_mp3buf?=?(*env)->GetByteArrayElements(env,?mp3buf,?NULL);????????int?result?=?lame_encode_flush(glf,?j_mp3buf,?mp3buf_size);????????(*env)->ReleaseByteArrayElements(env,?mp3buf,?j_mp3buf,?0);????????return?result;??}????JNIEXPORT?void?JNICALL?Java_com_example_lamemp3_MP3Recorder_close(??????????JNIEnv?*env,?jclass?cls)?{??????lame_close(glf);??????glf?=?NULL;??}?? ?
?
6 ?創(chuàng)建Android.mk,注意把com_example_lamemp3_MP3Recorder.c添加進(jìn)去。
?
?
[cpp]?view plaincopy
LOCAL_PATH?:=?$(call?my-dir)????include?$(CLEAR_VARS)????LAME_LIBMP3_DIR?:=?lame-3.99.5_libmp3lame????LOCAL_MODULE????:=?mp3lame??LOCAL_SRC_FILES?:=?$(LAME_LIBMP3_DIR)/bitstream.c?$(LAME_LIBMP3_DIR)/fft.c?$(LAME_LIBMP3_DIR)/id3tag.c?$(LAME_LIBMP3_DIR)/mpglib_interface.c?$(LAME_LIBMP3_DIR)/presets.c?$(LAME_LIBMP3_DIR)/quantize.c?$(LAME_LIBMP3_DIR)/reservoir.c?$(LAME_LIBMP3_DIR)/tables.c?$(LAME_LIBMP3_DIR)/util.c?$(LAME_LIBMP3_DIR)/VbrTag.c?$(LAME_LIBMP3_DIR)/encoder.c?$(LAME_LIBMP3_DIR)/gain_analysis.c?$(LAME_LIBMP3_DIR)/lame.c?$(LAME_LIBMP3_DIR)/newmdct.c?$(LAME_LIBMP3_DIR)/psymodel.c?$(LAME_LIBMP3_DIR)/quantize_pvt.c?$(LAME_LIBMP3_DIR)/set_get.c?$(LAME_LIBMP3_DIR)/takehiro.c?$(LAME_LIBMP3_DIR)/vbrquantize.c?$(LAME_LIBMP3_DIR)/version.c?com_example_lamemp3_MP3Recorder.c????include?$(BUILD_SHARED_LIBRARY)?? ?
?
7 ?AndroidManifest.xml添加權(quán)限。
?
?
[html]?view plaincopy
<uses-permission?android:name="android.permission.WRITE_EXTERNAL_STORAGE"?/>???<uses-permission?android:name="android.permission.RECORD_AUDIO"?/>?? ?
?
8 ?創(chuàng)建Builder后(上篇中有詳細(xì)介紹,這里不贅述),Clean,報(bào)錯(cuò):
?
?
[html]?view plaincopy
In?file?included?from?jni/lame-3.99.5_libmp3lame/bitstream.c:36:0:??jni/lame-3.99.5_libmp3lame/util.h:574:5:?error:?unknown?type?name?'ieee754_float32_t'??jni/lame-3.99.5_libmp3lame/util.h:574:40:?error:?unknown?type?name?'ieee754_float32_t'??make.exe:?***?[obj/local/armeabi/objs/mp3lame/lame-3.99.5_libmp3lame/bitstream.o]?Error?1??
打開(kāi)util.h
把 574行的 extern ieee754_float32_t fast_log2(ieee754_float32_t x);替換成extern float fast_log2(float x);
?
?
再次Clean,又報(bào)錯(cuò):
[html]?view plaincopy
jni/lame-3.99.5_libmp3lame/fft.c:47:32:?fatal?error:?vector/lame_intrin.h:?No?such?file?or?directory??compilation?terminated.??make.exe:?***?[obj/local/armeabi/objs/mp3lame/lame-3.99.5_libmp3lame/fft.o]?Error?1?? 打開(kāi)fft.c刪除47行#include "vector/lame_intrin.h"
?
Clean還報(bào)錯(cuò):
?
[html]?view plaincopy
In?file?included?from?jni/lame-3.99.5_libmp3lame/presets.c:29:0:??jni/lame-3.99.5_libmp3lame/set_get.h:24:18:?fatal?error:?lame.h:?No?such?file?or?directory??compilation?terminated.??make.exe:?***?[obj/local/armeabi/objs/mp3lame/lame-3.99.5_libmp3lame/presets.o]?Error?1?? 打開(kāi)set_get.h,刪除24行,#include <lame.h>
?
再次Clean,成功:
?
?
[html]?view plaincopy
[armeabi]?Compile?thumb??:?mp3lame?<=?version.c??[armeabi]?Compile?thumb??:?mp3lame?<=?com_example_lamemp3_MP3Recorder.c??[armeabi]?SharedLibrary??:?libmp3lame.so??[armeabi]?Install????????:?libmp3lame.so?=>?libs/armeabi/libmp3lame.so??
轉(zhuǎn)載于:https://www.cnblogs.com/hanfeihanfei/p/5561093.html
總結(jié)
以上是生活随笔為你收集整理的Android MP3录音实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。