【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能_第4頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能

Android中怎么利用AudioRecord實(shí)現(xiàn)暫停錄音功能,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。項(xiàng)目設(shè)計(jì)的思路:由于自帶的AudioRecord沒有pauseRecord()方法,我把開始錄音-->(暫停/繼續(xù)錄音)...-->停止錄音叫做一次錄音,點(diǎn)擊一次暫停就會(huì)產(chǎn)生一個(gè)文件(.pcm),將一次錄音產(chǎn)生的所有文件名(.pcm)用一個(gè)list裝起來,點(diǎn)擊停止后將遍歷list取得所有文件路徑進(jìn)行拼接。由于考慮到以后可能要進(jìn)行語音識(shí)別,所以對(duì)程序的靈活性和拓展性都做了相應(yīng)的處理,可以通過setListener()監(jiān)聽錄音的音頻流和監(jiān)聽錄音結(jié)束。采用線程池對(duì)線程進(jìn)行管理,減少系統(tǒng)開銷。對(duì)類的說明:AudioRecorder:封裝了錄音的方法:創(chuàng)建錄音對(duì)象、開始、暫停、停止、取消,使用靜態(tài)枚舉類Status來記錄錄音的狀態(tài)。FileUtils:文件工具類,用于文件路徑的獲取PcmToWav:封裝了將.pcm文件轉(zhuǎn)化.wav文件的方法WaveHeader:wav文件頭RecordStreamListener:監(jiān)聽錄音音頻流,用于拓展業(yè)務(wù)的處理接下來是關(guān)鍵代碼部分:1、AudioRecorder類:package

com.hxl.pauserecord.record;

import

android.media.AudioFormat;

import

android.media.AudioRecord;

import

android.media.MediaRecorder;

import

android.text.TextUtils;

import

android.util.Log;

import

java.io.File;

import

java.io.FileNotFoundException;

import

java.io.FileOutputStream;

import

java.io.IOException;

import

java.util.ArrayList;

import

java.util.List;

import

java.util.concurrent.ExecutorService;

import

java.util.concurrent.Executors;

/**

*

Created

by

HXL

on

16/8/11.

*

用于實(shí)現(xiàn)錄音

暫停錄音

*/

public

class

AudioRecorder

{

//音頻輸入-麥克風(fēng)

private

final

static

int

AUDIO_INPUT

=

MediaRecorder.AudioSource.MIC;

//采用頻率

//44100是目前的標(biāo)準(zhǔn),但是某些設(shè)備仍然支持22050,16000,11025

//采樣頻率一般共分為22.05KHz、44.1KHz、48KHz三個(gè)等級(jí)

private

final

static

int

AUDIO_SAMPLE_RATE

=

16000;

//聲道

單聲道

private

final

static

int

AUDIO_CHANNEL

=

AudioFormat.CHANNEL_IN_MONO;

//編碼

private

final

static

int

AUDIO_ENCODING

=

AudioFormat.ENCODING_PCM_16BIT;

//

緩沖區(qū)字節(jié)大小

private

int

bufferSizeInBytes

=

0;

//錄音對(duì)象

private

AudioRecord

audioRecord;

//錄音狀態(tài)

private

Status

status

=

Status.STATUS_NO_READY;

//文件名

private

String

fileName;

//錄音文件

private

List<String>

filesName

=

new

ArrayList<>();

//線程池

private

ExecutorService

mExecutorService;

//錄音監(jiān)聽

private

RecordStreamListener

listener;

public

AudioRecorder()

{

mExecutorService

=

Executors.newCachedThreadPool();

}

/**

*

創(chuàng)建錄音對(duì)象

*/

public

void

createAudio(String

fileName,

int

audioSource,

int

sampleRateInHz,

int

channelConfig,

int

audioFormat)

{

//

獲得緩沖區(qū)字節(jié)大小

bufferSizeInBytes

=

AudioRecord.getMinBufferSize(sampleRateInHz,

channelConfig,

channelConfig);

audioRecord

=

new

AudioRecord(audioSource,

sampleRateInHz,

channelConfig,

audioFormat,

bufferSizeInBytes);

this.fileName

=

fileName;

}

/**

*

創(chuàng)建默認(rèn)的錄音對(duì)象

*

*

@param

fileName

文件名

*/

public

void

createDefaultAudio(String

fileName)

{

//

獲得緩沖區(qū)字節(jié)大小

bufferSizeInBytes

=

AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE,

AUDIO_CHANNEL,

AUDIO_ENCODING);

audioRecord

=

new

AudioRecord(AUDIO_INPUT,

AUDIO_SAMPLE_RATE,

AUDIO_CHANNEL,

AUDIO_ENCODING,

bufferSizeInBytes);

this.fileName

=

fileName;

status

=

Status.STATUS_READY;

}

