ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:20.47KB ,
资源ID:20217360      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20217360.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(实现语音数据实时采集 播放资料Word格式.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

实现语音数据实时采集 播放资料Word格式.docx

1、/开始录制 isRecording=true;/设置录制标记为 true/开始录制 while(isRecording)/录制的内容放置到了 buffer中,result 代表存储长度 int result=audioRecord.read(buffer,0,buffer.length);/*.result 为 buffer中录制数据的长度(貌似基本上都是 640)。剩下就是处理 buffer了,是发送出去还是直接播放,这个随便你。*/录制循环结束后,记得关闭录制!if(audioRecord!=null)audioRecord.stop();二、AudioTrack代码实现介绍如下:1、声明

2、播放相关配置。private AudioTrack track=null;/录音文件播放对象 private int frequence=8000;/定义音频编码(16 位)private int bufferSize=-1;/播放缓冲大小 2、初始化 AudioTrack 对象(初始化一次,该对象可重复使用)/获取缓冲 大小 bufferSize=AudioTrack.getMinBufferSize(frequence,channelInConfig,audioEncoding);/实例 AudioTrack track=new AudioTrack(AudioManager.STREAM

3、_MUSIC,frequence,channelInConfig,audioEncoding,bufferSize,AudioTrack.MODE_STREAM);3、使用 AudioTrack 播放语音数据。/将语音数据写入即可。track.write(dataArray,buffer,len);问题一:由于目前的项目是实时采集,实时发送,所以需要考虑到包的大小,经测试,我们使用 160个 byte作为一个包传递可以做到比较良好的播放效果(也就是将一份buffer拆分成四个发送)。处理代码如下:/将数据通过监听接口回调出去 if(audioRecordingCallback!=null)in

4、t offset=result%MAX_DATA_LENGTH 0?1:0;/将一个 buffer拆分成几份小数据包 MAX_DATA_LENGTH 为包的最大 byte数 for(int i=0;i result)length=result-i*MAX_DATA_LENGTH;/写到回调接口 audioRecordingCallback.onRecording(buffer,i *MAX_DATA_LENGTH,length);问题二:有时候传输的过来播放声音会一卡一卡的,为了解决这样的问题,暂时使用了语音双缓冲机制来解决,问题优化很明显。代码和示意图如下:双缓冲示意图【有朋友说要源码,那我

5、就贴下】【声音采集的源码】/*实时音频录制处理类 *记得申明系统权限:MODIFY_AUDIO_SETTINGS、RECORD_AUDIO *使用实例代码:*audioRecoderHandler=new AudioRecoderHandler(this);*audioRecoderHandler.startRecord(new AudioRecordingCallback()*@Override *public void onStopRecord(String savedPath)*&Override *public void onRecording(byte data,int s

6、tartIndex,int length)*/TODO 录制监听。处理 data即可。立即播放 or发送出去,随你。*);*author 李长军 */SuppressWarnings(deprecation)public class AudioRecoderHandler private Context context=null;/*录音数据单次回调数组最大为多少 */private static int MAX_DATA_LENGTH=160;private AudioRecord audioRecord;/录音对象 private boolean isRecording=false;/标记

