【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件_第1頁
【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件_第2頁
【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件_第3頁
【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件_第4頁
【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

【移動應用開發(fā)技術】Android中怎么錄制mp3格式文件

Android中怎么錄制mp3格式文件,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。工具MP3格式是用一個開源項目轉的,MP3lame,由于該項目用到了jni,所以需要大家配置好ndk環(huán)境,環(huán)境配置在此就不多說了,大家可以自行百度,最新的應該很好配置。創(chuàng)建jni拷貝文件下載好后(我下載的是3.98.4版本)打開,找到libmp3lame文件,將里面的.h和.c拷貝下來,在自己的工程里創(chuàng)建jni文件夾,在jni文件夾下新建一個文件夾(我的命名為lame-3.98.4_libmp3lame,后面會用到),將剛才拷貝的文件復制進去,然后再把include文件夾里的lame.h也拷貝進去。創(chuàng)建Android.mk在jni中創(chuàng)建文件,Android.mkLOCAL_PATH

:=

$(call

my-dir)

include

$(CLEAR_VARS)

LAME_LIBMP3_DIR

:=

lame-3.98.4_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_maxi_mp3record_MP3Recorder.c

include

$(BUILD_SHARED_LIBRARY)**注意:**LAME_LIBMP3_DIR:=lame-3.98.4_libmp3lame需要將其改為你的項目中的文件名,即上面說的jni下新建的文件夾。大家應該看到了最后一句的com_maxi_mp3record_MP3Recorder.c很明顯這是我自己創(chuàng)建的.c文件。用來調用mp3lame中的接口的,對應著我java中的com.maxi.mp3record.MP3Recorder.java。咱們先創(chuàng)建java文件。創(chuàng)建MP3Recorder.java對應你的包名建一個MP3Recorder.java文件,該文件是java文件對應你的包名建立即可。package

ject.widget;

import

java.io.File;

import

java.io.FileNotFoundException;

import

java.io.FileOutputStream;

import

java.io.IOException;

import

android.media.AudioFormat;

import

android.media.AudioRecord;

import

android.media.MediaRecorder;

import

android.os.Handler;

/**

*

<b>類功能描述:</b><div

>

*

MP3實時錄制功能,可暫停,注意因踩用Native開發(fā),不能混淆

*/

public

class

MP3Recorder

{

private

String

filePath;

private

int

sampleRate;

private

boolean

isRecording

=

false;

private

boolean

isPause

=

false;

private

Handler

handler;

/**

*

開始錄音

*/

public

static

final

int

MSG_REC_STARTED

=

1;

/**

*

結束錄音

*/

public

static

final

int

MSG_REC_STOPPED

=

2;

/**

*

暫停錄音

*/

public

static

final

int

MSG_REC_PAUSE

=

3;

/**

*

繼續(xù)錄音

*/

public

static

final

int

MSG_REC_RESTORE

=

4;

/**

*

緩沖區(qū)掛了,采樣率手機不支持

*/

public

static

final

int

MSG_ERROR_GET_MIN_BUFFERSIZE

=

-1;

/**

*

創(chuàng)建文件時撲街了

*/

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(int

sampleRate)

{

this.sampleRate

=

sampleRate;

}

public

void

setFilePath(String

filePath)

{

this.filePath

=

filePath;

}

/**

*

開片

*/

public

void

start()

{

if

(isRecording)

{

return;

}

new

Thread()

{

@Override

public

void

run()

{

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);

//

5秒的緩沖

short[]

buffer

=

new

short[sampleRate

*

(16

/

8)

*

1

*

5];

byte[]

mp3buffer

=

new

byte[(int)

(7200

+

buffer.length

*

2

*

1.25)];

FileOutputStream

output

=

null;

try

{

File

file

=

createSDFile(filePath);

output

=

new

FileOutputStream(file);

}

catch

(FileNotFoundException

e)

{

if

(handler

!=

null)

{

handler.sendEmptyMessage(MSG_ERROR_CREATE_FILE);

}

return;

}

catch

(IOException

e)

{

//

TODO

Auto-generated

catch

block

e.printStackTrace();

}

MP3Recorder.init(sampleRate,

1,

sampleRate,

32);

isRecording

=

true;

//

錄音狀態(tài)

isPause

=

false;

//

錄音狀態(tài)

try

{

try

{

audioRecord.startRecording();

//

開啟錄音獲取音頻數據

if

(mListener

!=

null)

{

mListener.wellPrepared();

}

}

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;

}

/*--End--*/

/*--實時錄音寫數據--*/

readSize

=

audioRecord.read(buffer,

0,

minBufferSize);

voiceLevel

=

getVoiceSize(readSize,

buffer);

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;

}

}

}

/*--End--*/

}

/*--錄音完--*/

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);

}

}

/*--End--*/

}

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;

}

//

獲得聲音的level

public

int