/**

*

開始錄音

*

*/

public

void

startRecord()

{

if

(status

==

Status.STATUS_NO_READY||audioRecord==null)

{

throw

new

IllegalStateException("錄音尚未初始化,請(qǐng)檢查是否禁止了錄音權(quán)限~");

}

if

(status

==

Status.STATUS_START)

{

throw

new

IllegalStateException("正在錄音");

}

Log.d("AudioRecorder",

"===startRecord==="

+

audioRecord.getState());

audioRecord.startRecording();

String

currentFileName

=

fileName;

if

(status

==

Status.STATUS_PAUSE)

{

//假如是暫停錄音

將文件名后面加個(gè)數(shù)字,防止重名文件內(nèi)容被覆蓋

currentFileName

+=

filesName.size();

}

filesName.add(currentFileName);

final

String

finalFileName=currentFileName;

//將錄音狀態(tài)設(shè)置成正在錄音狀態(tài)

status

=

Status.STATUS_START;

//使用線程池管理線程

mExecutorService.execute(new

Runnable()

{

@Override

public

void

run()

{

writeDataTOFile(finalFileName);

}

});

}

/**

*

暫停錄音

*/

public

void

pauseRecord()

{

Log.d("AudioRecorder",

"===pauseRecord===");

if

(status

!=

Status.STATUS_START)

{

throw

new

IllegalStateException("沒有在錄音");

}

else

{

audioRecord.stop();

status

=

Status.STATUS_PAUSE;

}

}

/**

*

停止錄音

*/

public

void

stopRecord()

{

Log.d("AudioRecorder",

"===stopRecord===");

if

(status

==

Status.STATUS_NO_READY

||

status

==

Status.STATUS_READY)

{

throw

new

IllegalStateException("錄音尚未開始");

}

else

{

audioRecord.stop();

status

=

Status.STATUS_STOP;

release();

}

}

/**

*

釋放資源

*/

public

void

release()

{

Log.d("AudioRecorder",

"===release===");

//假如有暫停錄音

try

{

if

(filesName.size()

>

0)

{

List<String>

filePaths

=

new

ArrayList<>();

for

(String

fileName

:

filesName)

{

filePaths.add(FileUtils.getPcmFileAbsolutePath(fileName));

}

//清除

filesName.clear();

//將多個(gè)pcm文件轉(zhuǎn)化為wav文件

mergePCMFilesToWAVFile(filePaths);

}

else

{

//這里由于只要錄音過filesName.size都會(huì)大于0,沒錄音時(shí)fileName為null

//會(huì)報(bào)空指針

NullPointerException

//

將單個(gè)pcm文件轉(zhuǎn)化為wav文件

//Log.d("AudioRecorder",

"=====makePCMFileToWAVFile======");

//makePCMFileToWAVFile();

}

}

catch

(IllegalStateException

e)

{

throw

new

IllegalStateException(e.getMessage());

}

if

(audioRecord

!=

null)

{

audioRecord.release();

audioRecord

=

null;

}

status

=

Status.STATUS_NO_READY;

}

/**

*

取消錄音

*/

public

void

canel()

