今天无意中看到一篇关于android实现语音数据实时采集/播放的文章,感觉写得非常棒,挺全面的,所以特地转载了,还有其实还可以根据这篇博客内容考虑下视频数据实时采集、播放的实现。博客原文地址http://blog.csdn.net/lantingshuxu/article/details/53520316
最近做的项目是和语音实时采集并发送,对方实时接收并播放相关,下面记录下实现的核心代码。
很多Android开发者应该知道android有个MediaRecorder对象和MediaPlayer对象,用于录制和播放音频。这个弊端在于他们不能实时采集并发送出去,所以,我们只能使用AudioRecord和AudioTrack来实现。
记得申明权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" >
一、AudioRecord实现核心代码介绍如下:
1、先申明相关录制配置参数
private AudioRecord audioRecord;
private int frequence = 8000;
private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
private byte[] buffer = null;
2、在开始录制前,我们需要初始化AudioRecord类。
int bufferSize = AudioRecord.getMinBufferSize(frequence,
channelInConfig, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequence, channelInConfig, audioEncoding, bufferSize);
buffer = new byte[bufferSize];
3、准备开始录制,使用循环不断读取数据。
audioRecord.startRecording();
isRecording = true;
while (isRecording) {
int result = audioRecord.read(buffer, 0, buffer.length);
}
if (audioRecord != null) {
audioRecord.stop();
}
二、AudioTrack代码实现介绍如下:
1、声明播放相关配置。
private AudioTrack track = null;
private int frequence = 8000;
private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = -1;
2、初始化AudioTrack对象(初始化一次,该对象可重复使用)
bufferSize = AudioTrack.getMinBufferSize(frequence, channelInConfig,
audioEncoding);
track = new AudioTrack(AudioManager.STREAM_MUSIC, frequence,
channelInConfig, audioEncoding, bufferSize,
AudioTrack.MODE_STREAM);
3、使用AudioTrack播放语音数据。
track.write(dataArray, buffer, len);
问题一:
由于目前的项目是实时采集,实时发送,所以需要考虑到包的大小,经测试,我们使用160个byte作为一个包传递可以做到比较良好的播放效果(也就是将一份buffer拆分成四个发送)。处理代码如下:
if (audioRecordingCallback != null) {
int offset = result % MAX_DATA_LENGTH > 0 ? 1 : 0;
for (int i = 0; i < result / MAX_DATA_LENGTH + offset; i++) {
int length = MAX_DATA_LENGTH;
if ((i + 1) * MAX_DATA_LENGTH > result) {
length = result - i * MAX_DATA_LENGTH;
}
audioRecordingCallback.onRecording(buffer, i
* MAX_DATA_LENGTH, length);
}
}
问题二:
有时候传输的过来播放声音会一卡一卡的,为了解决这样的问题,暂时使用了语音双缓冲机制来解决,问题优化很明显。代码和示意图如下: