木瓜妮子多媒体开发教程---第五天---Android下音频录制和播放
来源:互联网 发布:易经入门书籍推荐 知乎 编辑:程序博客网 时间:2024/04/28 00:45
Android下音频录制和播放
1. 音频的捕获
在通常情况下,捕获音频有三种不同方法,每种方法都有优点和弱点。第一种方法是使用意图,这是种最简单的方式,通过一个意图利用已有的、提供录制功能的原生应用程序,它虽然最简单却最不灵活;第二种是使用MediaRecord类,它比较难于使用,但是能在原有类基础上添加更多的灵活性。最后一种方法是使用AudioRecord类,它提供了最大的灵活性,但是也最原始,使用比较复杂。
2. 使用意图捕获音频
在MediaStore.Audio.Media类中存在的变量RECORD_SOUND_ACTION可用来实现创建该意图的动作:
int Mediarecord = 0; Intentintent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); startActivityForResult(intent,Mediarecord);//通过意图捕获音频
通过使用startActivityForResult方法,触发内置录音机,并当用户录制完成后返回录音。程序中创建了一个名为Mediarecord的常量,并将它传递给startActivityForResult,从而可以确定任何onActivityResult调用的来源。当有startActivityForResult函数触发时,任何活动在返回时都会调用onActivityResult方法,这个常量连同意图一起传入,以此来进行区分。onActivityResult方法是一个用以处理意图返回数据的一个必需的方法,在这里onActivityResult方法可以对意图返回的录音播放。
3. MediaRecord类
在AndroidSDK中包含了一个Mediarecord类,可以利用它来建立自己的音频录制功能,在创建音频功能的过程中,可以控制录制音频的时间长度等,从而有了更多的灵活性。在完成一个Mediarecord的对象的创建后,为了捕获音频,需要调用setAudioEncoderh、setAudioSource和setOutputFormat、setOutputFile的方法,方法调用顺序也是对结果有很大影响的。下图是MediaRecorder的状态机。
简单的启动mediarecord的方法:
medirecoder= newMediaRecorder();medirecoder.setAudioSource(MediaRecorder.AudioSource.MIC);//音频来自于麦克风录制medirecoder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//输出格式为3gpmedirecoder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//编码方式File path = newFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/AudioPlay/");path.mkdirs();//如果目录不存在则创建try { audiofile=File.createTempFile("record_temp",".3gp",path);//创建临时文件} catch(IOException e) { e.printStackTrace();}medirecoder.setOutputFile(audiofile.getAbsolutePath());try { medirecoder.prepare();} catch(IllegalStateException e) { e.printStackTrace();} catch(IOException e) { e.printStackTrace();}medirecoder.start();//启动Mediarecord 如何停止录制,调用stop方法,并通过release释放:medirecoder.stop();medirecoder.release();
4. AudioRecord类
借助这个类可以操作原始音频,主要是实现边录边播(AudioRecord+AudioTrack)以及对音频的实时处理,如会说话的汤姆猫。因为类本身没有多少内置功能,所以只需要构造一个AudioRecord类型的对象,对其传入不同的配置参数,来实现语音的实时处理,用代码来实现对音频的封装、编码和压缩。AudioRecord类的输出是PCM语音数据,无法直接保存成音频文件,不能直接被播放器播放,这也就给编程带来了一定难度。
AudioTrack用于管理单个的音频资源。 在构造AudioTrack实例时,会涉及到流类型、采样率、通道配置、音频格式、缓冲大小、播放模式等因素。AudioTrack支持STREAM_VOICE_CALL、STREAM_SYSTEM、STREAM_RING、STREAM_MUSIC和STREAM_ALARM等流类型。AudioTrack支持44100Hz、22050Hz、11025Hz等采样率。AudioTrack支持单声道(CHANNEL_OUT_MONO)、立体声(CHANNEL_OUT_STEREO)等两种通道。AudioTrack支持ENCODING_PCM_16BIT、ENCODING_PCM_8BIT等两种编码格式。AudioTrack支持两种播放模式:静态模式(staticmode)和流模式(Streamingmode)。其中静态模式由于没有从Java层向原生层传递数据造成的延迟,时延很小。当音频流较大不足以在音频缓冲中一次写入时,可采用流模式。AudioTrack的播放状态包括PLAYSTATE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING等。AudioTrack实例的状态包括STATE_INITIALIZED、STATE_NO_STATIC_DATA、STATE_UNINITIALIZED等。
向音频缓冲中添加数据的方法为write()。在设置音频缓冲时,其大小与采样率、通道和音频格式有关。其计算公式为:缓冲大小=最小帧数×(通道==CHANNEL_OUT_STEREO?2:1)×(音频格式==PCM16?2:1)。而最小帧数则受制于采样率和音频设备的延迟等因素。
4.实现播放功能
Android支持多种用于播放的音频文件格式和编解码器。在MediaPlayer中,根据数据源为元数据、音频文件、音频流的不同情况,有着相应的处理过程。基本的过程如下:
1)播放raw中音频文件
如果音频文件位于Android工程的“res/raw”文件夹下。播放音频文件的过程为:
<span style="white-space:pre"></span> MediaPlayer mp=MediaPlayer.create(context, R.raw.sound_file); mp.start();
2)播放音频文件
如果音频文件的路径为PATH_OF_FILE,播放音频文件的过程为:
MediaPlayer mp=newMediaPlayer(); try { mp.setDataSource(PATH_OF_FILE); //设置数据源 mp.prepare(); } catch(IllegalArgumentException e) { // TODOAuto-generated catch block e.printStackTrace(); } catch(SecurityException e) { // TODOAuto-generated catch block e.printStackTrace(); } catch(IllegalStateException e) { // TODOAuto-generated catch block e.printStackTrace(); } catch(IOException e) { // TODOAuto-generated catch block e.printStackTrace(); } mp.start();
3)播放音频流
如果音频文件的URL地址为URL_ADDRESS,播放音频流的过程为:
MediaPlayer mp=newMediaPlayer(); try { mp.setDataSource(URL_ADDRESS); mp.prepare(); }catch (IllegalArgumentException e) { e.printStackTrace(); }catch (SecurityException e) { e.printStackTrace(); }catch (IllegalStateException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } //设置数据源 mp.start();
可以通过下面的语句完成对存储完成的临时存储的录音文件的读取。
mediplayer.setDataSource(audiofile.getAbsolutePath());
4)实现音量的控制
将对音量的控制写成了一个独立的方法,并且采用了动态布局,在MainActivity的代码中将控制条添加进布局中。
<span style="color:#0000c0;"> </span><span style="color: rgb(0, 0, 192); white-space: pre;"></span> LinearLayout mLayout = new LinearLayout(this);mLayout.setOrientation(LinearLayout.VERTICAL);LP_MW = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);mLayout.setLayoutParams(LP_MW);
protected void audioVolume (){setVolumeControlStream(AudioManager.STREAM_MUSIC);final AudioManager am = ( AudioManager) getSystemService(MainActivity.AUDIO_SERVICE);final SeekBar volume = new SeekBar(this);final TextView textview1 = new TextView(this);volume.setLayoutParams(LP_MW);volume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_MUSIC));volume.setProgress(am.getStreamVolume(AudioManager.STREAM_MUSIC));volume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar arg0) {}@Overridepublic void onStartTrackingTouch(SeekBar arg0) {}@Overridepublic void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {am.setStreamVolume(AudioManager.STREAM_MUSIC, arg1, 0);//why set am to final typetextview1.setText("Volume:"+arg1+"%");}});mLayout.addView(textview1);//mLayout是布局文件mLayout.addView(volume);}
项目完成,上效果图:
对于这个项目其实还可以深入,我还想研究一下类内部究竟是如何降噪的,播放时的扩音,总之,不能总是习惯类提供给我们的便利,对于一些算法还是值得去研究一下。
- 木瓜妮子多媒体开发教程---第五天---Android下音频录制和播放
- 木瓜妮子多媒体开发教程---第六天---Android下的音频均衡器
- 木瓜妮子多媒体开发教程---第一天---Android环境搭建和Helloworld项目测试
- 木瓜妮子多媒体开发教程---第三天---Android下图像灰度化和二值化
- 木瓜妮子多媒体开发教程---第二天---Android下对图像的几何操作
- 木瓜妮子多媒体开发教程---第四天---Android下图像空间滤波
- Android 多媒体——音频播放录制、视频播放、相机
- Android开发笔记-音频录制/播放&音频
- Android开发笔记-音频录制/播放&音频
- Linux下OSS音频录制和播放
- Android 音频录制和播放问题
- Android中的多媒体音频和视频播放
- 音频录制和播放
- 播放和录制音频
- 录制音频和播放音频
- 【Android开发】多媒体应用开发-使用MediaPlayer播放音频
- 【Android开发】多媒体应用开发-使用SoundPool播放音频
- Android音频录制与播放
- ArrayBlockingQueue和ExecutorService的理解与感悟
- MessageBox
- 如何一个人打造日PV百万的网站架构——SDCC 2013讲师曹力专访
- 关于SetWindowOrg和SetViewportOrg函数的说明!
- Fiddler进行Android抓包踩过的一个坑
- 木瓜妮子多媒体开发教程---第五天---Android下音频录制和播放
- 黑马程序员----------类与对象(三)
- 需要这样一个记事本-12 C#命名空间介绍
- 四步走循序渐进克服SAT阅读关
- 经典排序算法--快速排序
- dojo tree的使用
- maven中进行junit测试报class not found的问题
- iOS设备上回声消除的例子
- 联诚发(LCF):用大数据看小间距屏