{

filesName.clear();

fileName

=

null;

if

(audioRecord

!=

null)

{

audioRecord.release();

audioRecord

=

null;

}

status

=

Status.STATUS_NO_READY;

}

/**

*

將音頻信息寫入文件

*

*/

private

void

writeDataTOFile(String

currentFileName)

{

//

new一個(gè)byte數(shù)組用來存一些字節(jié)數(shù)據(jù),大小為緩沖區(qū)大小

byte[]

audiodata

=

new

byte[bufferSizeInBytes];

FileOutputStream

fos

=

null;

int

readsize

=

0;

try

{

File

file

=

new

File(FileUtils.getPcmFileAbsolutePath(currentFileName));

if

(file.exists())

{

file.delete();

}

fos

=

new

FileOutputStream(file);//

建立一個(gè)可存取字節(jié)的文件

}

catch

(IllegalStateException

e)

{

Log.e("AudioRecorder",

e.getMessage());

throw

new

IllegalStateException(e.getMessage());

}

catch

(FileNotFoundException

e)

{

Log.e("AudioRecorder",

e.getMessage());

}

while

(status

==

Status.STATUS_START)

{

readsize

=

audioRecord.read(audiodata,

0,

bufferSizeInBytes);

if

(AudioRecord.ERROR_INVALID_OPERATION

!=

readsize

&&

fos

!=

null)

{

try

{

fos.write(audiodata);

if

(listener

!=

null)

{

//用于拓展業(yè)務(wù)

listener.onRecording(audiodata,

0,

audiodata.length);

}

}

catch

(IOException

e)

{

Log.e("AudioRecorder",

e.getMessage());

}

}

}

if

(listener

!=

null)

{

listener.finishRecord();

}

try

{

if

(fos

!=

null)

{

fos.close();//

關(guān)閉寫入流

}

}

catch

(IOException

e)

{

Log.e("AudioRecorder",

e.getMessage());

}

}

/**

*

將pcm合并成wav

*

*

@param

filePaths

*/

private

void

mergePCMFilesToWAVFile(final

List<String>

filePaths)

