【android开发】实现语音数据实时采集/播放

来源:互联网 发布:世界征服者3 mac 破解 编辑:程序博客网 时间:2024/06/10 05:42

今天无意中看到一篇关于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" >
  • 1
  • 2
  • 1
  • 2

一、AudioRecord实现核心代码介绍如下: 
1、先申明相关录制配置参数

private AudioRecord audioRecord;// 录音对象private int frequence = 8000;// 采样率 8000private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定义采样通道private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定义音频编码(16位)private byte[] buffer = null;// 录制的缓冲数组
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

2、在开始录制前,我们需要初始化AudioRecord类。

// 根据定义好的几个配置,来获取合适的缓冲大小// int bufferSize = 800;int bufferSize = AudioRecord.getMinBufferSize(frequence,        channelInConfig, audioEncoding);// 实例化AudioRecordaudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,        frequence, channelInConfig, audioEncoding, bufferSize);// 定义缓冲数组buffer = new byte[bufferSize];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3、准备开始录制,使用循环不断读取数据。

audioRecord.startRecording();// 开始录制isRecording = true;// 设置录制标记为true// 开始录制while (isRecording) {// 录制的内容放置到了buffer中,result代表存储长度int result = audioRecord.read(buffer, 0, buffer.length);/*.....result为buffer中录制数据的长度(貌似基本上都是640)。剩下就是处理buffer了,是发送出去还是直接播放,这个随便你。*/}//录制循环结束后,记得关闭录制!!if (audioRecord != null) {    audioRecord.stop();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

二、AudioTrack代码实现介绍如下: 
1、声明播放相关配置。

private AudioTrack track = null;// 录音文件播放对象private int frequence = 8000;// 采样率 8000private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定义采样通道private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定义音频编码(16位)private int bufferSize = -1;// 播放缓冲大小
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

2、初始化AudioTrack对象(初始化一次,该对象可重复使用)

// 获取缓冲 大小bufferSize = AudioTrack.getMinBufferSize(frequence, channelInConfig,        audioEncoding);// 实例AudioTracktrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequence,        channelInConfig, audioEncoding, bufferSize,        AudioTrack.MODE_STREAM);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、使用AudioTrack播放语音数据。

//将语音数据写入即可。track.write(dataArray, buffer, len);
  • 1
  • 2
  • 1
  • 2

问题一: 
由于目前的项目是实时采集,实时发送,所以需要考虑到包的大小,经测试,我们使用160个byte作为一个包传递可以做到比较良好的播放效果(也就是将一份buffer拆分成四个发送)。处理代码如下:

// 将数据通过监听接口回调出去if (audioRecordingCallback != null) {    int offset = result % MAX_DATA_LENGTH > 0 ? 1 : 0;    //将一个buffer拆分成几份小数据包 MAX_DATA_LENGTH 为包的最大byte数    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);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

问题二: 
有时候传输的过来播放声音会一卡一卡的,为了解决这样的问题,暂时使用了语音双缓冲机制来解决,问题优化很明显。代码和示意图如下: 
双缓冲示意图


1 0
原创粉丝点击