【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能_第1页
【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能_第2页
【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能_第3页
【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能_第4页
【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android中怎么利用AudioRecord实现暂停录音功能

Android中怎么利用AudioRecord实现暂停录音功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。项目设计的思路:由于自带的AudioRecord没有pauseRecord()方法,我把开始录音-->(暂停/继续录音)...-->停止录音叫做一次录音,点击一次暂停就会产生一个文件(.pcm),将一次录音产生的所有文件名(.pcm)用一个list装起来,点击停止后将遍历list取得所有文件路径进行拼接。由于考虑到以后可能要进行语音识别,所以对程序的灵活性和拓展性都做了相应的处理,可以通过setListener()监听录音的音频流和监听录音结束。采用线程池对线程进行管理,减少系统开销。对类的说明:AudioRecorder:封装了录音的方法:创建录音对象、开始、暂停、停止、取消,使用静态枚举类Status来记录录音的状态。FileUtils:文件工具类,用于文件路径的获取PcmToWav:封装了将.pcm文件转化.wav文件的方法WaveHeader:wav文件头RecordStreamListener:监听录音音频流,用于拓展业务的处理接下来是关键代码部分: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.

*

用于实现录音

暂停录音

*/

public

class

AudioRecorder

{

//音频输入-麦克风

private

final

static

int

AUDIO_INPUT

=

MediaRecorder.AudioSource.MIC;

//采用频率

//44100是目前的标准,但是某些设备仍然支持22050,16000,11025

//采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级

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;

//

缓冲区字节大小

private

int

bufferSizeInBytes

=

0;

//录音对象

private

AudioRecord

audioRecord;

//录音状态

private

Status

status

=

Status.STATUS_NO_READY;

//文件名

private

String

fileName;

//录音文件

private

List<String>

filesName

=

new

ArrayList<>();

//线程池

private

ExecutorService

mExecutorService;

//录音监听

private

RecordStreamListener

listener;

public

AudioRecorder()

{

mExecutorService

=

Executors.newCachedThreadPool();

}

/**

*

创建录音对象

*/

public

void

createAudio(String

fileName,

int

audioSource,

int

sampleRateInHz,

int

channelConfig,

int

audioFormat)

{

//

获得缓冲区字节大小

bufferSizeInBytes

=

AudioRecord.getMinBufferSize(sampleRateInHz,

channelConfig,

channelConfig);

audioRecord

=

new

AudioRecord(audioSource,

sampleRateInHz,

channelConfig,

audioFormat,

bufferSizeInBytes);

this.fileName

=

fileName;

}

/**

*

创建默认的录音对象

*

*

@param

fileName

文件名

*/

public

void

createDefaultAudio(String

fileName)

{

//

获得缓冲区字节大小

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("录音尚未初始化,请检查是否禁止了录音权限~");

}

if

(status

==

Status.STATUS_START)

{

throw

new

IllegalStateException("正在录音");

}

Log.d("AudioRecorder",

"===startRecord==="

+

audioRecord.getState());

audioRecord.startRecording();

String

currentFileName

=

fileName;

if

(status

==

Status.STATUS_PAUSE)

{

//假如是暂停录音

将文件名后面加个数字,防止重名文件内容被覆盖

currentFileName

+=

filesName.size();

}

filesName.add(currentFileName);

final

String

finalFileName=currentFileName;

//将录音状态设置成正在录音状态

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

//将多个pcm文件转化为wav文件

mergePCMFilesToWAVFile(filePaths);

}

else

{

//这里由于只要录音过filesName.size都会大于0,没录音时fileName为null

//会报空指针

NullPointerException

//

将单个pcm文件转化为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一个byte数组用来存一些字节数据,大小为缓冲区大小

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

建立一个可存取字节的文件

}

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)

{

//用于拓展业务

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

关闭写入流

}

}

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

}

}

});

}

/**

*

将单个pcm文件转化为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");

}

}

});

}

/**

*

录音对象的状态

*/

public

enum

Status

{

//未开始

STATUS_NO_READY,

//预备

STATUS_READY,

//录音

STATUS_START,

//暂停

STATUS_PAUSE,

//停止

STATUS_STOP

}

/**

*

获取录音对象的状态

*

*

@return

*/

public

Status

getStatus()

{

return

status;

}

/**

*

获取本次录音文件的个数

*

*

@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文件转化为wav文件

*/

public

class

PcmToWav

{

/**

*

合并多个pcm文件为一个wav文件

*

*

@param

filePathList

pcm文件路径集合

*

@param

destinationPath

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

}

//

填入参数,比特率等等。这里用的是16位单声道

8000

hz

WaveHeader

header

=

new

WaveHeader();

//

长度字段

=

内容的大小(TOTAL_SIZE)

+

//

头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)

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标准,头部应该是44字节,如果不是44个字节则不进行转换文件

return

false;

//先删除目标文件

File

destfile

=

new

File(destinationPath);

if

(destfile.exists())

destfile.delete();

//合成所有的pcm文件的数据,写到目标文件

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;

}

/**

*

将一个pcm文件转化为wav文件

*

*

@param

pcmPath

pcm文件路径

*

@param

destinationPath

目标文件路径(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();

//

填入参数,比特率等等。这里用的是16位单声道

8000

hz

WaveHeader

header

=

new

WaveHeader();

//

长度字段

=

内容的大小(TOTAL_SIZE)

+

//

头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)

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标准,头部应该是44字节,如果不是44个字节则不进行转换文件

return

false;

//先删除目标文件

File

destfile

=

new

File(destinationPath);

if

(destfile.exists())

destfile.delete();

//合成所有的pcm文件的数据,写到目标文件

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等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论