{

mExecutorService.execute(new

Runnable()

{

@Override

public

void

run()

{

if

(PcmToWav.mergePCMFilesToWAVFile(filePaths,

FileUtils.getWavFileAbsolutePath(fileName)))

{

//操作成功

}

else

{

//操作失敗

Log.e("AudioRecorder",

"mergePCMFilesToWAVFile

fail");

throw

new

IllegalStateException("mergePCMFilesToWAVFile

fail");

}

}

});

}

/**

*

將單個(gè)pcm文件轉(zhuǎn)化為wav文件

*/

private

void

makePCMFileToWAVFile()

{

mExecutorService.execute(new

Runnable()

{

@Override

public

void

run()

{

if

(PcmToWav.makePCMFileToWAVFile(FileUtils.getPcmFileAbsolutePath(fileName),

FileUtils.getWavFileAbsolutePath(fileName),

true))

{

//操作成功

}

else

{

//操作失敗

Log.e("AudioRecorder",

"makePCMFileToWAVFile

fail");

throw

new

IllegalStateException("makePCMFileToWAVFile

fail");

}

}

});

}

/**

*

錄音對(duì)象的狀態(tài)

*/

public

enum

Status

{

//未開始

STATUS_NO_READY,

//預(yù)備

STATUS_READY,

//錄音

STATUS_START,

//暫停

STATUS_PAUSE,

//停止

STATUS_STOP

}

/**

*

獲取錄音對(duì)象的狀態(tài)

*

*

@return

*/

public

Status

getStatus()

{

return

status;

}

/**

*

獲取本次錄音文件的個(gè)數(shù)

*

*

@return

*/

public

int

getPcmFilesCount()

{

return

filesName.size();

}

public

RecordStreamListener

getListener()

{

return

listener;

}

public

void

setListener(RecordStreamListener

listener)

{

this.listener

=

listener;

}

}2:PcmToWavpackage

com.hxl.pauserecord.record;

import

android.util.Log;

import

java.io.BufferedInputStream;

import

java.io.BufferedOutputStream;

import

java.io.File;

import

java.io.FileInputStream;

import

java.io.FileNotFoundException;

import

java.io.FileOutputStream;

import

java.io.IOException;

import

java.io.InputStream;

import

java.io.OutputStream;

import

java.text.SimpleDateFormat;

import

java.util.ArrayList;

import

java.util.Date;

import

java.util.List;

/**

*

Created

by

HXL

on

16/8/11.

*

將pcm文件轉(zhuǎn)化為wav文件

*/

public

class

PcmToWav

{

/**

*

合并多個(gè)pcm文件為一個(gè)wav文件

*

*

@param

filePathList

pcm文件路徑集合

*

@param

destinationPath

目標(biāo)wav文件路徑

*

@return

true|false

*/

public

static

boolean

mergePCMFilesToWAVFile(List<String>

filePathList,

String

destinationPath)

{

File[]

file

=

new

File[filePathList.size()];

byte

buffer[]

=

null;

int

TOTAL_SIZE

=

0;

int

fileNum

=

filePathList.size();

for

(int

i

=

0;

i

<

fileNum;

i++)

{

file[i]

=

new

File(filePathList.get(i));

TOTAL_SIZE

+=

file[i].length();

}

//

填入?yún)?shù),比特率等等。這里用的是16位單聲道

8000

hz

WaveHeader

header

=

new

WaveHeader();

//

長度字段

=

內(nèi)容的大?。═OTAL_SIZE)

+

//

頭部字段的大小(不包括前面4字節(jié)的標(biāo)識(shí)符RIFF以及fileLength本身的4字節(jié))

header.fileLength

=

TOTAL_SIZE

+

(44

-

8);

header.FmtHdrLeth

=

16;

header.BitsPerSample

=

16;

header.Channels

=

2;

header.FormatTag

=

0x0001;

header.SamplesPerSec

=

8000;

header.BlockAlign

=

(short)

(header.Channels

*

header.BitsPerSample

/

8);

header.AvgBytesPerSec

=

header.BlockAlign

*

header.SamplesPerSec;

header.DataHdrLeth

=

TOTAL_SIZE;

byte[]

h

=

null;

try

{

h

=

header.getHeader();

}

catch

(IOException

e1)

{

Log.e("PcmToWav",

e1.getMessage());

return

false;

}

if

(h.length

!=

44)

//

WAV標(biāo)準(zhǔn),頭部應(yīng)該是44字節(jié),如果不是44個(gè)字節(jié)則不進(jìn)行轉(zhuǎn)換文件

return

false;

//先刪除目標(biāo)文件

File

destfile

=

new

File(destinationPath);

if

(destfile.exists())

destfile.delete();

//合成所有的pcm文件的數(shù)據(jù),寫到目標(biāo)文件

try

{

buffer

=

new

byte[1024

*

4];

//

Length

of

All

Files,

Total

Size

InputStream

inStream

=

null;

OutputStream

ouStream

=

null;

ouStream

=

new

BufferedOutputStream(new

FileOutputStream(

destinationPath));

ouStream.write(h,

0,

h.length);

for

(int

j

=

0;

j

<

fileNum;

j++)

{

inStream

=

new

BufferedInputStream(new

FileInputStream(file[j]));

int

size

=

inStream.read(buffer);

while

(size

!=

-1)

{

ouStream.write(buffer);

size

=

inStream.read(buffer);

}

inStream.close();

}

ouStream.close();

}

catch

(FileNotFoundException

e)

{

Log.e("PcmToWav",

e.getMessage());

return

false;

}

catch

(IOException

ioe)

{

Log.e("PcmToWav",

ioe.getMessage());

return

false;

}

clearFiles(filePathList);

Log.i("PcmToWav",

"mergePCMFilesToWAVFile

success!"

+

new

SimpleDateFormat("yyyy-MM-dd

hh:mm").format(new

Date()));

return

true;

}

/**

*

將一個(gè)pcm文件轉(zhuǎn)化為wav文件

*

*

@param

pcmPath

pcm文件路徑

*

@param

destinationPath

目標(biāo)文件路徑(wav)

*

@param

deletePcmFile

是否刪除源文件

*

@return

*/

public

static

boolean

makePCMFileToWAVFile(String

pcmPath,

String

destinationPath,

boolean

deletePcmFile)

{

byte

buffer[]

=

null;

int

TOTAL_SIZE

=

0;

File

file

=

new

File(pcmPath);

if

(!file.exists())

{

return

false;

}

TOTAL_SIZE

=

(int)

file.length();

//

填入?yún)?shù),比特率等等。這里用的是16位單聲道