7、是否正在录音中 private int frequence=8000;/定义采样通道(过时,但是使用其他的又不行 private int audioEncoding=AudioFormat.ENCODING_PCM_16BIT;/录制的缓冲数组 private File lastCacheFile=null;/记录上次录制的文件名 private CommonSharedpreferenceHelper commonSharedpreferenceHelper;private boolean shouldSaveAudio=false;/标记是否保存录音历史记录 public AudioRec

8、oderHandler(Context context)if(context=null)throw new RuntimeException(Context could not be null!);this.context=context;commonSharedpreferenceHelper=CommonSharedpreferenceHelper .getInstance(context);/*设置处理对象是否保存录音历史记录(如果设置为 false表示不保存)*param shouldSaveAudio *true表示保存(默认),false不保存,onStopRecord 回调将会返

9、回 null */public void setShouldSaveAudio(boolean shouldSaveAudio)this.shouldSaveAudio=shouldSaveAudio;/*开始录制音频 *param callBackListener *录制过程中的回调函数 */public void startRecord(AudioRecordingCallback audioRecordingCallback)RecordTask task=new RecordTask(audioRecordingCallback);task.execute();/开始执行 /*停止录制

10、 */public void stoppRecord()isRecording=false;/*删除上次录制的文件(一般是用户取消发送导致删除上次录制的内容)*return true表示删除成功,false表示删除失败,一般是没有上次录制的文件,或者文件已经被删除了 */public boolean deleteLastRecordFile()boolean success=false;if(lastCacheFile!=null&lastCacheFile.exists()success=lastCacheFile.delete();return success;/*获取音频文件的缓存地址(

11、获取的地址都是可以直接存储的,也就是文件夹已建立好),需要注意的是,缓存地址和用户的 ID 有关 *return 音频文件的缓存地址路径,如果获取失败,返回 null */private String getOutputDir()String path=null;File cacheFile=null;if(context!=null)cacheFile=context .getExternalFilesDir(android.os.Environment.DIRECTORY_MUSIC);if(cacheFile=null)Toast.makeText(context,您的 SD卡不可用,T

12、oast.LENGTH_SHORT).show();else path=cacheFile.getAbsolutePath()+/+commonSharedpreferenceHelper.getCurrentUserID()+/record;/创建文件夹 new File(path).mkdirs();return path;/*录制音频的任务类 *author 李长军 */private class RecordTask extends AsyncTask private AudioRecordingCallback audioRecordingCallback=null;public R

13、ecordTask(AudioRecordingCallback audioRecordingCallback)this.audioRecordingCallback=oRecordingCallback;Override protected void onPreExecute()/根据定义好的几个配置,来获取合适的缓冲大小 /int bufferSize=800;/设置录制标记为 true Override protected void onPostExecute(String result)audioRecord=null;if(result=null)lastCacheFile=null

14、;else lastCacheFile=new File(result);if(audioRecordingCallback!=null)audioRecordingCallback.onStopRecord(result);Override protected String doInBackground(String.params)String cacheDir=getOutputDir();String tempFileName=null;/输出的文件流 DataOutputStream dataOutputStream=null;/如果设置了要保存历史录音文件,则 创建临时文件 if(s

15、houldSaveAudio&cacheDir!=null)tempFileName=cacheDir+/+System.currentTimeMillis();cacheFile=new File(pFileName);try dataOutputStream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(cacheFile);catch(FileNotFoundException e)e.printStackTrace();/开始录制 while(isRecording)/录制的内容放置到了 buffe

16、r中,result 代表存储长度 int result=audioRecord.read(buffer,0,buffer.length);/如果设置需要保存录音文件 if(shouldSaveAudio&dataOutputStream!=null)for(int i=0;i 0?for(int i=0;audioRecordingCallback.onRecording(buffer,i *MAX_DATA_LENGTH,length);if(dataOutputStream!=null)try dataOutputStream.close();catch(IOException e)e.p

17、rintStackTrace();return tempFileName;/*监听录制过程,用于实时获取录音数据 *author 李长军 */public static interface AudioRecordingCallback /*录音数据获取回调 *param data *数据数组对象 *param startIndex *数据其开始 *param length *数据的结尾 */public void onRecording(byte data,int startIndex,int length);/*录音结束后的回调 *param savedPath *录音文件存储的路径 */p

18、ublic void onStopRecord(String savedPath);/*释放资源 */public void release()if(audioRecord!=null)audioRecord.release();audioRecord=null;【声音播放的源码】/*实时音频播放处理类 *使用示例代码如下:*audioPlayerHandler=new AudioPlayerHandler();*audioPlayerHandler.prepare();/播放前需要 prepare。可以重复 prepare */直接将需要播放的数据传入即可 *audioPlayerHandl

19、er.onPlaying(data,0,data.length);*author 李长军 */SuppressWarnings(deprecation)public class AudioPlayerHandler implements Runnable private AudioTrack track=null;/录音文件播放对象 private boolean isPlaying=false;/播放缓冲大小 /使用双缓冲机制 private ByteArrayOutputStream bufferStream0=new ByteArrayOutputStream();private Byt

20、eArrayOutputStream bufferStream1=new ByteArrayOutputStream();private int currentBuffer=-1;/记录当前哪个 buffer填充完毕,并正在播放中。-1表示都没有。0表示第一个,1 表示第二个 /互斥信号量 private Semaphore semaphore=new Semaphore(1);/是否释放资源的标志位 private boolean release=false;public AudioPlayerHandler()/获取缓冲 大小 bufferSize=AudioTrack.getMinBuf

21、ferSize(frequence,channelInConfig,audioEncoding);try /默认需要抢占一个信号量。防止播放进程执行 semaphore.acquire();catch(InterruptedException e)e.printStackTrace();/开启播放线程 new Thread(this).start();/*播放,当有新数据传入时,*param data *语音 byte数组 *param startIndex *开始的偏移量 *param length *数据长度 */public synchronized void onPlaying(byt

22、e data,int startIndex,int length)if(AudioTrack.ERROR_BAD_VALUE=bufferSize)/初始化错误 return;switch(currentBuffer)case 0:bufferStream1.write(data,startIndex,length);/如果缓冲区不够大,暂时不往下执行 if(bufferStream1.size()bufferSize)if(bufferStream0.size()bufferSize)if(bufferStream1.size()=0)currentBuffer=0;semaphore.re

23、lease();break;default:/*准备播放 */public void prepare()if(track!isPlaying)track.play();isPlaying=true;/*停止播放 */public void stop()if(track!=null)track.stop();isPlaying=false;/*释放资源 */public void release()release=true;if(track!=null)track.release();track=null;try bufferStream0.close();bufferStream0=null;

24、Override public void run()while(true)try semaphore.acquire();/如果资源释放了,则不再执行 if(release)return;if(currentBuffer=-1)continue;/如果当前是第一个 buff填充完毕 if(currentBuffer=0)runPlay(bufferStream0);/如果当前是第二个 buff填充完毕 else if(currentBuffer=1)runPlay(bufferStream1);/*执行播放语音 *param bufferStream */private void runPla

25、y(ByteArrayOutputStream bufferStream)int dataSize=bufferStream.size();byte dataArray=bufferStream.toByteArray();int count=dataSize/bufferSize;/将数据按照 buffer的大小可以切分的份数 int offset=dataSize%bufferSize=0?0:1;/如果有余数,则还得循环一次 for(int i=0;i dataSize)len=dataSize-i*bufferSize;else len=bufferSize;track.write(dataArray,i*bufferSize,len);bufferStream.reset();/重置 Stream

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1