音频的采集比较简单,可通过AudioRecord
实现音频采集,普通应用一般只能采集到麦克风输出的声音(MediaRecorder.AudioSource.MIC)
,系统应用可以采集系统声音(MediaRecorder.AudioSource.REMOTE_SUBMIX)
。
AudioRecord
的构造需要以下几个参数:
-
1、audioSource
声音类型,麦克风或系统 -
2、sampleRateInHz
赫兹,赫兹越高声音质量越好,一般是44100 或 48000 -
3、channelConfig
声道,一般是双声道采集 -
4、audioFormat
格式,一般是16位 -
5、bufferSizeInBytes
缓存大小,可通过AudioRecord.getMinBufferSize
获取
// TODO system app use MediaRecorder.AudioSource.REMOTE_SUBMIX
private static final int AUDIO_RESOURCE = MediaRecorder.AudioSource.MIC;
private final static int AUDIO_SAMPLE_RATE = 48000;
private final static int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
private final static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private int mAudioResource = AUDIO_RESOURCE;
private int mAudioSampleRate = AUDIO_SAMPLE_RATE;
private int mChannelConfig = CHANNEL_CONFIG;
private int mAudioFormat = AUDIO_FORMAT;
private int mBufferSizeInBytes;
this.mBufferSizeInBytes = AudioRecord.getMinBufferSize(mAudioSampleRate, mChannelConfig, mAudioFormat);
mAudioRecord = new AudioRecord(mAudioResource, mAudioSampleRate, mChannelConfig, mAudioFormat, mBufferSizeInBytes * 2);
初始化完成之后,可通过read
方法读取音频数据
public void startCapture() {
Log.i(TAG, "startRecord");
if (mAudioRecord == null) {
Log.w(TAG, "invalid AudioRecord");
return;
}
//判断AudioRecord的状态是否初始化完毕
//在AudioRecord对象构造完毕之后,就处于AudioRecord.STATE_INITIALIZED状态了。
int state = mAudioRecord.getState();
if (state == AudioRecord.STATE_UNINITIALIZED) {
Log.w(TAG, "AudioRecord STATE_UNINITIALIZED");
stopCapture();
return;
}
Log.i(TAG, "startRecording");
mAudioRecord.startRecording();
//开启线程读取数据
mThread = new Thread(mRecordTask);
mThread.start();
}
private Runnable mRecordTask = new Runnable() {
@Override
public void run() {
Log.i(TAG, "recordTask run");
final byte[] data = new byte[mBufferSizeInBytes];
isRecording = true;
while (isRecording) {
int state;
if ((state = mAudioRecord.getRecordingState()) != AudioRecord.RECORDSTATE_RECORDING) {
Log.i(TAG, "recordTask state: " + state);
continue;
}
//读取采集数据到缓冲区中,read就是读取到的数据量
final int read = mAudioRecord.read(data, 0, mBufferSizeInBytes);
if (AudioRecord.ERROR_INVALID_OPERATION != read && AudioRecord.ERROR_BAD_VALUE != read)
try {
if (read <= 0) {// != mFrameSize) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w(TAG, e);
}
continue;
}
if (mAudioCallback != null) {
mAudioCallback.onCaptureAudioCallback(data);
}
} catch (Exception e) {
Log.w(TAG, e);
}
}
Log.i(TAG, "recordTask end");
}
};
结束录音的时候,关闭AudioRecord
public void stopCapture() {
Log.i(TAG, "stopRecord");
isRecording = false;
if (mAudioRecord != null) {
try {
mAudioRecord.stop();
Log.i(TAG, "audioRecord.stop()");
} catch (Exception e) {
Log.w(TAG, e);
}
try {
mAudioRecord.release();
Log.i(TAG, "audioRecord.release()");
} catch (Exception e) {
Log.w(TAG, e);
}
}
}
通过回调将录制的声音数据回调给调用者,调用者可存储声音数据到文件,通过软件Audacity
可播放原始的pcm
声音数据。
网友评论