




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 城區(qū)供水設(shè)施智能化改造項(xiàng)目目標(biāo)與任務(wù)
- 保險(xiǎn)公司與能源企業(yè)2025年度能源項(xiàng)目保險(xiǎn)服務(wù)合同
- 2025年度高科技研發(fā)中心建設(shè)合同管理規(guī)范
- 二零二五年度新型離婚協(xié)議書及共同財(cái)產(chǎn)處理
- 2025年度瓷磚品牌形象授權(quán)與加盟合同
- 二零二五年度快遞配送網(wǎng)絡(luò)建設(shè)合作協(xié)議
- 2025年度個(gè)人租房合同及租后房屋智能化改造協(xié)議
- 2025年度路燈工程燈具節(jié)能性能測試與認(rèn)證合同
- 2025年度宅基地租賃與農(nóng)村公共設(shè)施建設(shè)合同
- 2025年度養(yǎng)老養(yǎng)生生產(chǎn)經(jīng)營場地租賃合同
- 加油站地罐交接及容積表關(guān)系
- 電信寬帶注銷委托書
- 新教材人教版高中數(shù)學(xué)必修第二冊全冊教案
- 班(組)戰(zhàn)斗動作訓(xùn)練教案
- 農(nóng)產(chǎn)品電商運(yùn)營-完整全套課件
- 唐河縣泌陽凹陷郭橋天然堿礦產(chǎn)資源開采與生態(tài)修復(fù)方案
- 科研項(xiàng)目匯報(bào)ppt
- 建設(shè)工程項(xiàng)目法律風(fēng)險(xiǎn)防控培訓(xùn)稿PPT講座
- “不作為、慢作為、亂作為”自查自糾報(bào)告范文(三篇)
- 上海市楊浦區(qū)2022屆初三中考二模英語試卷+答案
- 課件《中國式現(xiàn)代化》
評論
0/150
提交評論