8000

hz

WaveHeader

header

=

new

WaveHeader();

//

長度字段

=

內(nèi)容的大?。═OTAL_SIZE)

+

//

頭部字段的大小(不包括前面4字節(jié)的標(biāo)識(shí)符RIFF以及fileLength本身的4字節(jié))

header.fileLength

=

TOTAL_SIZE

+

(44

-

8);

header.FmtHdrLeth

=

16;

header.BitsPerSample

=

16;

header.Channels

=

2;

header.FormatTag

=

0x0001;

header.SamplesPerSec

=

8000;

header.BlockAlign

=

(short)

(header.Channels

*

header.BitsPerSample

/

8);

header.AvgBytesPerSec

=

header.BlockAlign

*

header.SamplesPerSec;

header.DataHdrLeth

=

TOTAL_SIZE;

byte[]

h

=

null;

try

{

h

=

header.getHeader();

}

catch

(IOException

e1)

{

Log.e("PcmToWav",

e1.getMessage());

return

false;

}

if

(h.length

!=

44)

//

WAV標(biāo)準(zhǔn),頭部應(yīng)該是44字節(jié),如果不是44個(gè)字節(jié)則不進(jìn)行轉(zhuǎn)換文件

return

false;

//先刪除目標(biāo)文件

File

destfile

=

new

File(destinationPath);

if

(destfile.exists())

destfile.delete();

//合成所有的pcm文件的數(shù)據(jù),寫到目標(biāo)文件

try

{

buffer

=

new

byte[1024

*

4];

//

Length

of

All

Files,

Total

Size

InputStream

inStream

=

null;

OutputStream

ouStream

=

null;

ouStream

=

new

BufferedOutputStream(new

FileOutputStream(

destinationPath));

ouStream.write(h,

0,

h.length);

inStream

=

new

BufferedInputStream(new

FileInputStream(file));

int

size

=

inStream.read(buffer);

while

(size

!=

-1)

{

ouStream.write(buffer);

size

=

inStream.read(buffer);

}

inStream.close();

ouStream.close();

}

catch

(FileNotFoundException

e)

{

Log.e("PcmToWav",

e.getMessage());

return

false;

}

catch

(IOException

ioe)

{

Log.e("PcmToWav",

ioe.getMessage());

return

false;

}

if

(deletePcmFile)

{

file.delete();

}

Log.i("PcmToWav",

"makePCMFileToWAVFile

success!"

+

new

SimpleDateFormat("yyyy-MM-dd

hh:mm").format(new

Date()));

return

true;

}

/**

*

清除文件

*

*

@param

filePathList

*/

private

static

void

clearFiles(List<String>

filePathList)

{

for

(int

i

=

0;

i

<

filePathList.size();

i++)

{

File

file

=

new

File(filePathList.get(i));

if

(file.exists())

{

file.delete();

}

}

}

}3、WaveHeader類:package

com.hxl.pauserecord.record;

import

java.io.ByteArrayOutputStream;

import

java.io.IOException;

/**

*

Created

by

HXL

on

16/3/9.

*

wav文件頭

*/

public

class

WaveHeader

{

public

final

char

fileID[]

=

{'R',

'I',

'F',

'F'};

public

int

fileLength;

public

char

wavTag[]

=

{'W',

'A',

'V',

'E'};;

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論