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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

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

Android中怎么錄制mp3格式文件,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。工具M(jìn)P3格式是用一個(gè)開源項(xiàng)目轉(zhuǎn)的,MP3lame,由于該項(xiàng)目用到了jni,所以需要大家配置好ndk環(huán)境,環(huán)境配置在此就不多說了,大家可以自行百度,最新的應(yīng)該很好配置。創(chuàng)建jni拷貝文件下載好后(我下載的是3.98.4版本)打開,找到libmp3lame文件,將里面的.h和.c拷貝下來,在自己的工程里創(chuàng)建jni文件夾,在jni文件夾下新建一個(gè)文件夾(我的命名為lame-3.98.4_libmp3lame,后面會用到),將剛才拷貝的文件復(fù)制進(jìn)去,然后再把include文件夾里的lame.h也拷貝進(jìn)去。創(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需要將其改為你的項(xiàng)目中的文件名,即上面說的jni下新建的文件夾。大家應(yīng)該看到了最后一句的com_maxi_mp3record_MP3Recorder.c很明顯這是我自己創(chuàng)建的.c文件。用來調(diào)用mp3lame中的接口的,對應(yīng)著我java中的com.maxi.mp3record.MP3Recorder.java。咱們先創(chuàng)建java文件。創(chuàng)建MP3Recorder.java對應(yīng)你的包名建一個(gè)MP3Recorder.java文件,該文件是java文件對應(yīng)你的包名建立即可。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實(shí)時(shí)錄制功能,可暫停,注意因踩用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;

/**

*

結(jié)束錄音

*/

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ū)掛了,采樣率手機(jī)不支持

*/

public

static

final

int

MSG_ERROR_GET_MIN_BUFFERSIZE

=

-1;

/**

*

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

*/

public

static

final

int

MSG_ERROR_CREATE_FILE

=

-2;

/**

*

初始化錄音器時(shí)撲街了

*/

public

static

final

int

MSG_ERROR_REC_START

=

-3;

/**

*

錄緊音的時(shí)候出錯(cuò)

*/

public

static

final

int

MSG_ERROR_AUDIO_RECORD

=

-4;

/**

*

編碼時(shí)掛了

*/

public

static

final

int

MSG_ERROR_AUDIO_ENCODE

=

-5;

/**

*

寫文件時(shí)掛了

*/

public

static

final

int

MSG_ERROR_WRITE_FILE

=

-6;

/**

*

沒法關(guān)閉文件流

*/

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

//

根據(jù)定義好的幾個(gè)配置,來獲取合適的緩沖大小

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

//

開啟錄音獲取音頻數(shù)據(jù)

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--*/

/*--實(shí)時(shí)錄音寫數(shù)據(jù)--*/

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

內(nèi)容取出,進(jìn)行平方和運(yùn)算

for

(int

i

=

0;

i

<

buffer.length;

i++)

{

v

+=

buffer[i]

*

buffer[i];

}

//

平方和除以數(shù)據(jù)總長度,得到音量大小。

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

}

/**

*

初始化錄制參數(shù)

*/

public

static

void

init(int

inSamplerate,

int

outChannel,

int

outSamplerate,

int

outBitrate)

{

init(inSamplerate,

outChannel,

outSamplerate,

outBitrate,

7);

}

/**

*

初始化錄制參數(shù)

quality:0=很好很慢

9=很差很快

*/

public

native

static

void

init(int

inSamplerate,

int

outChannel,

int

outSamplerate,

int

outBitrate,

int

quality);

/**

*

音頻數(shù)據(jù)編碼(PCM左進(jìn),PCM右進(jìn),MP3輸出)

*/

public

native

static

int

encode(short[]

buffer_l,

short[]

buffer_r,

int

samples,

byte[]

mp3buf);

/**

*

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

*/

public

native

static

int

flush(byte[]

mp3buf);

/**

*

結(jié)束編碼

*/

public

native

static

void

close();

}創(chuàng)建c文件在創(chuàng)建c文件,創(chuàng)建在jni下,命名就按你的java文件所在的包名命名”.”替換為“_”。例如:com_maxi_mp3record_MP3Recorder.c。當(dāng)然還得有頭文件: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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論