getVoiceSize(int

r,

short[]

buffer)

{

if

(isRecording)

{

try

{

long

v

=

0;

//

buffer

內容取出,進行平方和運算

for

(int

i

=

0;

i

<

buffer.length;

i++)

{

v

+=

buffer[i]

*

buffer[i];

}

//

平方和除以數據總長度,得到音量大小。

double

mean

=

v

/

(double)

r;

double

volume

=

10

*

Math.log10(mean);

return

(((int)

volume

/

10)

-

1);

}

catch

(Exception

e)

{

//

TODO

Auto-generated

catch

block

}

}

return

1;

}

/**

*

在SD卡上創(chuàng)建文件

*

*

@throws

IOException

*/

public

static

File

createSDFile(String

fileName)

throws

IOException

{

File

file

=

new

File(fileName);

if

(!isFileExists(file))

if

(file.isDirectory())

{

file.mkdirs();

}

else

{

file.createNewFile();

}

return

file;

}

private

int

voiceLevel;

public

int

getVoiceLevel()

{

return

voiceLevel;

}

public

interface

AudioStageListener

{

void

wellPrepared();

}

public

AudioStageListener

mListener;

public

void

setOnAudioStageListener(AudioStageListener

listener)

{

mListener

=

listener;

}

/**

*

錄音狀態(tài)管理

*

*

@see

RecMicToMp3#MSG_REC_STARTED

*

@see

RecMicToMp3#MSG_REC_STOPPED

*

@see

RecMicToMp3#MSG_REC_PAUSE

*

@see

RecMicToMp3#MSG_REC_RESTORE

*

@see

RecMicToMp3#MSG_ERROR_GET_MIN_BUFFERSIZE

*

@see

RecMicToMp3#MSG_ERROR_CREATE_FILE

*

@see

RecMicToMp3#MSG_ERROR_REC_START

*

@see

RecMicToMp3#MSG_ERROR_AUDIO_RECORD

*

@see

RecMicToMp3#MSG_ERROR_AUDIO_ENCODE

*

@see

RecMicToMp3#MSG_ERROR_WRITE_FILE

*

@see

RecMicToMp3#MSG_ERROR_CLOSE_FILE

*/

public

void

setHandle(Handler

handler)

{

this.handler

=

handler;

}

/*--以下為Native部分--*/

static

{

System.loadLibrary("mp3lame");

}

/**

*

初始化錄制參數

*/

public

static

void

init(int

inSamplerate,

int

outChannel,

int

outSamplerate,

int

outBitrate)

{

init(inSamplerate,

outChannel,

outSamplerate,

outBitrate,

7);

}

/**

*

初始化錄制參數

quality:0=很好很慢

9=很差很快

*/

public

native

static

void

init(int

inSamplerate,

int

outChannel,

int

outSamplerate,

int

outBitrate,

int

quality);

/**

*

音頻數據編碼(PCM左進,PCM右進,MP3輸出)

*/

public

native

static

int

encode(short[]

buffer_l,

short[]

buffer_r,

int

samples,

byte[]

mp3buf);

/**

*

據說錄完之后要刷干凈緩沖區(qū)

*/

public

native

static

int

flush(byte[]

mp3buf);

/**

*

結束編碼

*/

public

native

static

void

close();

}創(chuàng)建c文件在創(chuàng)建c文件,創(chuàng)建在jni下,命名就按你的java文件所在的包名命名”.”替換為“_”。例如:com_maxi_mp3record_MP3Recorder.c。當然還得有頭文件:com_maxi_mp3record_MP3R_maxi_mp3record_MP3Recorder.c#include

"lame-3.98.4_libmp3lame/lame.h"

#include

"com_maxi_mp3record_MP3Recorder.h"

static

lame_global_flags

*glf

=

NULL;

JNIEXPORT

void

JNICALL

Java_com_maxi_mp3record_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_maxi_mp3record_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_maxi_mp3record_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_maxi_mp3record_MP3Recorder_close(

JNIEnv

*env,

jclass

cls)

{

lame_close(glf);

glf

=

NULL;

}com_maxi_mp3record_MP3Recorder.h/*

DO

NOT

EDIT

THIS

FILE

-

it

is

machine

generated

*/

#include

<jni.h>

/*

Header

for

class

com_maxi_mp3record_MP3Recorder

*/

#ifndef

_Included_com_maxi_mp3record_MP3Recorder

#define

_Included_com_maxi_mp3record_MP3Recorder

#ifdef

__cplusplus

extern

"C"

{

#endif

/*

*

Class:

com_maxi_mp3record_MP3Recorder

*

Method:

init

*

Signature:

(IIIII)V

*/

JNIEXPORT

void

JNICALL

Java_com_maxi_mp3record_MP3Recorder_init

(JNIEnv

*,

jclass,

jint,

jint,

jint,

jint,

jint

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論