音频开发——录音与播放、音量调节
来源:互联网 发布:python 迭代器 定义 编辑:程序博客网 时间:2024/05/21 10:17
Android提供了两个API用于实现录音功能:
android.media.AudioRecord和android.media.MediaRecorder,对比如下:
会说话的汤姆猫,以及其他语音识别与处理的软件(如百度翻译、科大讯飞翻译),获取音源数据肯定是使用了AudioRecord。用AudioRecord录音,并实现WAV格式封装,未经过任何压缩,输出的音频文件很大。MediaRecorder由于已经实现了音频数据的压缩和编码,支持.aac(API = 16) .amr .3gp等,因此,输出的音频文件较小。
当然,这里说的文件大小跟采样率以及采集通道的选择还有直接关系。比如AudioRecord,16000的采用率,单声道,那么录制1秒获取的原始数据量为16000个short,也就是32000个字节;双通道就再乘以2,即64000个字节。
使用MediaRecorder比较简单:
public void startAudioRecord(String saveFilePath){ mediaRecorder = new MediaRecorder(); recordFile = new File(saveFilePath); // 判断,若当前文件已存在,则删除 if (recordFile.exists()) { recordFile.delete(); } mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mediaRecorder.setAudioChannels(2); mediaRecorder.setAudioSamplingRate(16000); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mediaRecorder.setOutputFile(recordFile.getAbsolutePath()); mediaRecorder.setMaxDuration(1000 * 60 * 60); try { // 准备好开始录音 mediaRecorder.prepare(); mediaRecorder.start(); logd("录音开始,"+recordFile.getAbsolutePath()); TGTConfig.isAudioRecordStart = true; } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); logd(e); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); logd(e); } } public void stopAudioRecord(){ if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.release(); mediaRecorder = null; logd("录音结束,"+recordFile.getAbsolutePath()); TGTConfig.isAudioRecordStart = false; } }
使用AudioRecord稍微复杂一点,网上有现成的代码,这里仅供参考:
第一步,创建对象,获取buffer大小,这里的采样率取16000;44100(44.1kHz)是目前普遍使用的频率,但是某些设备仍然支持22050,16000,11025;
public final static int AUDIO_SAMPLE_RATE = 16000;public final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;private void creatAudioRecord(String savePath) { // 获取音频文件路径 AudioName = savePath.replace(".wav", ".raw"); NewAudioName = savePath; // 获得缓冲区字节大小 bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); // 创建AudioRecord对象 audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);}
AudioFormat.CHANNEL_IN_STEREO是指双通道,还有很多channel选项,但不一定每个都支持,不支持会报错导致crash;另外,双通道获取的数据通常是交替存放的,比如:最终buffer(short类型举例)内存放的数据将会是:short1,short2,short1,short2,……这样的顺序;
第二步,用一个子线程处理音频数据:
private void saveAudioRecord(final String AudioName, final String NewAudioName){ new Thread(new Runnable() { @Override public void run() { writeDateTOFile(AudioName);//往文件中写入裸数据 TGTConfig.audioRecordEnable = true;//裸数据文件写结束,才接受新的录制指令 logd("audio Record Enable again."); copyWaveFile(AudioName, NewAudioName);//给裸数据加上头文件 new File(AudioName).delete();//删除裸数据 logd("录音文件大小:"+ AdbUtil.sendAdb("du -sh "+ NewAudioName, true).replace(NewAudioName,"")); } }).start(); }//writeDateTOFile方法和copyWaveFile方法请参照其他网上资料
//获取数据的核心方法是
readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);其中audiodata可以是short数组或者byte数组,我认为使用byte数组,方便直接通过FileOutputStream进行文件存储,而使用short数组,方便对音频数据进行处理,比如计算分贝等等。当然short和byte数组的转换也是很方便的,可以自己实现,也可以使用ByteBuffer类:
ByteBuffer.wrap(audiodata).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(buffer2);
这里进行转换的话,有一个大端(高位存高地址)小端(地位存高地址)的概念需要注意。
播放录音采用MediaPlayer,举例如下:
//播放携带的音频资源文件public void startPlayAudio(int resourceId) { if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.reset(); } try { mediaPlayer = MediaPlayer.create(context, resourceId); mediaPlayer.start(); } catch (Exception e) { e.printStackTrace(); logd(e); }}
//播放音频文件public void startPlayAudio(String filePath){ playFile = new File(filePath); if (playFile.exists() && playFile != null) { Uri uri = Uri.fromFile(playFile); if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.reset(); } mediaPlayer = MediaPlayer.create(context, uri); if(mediaPlayer != null) { mediaPlayer.start(); TGTConfig.isAudioPlayStart = true; logd("播放录音文件," + playFile.getAbsolutePath()); //监听MediaPlayer播放完成 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer paramMediaPlayer) { // TODO Auto-generated method stub logd("录音播放结束," + playFile.getAbsolutePath()); TGTConfig.isAudioPlayStart = false; } }); }else{ logd("播放录音失败"); } }else{ logd("无法播放录音,文件不存在"); }}
调节音量也很简单,举例如下:
AudioManager audioManager;public boolean setVolume(int volume, int stream) { if (audioManager != null) { /*logd("max value is " + audioManager.getStreamMaxVolume(stream) + ",min value is " + audioManager.getStreamMinVolume(stream));*/ audioManager.setStreamVolume(stream, volume, 0); if (audioManager.getStreamVolume(stream) == volume) { return true; } } else { audioManager = (AudioManager) App.getContext().getSystemService(Context.AUDIO_SERVICE); return false; } return false;}
- 音频开发——录音与播放、音量调节
- iOS开发 调节音频音量,音频混合
- android闹钟开发(四)--音乐播放与音量调节
- android闹钟开发(四)--音乐播放与音量调节
- Android 音频 录音与播放
- iphone 录音与播放同时 音量问题
- html音频音量调节
- 使用AudioManager调节播放器音量的开发实例
- android 的 c层 实现 音乐播放与音量调节
- iOS开发 音频播放、录音、视频播放、拍照、视频录制
- iOS开发:音频播放、录音、视频播放、拍照、视频录制
- iOS开发--音频播放、录音、视频播放、拍照、视频录制
- 播放音乐并调节音量
- 录音,播放音频
- 录音/播放音频
- 音频播放\录音
- Android官方开发文档Training系列课程中文版:管理音频播放之控制APP的音量与播放
- 【Android应用实例之五】调节播放器音量——AudioManager的应用
- 4、进制转换
- Java基础进阶知识点
- Java正确创建线程池方式
- svn同步时指定某些文件不显示
- laravel 学习记录
- 音频开发——录音与播放、音量调节
- 【树链剖分】LGP3613 睡觉困难综合征
- js打开word文档,而不是下载
- 物联网让智慧城市梦想成真
- tensorflow基础(二)--TF训练和变量
- 使用cmd遇到的问题
- PHP基础
- UE4蓝图节点文档翻译【目录】--- Add Event/Collision
- boost构造和解析json