Android录制音频的三种方式
对于录制音频,Android系统就都自带了一个小小的应用,可是使用起来可能不是特别的灵活。所以有提供了另外的俩种。
下边来介绍下这三种录制的方式;
1、通过Intent调用系统的录音器功能,然后在录制完毕保存以后在onActivityResult中返回录制的音频的uri,然后通过Mediaplayer进行播放
调用系统的录音器
private final static int REQUEST_RECORDER = 100;
private Uri uri;
public void recorder_Intent(){
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent,REQUEST_RECORDER);
}
获取返回的信息
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && REQUEST_RECORDER == requestCode){
uri = data.getData();
}
}
<span style=""><span style="font-size:24px;">通过Mediaplayer进行播放</span></span>
if (uri != null){
if (mediaPlayer != null) {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(RecorderActivity.this, uri);
mediaPlayer.prepare(); } catch (IOException e) {
e.printStackTrace();
} }else
Toast.makeText(RecorderActivity.this,"没有成功创建Mediaplayer",Toast.LENGTH_SHORT).show();
}
2、通过MediaRecorder来进行音频的录制:
MediaRecorder 类可用于音频和视频的捕获。再构造了一个MediaRecorder对象之后,为了捕获音频,必须调用setAudioEncoder和setAudioSource这俩个方法。
假设不调用这些方法,那么将不会录制音频(视频也相同不会),另外,MediaRecorder在准备录制之前通常还会调用setOutputFormat 和setOutputFile,
在实例化MediaRecorder之后。应该调用的第一个方法是setAudioSource。它採用一个AudioSource内部类中定义的常量作为參数,我们通常使用的常量是MediaRecorder。
AudioSource.MIC.
依据顺序,下一个调用的就是setOutputFormat ,这种方法採用在MediaRecorder.OutputFormat内部类中指定的常量作为參数:
(1)MediaRecorder.OutputFormat.MPEG_4:这个常量指定输出的文件将是一个MPEG_4文件,包括音频跟视频轨
(2)MediaRecorder.OutputFormat.RAW_AMR;这个常量表示输出一个没有不论什么容器类型的原始文件,仅仅有在捕获没有视频的音频且音频编码器是AMR_NB时才会使用这个常量。
(3)MediaRecorder.OutputFormat.THREE_GPP:这个常量指定输出的文件将是一个3gpp文件(.3gp)。它可能同一时候包括音频跟视频轨
MediaRecorder音频编码。在设置输出格式之后,能够调用setAudioEncoder方法来设置应该使用编码器,可能的值指定为MediaRecorder.AudioEncoder类中的常量。出来使用DEFAULT之外,仅仅存在一个其它的值:MediaRecorder.AudioEncoder.AMR_NB,这是自适应多速率窄带编解码器。
这样的编解码器针对语音进行了优化,因此不适应于语音之外的其它内容。默认情况下他的採样率是8kHz,码率在 4.75~12.2kbps之间。这个俩个数据对于录制语音之外的其它内容而言很低。可是,这是当前可用于MediaRecorder的唯一选择。
下来就看代码的实现:
这是录制的代码:
private MediaRecorder mediaRecorder = new MediaRecorder();
private File audioFile;
public void recorder_Media(){
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android/data/com.example.chengpengfei_d.recorderdemo/files");
path.mkdirs();
amplitude = new RecordAmplitude();
try {
audioFile = File.createTempFile("recording",".3gp",path);
mediaRecorder.setOutputFile(audioFile.getAbsolutePath());
mediaRecorder.prepare();
mediaRecorder.start();
isRecording = true;
amplitude.execute();
} catch (IOException e) {
e.printStackTrace();
}
}
这是播放的代码
case FLAG_MEDIA:
isRecording = false;
amplitude.cancel(true);
mediaRecorder.stop();
mediaRecorder.release();
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(audioFile.getAbsolutePath());
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
break;
3 使用AudioRecord录制原始音频:
这就是第三种捕获音频的方法。使用AudioRecord的类。AudioRecord是三个方法中最灵活的(由于他同意訪问原始音频流),可是他是拥有最少的内置功能。如不会自己主动压缩音频等等。
使用AudioRecord的基础知识很easy。我们仅仅须要构造一个AudioRecord类型的对象,并传入各种不同配置參数。
须要制定的第一个值就是音频源。以下使用值与之前用于MediaRecorder的值同样,其在MediaRecorder.AudioSource 中定义。实际上。这意味着能够使用MediaRecorder.AudioSource.MIC;
int audiosource = MediaRecorder.AudioSource.MIC;
须要指定的下一个值是录制的採样率,应以赫兹为单位,我们知道。MediaRecorder採样的音频是8000赫兹。
而CD质量的音频一般是44100赫兹(44100Hz)。Hz或赫兹是每秒的样本数量。
不同的Android手机硬件将可以以不同的採样率进行採样。对于我的这个样例将以11025Hz的採样率来进行採样,这是一个经常使用的採样率。
int sampleRateInHz = 11025;
接下来,须要指定捕获的音频通道的数量,在AudioFormat类中指定了用于此參数的常量。并且可依据名称理解他们。
如今将使用单声道配置。
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
随后。须要指定音频格式。
在AudioFormat类中也指定了一下各种可能的常量。
在这四个选择中,我们选择PCM_16位和PCM 8位。
PCM代表脉冲编码调制(Pulse Code Modulation) 他实际上是原始的音频样本。
因此能够设置每一个样本的分辨率为16位或8位。16位将占用很多其它的控件和处理能力,但表示的音频将更接近真实。
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
最后将须要指定缓冲区大小。
时间上能够查询AudioRecord类以获得最小缓冲区大小。查询方式是调用getMinBufferSize的静态方法,同一时候传入採样率,通道配置以及音频格式。
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig
,audioFormat);
下边就看实际的代码吧:
主要分俩个方法,还有些初始化的代码:
private boolean isPlaying = false;
private int frequency = 11025;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int audiosource = MediaRecorder.AudioSource.MIC;
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
File recordingFile = null;
RecordAudio recordAudio = null;
PlayAudio playAudio = null;
public void recorder_Audio() throws IOException {
//AudioRecord不会直接保存音频。须要自己保存
File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
path.mkdirs(); try {
recordingFile = File.createTempFile("recording", ".pcm", path);
} catch (IOException e) {
e.printStackTrace();
}
recordAudio = new RecordAudio();
recordAudio.execute();
} public void playRecorder() {
isRecording = false;
playAudio = new PlayAudio();
playAudio.execute();
}
//播放录制音频的异步任务
private class PlayAudio extends AsyncTask<Void,Integer,Void>{
@Override
protected Void doInBackground(Void... params) {
isPlaying = true;
int bufferSize = AudioTrack.getMinBufferSize(frequency,channelConfig,audioFormat);
short[] buffer = new short[bufferSize / 4];
DataInputStream dis= null;
try {
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,frequency,channelConfig,audioFormat,bufferSize,AudioTrack.MODE_STREAM);
audioTrack.play();
try {
while(isPlaying && dis.available() > 0 ){
int i = 0;
while(dis.available() > 0 && i < buffer.length){
buffer[i] = dis.readShort();
i++;
}
audioTrack.write(buffer,0,buffer.length);
}
dis.close(); } catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
<span style="white-space:pre"> </span>
//录制音频的一个异步任务;
private class RecordAudio extends AsyncTask<Void,Integer,Void>{
@Override
protected Void doInBackground(Void... params) {
isRecording = true;
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfig,audioFormat);
AudioRecord audioRecord = new AudioRecord(audiosource,frequency,channelConfig,audioFormat,bufferSize);
short [] buffer = new short[bufferSize];
audioRecord.startRecording();
int r = 0;
while(isRecording){
int bufferReadResult = audioRecord.read(buffer,0,bufferSize);
for (int i = 0; i<bufferReadResult; i++){
try {
dos.writeShort(buffer[i]); } catch (IOException e) {
e.printStackTrace();
}
}
publishProgress(new Integer(r));
r++;
}
audioRecord.stop();
dos.close();
} catch (Exception e) {
e.printStackTrace();
} return null;
} @Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
mTv_progress.setText(values[0] + "");
}
}
至此三种方式也就完了,这是一个关于音频录制的实例。通过三种不同方式的录制来达到同样的目的。可是要了解。三种的优缺点。假设想看实际效果,下载以后执行下看看吧。本实例是在Android studio中开发,假设Ecplise的话那么直接移植代码,以及清单文件的内容,应该就能够,假设不行能够联系我。
下载地址:http://download.csdn.net/detail/u012808234/9482926
Android录制音频的三种方式的更多相关文章
- uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
前言: 关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式. 一.H5+方法调用android原生方法 H5+ Android开发规范官 ...
- Android 使用OpenCV的三种方式(Android Studio)
http://blog.csdn.net/sbsujjbcy/article/details/49520791 其实最早接触OpenCV是很久很久之前的事了,大概在2013年的5,6月份,当时还是个菜 ...
- Android 生成LayoutInflater的三种方式
通俗的说,inflate就相当于将一个xml中定义的布局找出来. 因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组 ...
- 【Android进度条】三种方式实现自定义圆形进度条ProgressBar
一.通过动画实现 定义res/anim/loading.xml如下: <?xml version="1.0" encoding="UTF-8"?> ...
- Android数据存储的三种方式:SharePreferences , file , SQLite
(1)SharePreferences: 存入: SharedPreferences setter = this.getSharedPreferences("spfile", 0) ...
- Android播放音频的两种方式
一种使用MediaPlayer,使用这种方式通常是播放比较长的音频,如游戏中的背景音乐. 代码如下: private MediaPlayer mPlayer = null; mPlayer = Med ...
- Android处理XML的三种方式
http://www.cnblogs.com/zhangdongzi/archive/2011/04/14/2016434.html http://blog.csdn.net/zzp16/articl ...
- Android 音视频开发(一) : 通过三种方式绘制图片
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7456956.html 在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就 ...
- Android自定义View的三种实现方式
在毕设项目中多处用到自定义控件,一直打算总结一下自定义控件的实现方式,今天就来总结一下吧.在此之前学习了郭霖大神博客上面关于自定义View的几篇博文,感觉受益良多,本文中就参考了其中的一些内容. 总结 ...
随机推荐
- Spring Boot 起步
……………………………………………………………………………………………………………… [应用配置]application.yml [port][context-path][datasource][jp ...
- IDEA 远程调试 Tomcat 和 Debugger
一般来说我们本地环境使用Tomcat,生产环境使用GlassFish. 准备工作 明确远程服务器的 IP 地址,比如:192.168.92.128 关掉服务器防火墙:service iptables ...
- iOS: 并发编程的几个知识点
iOS 多线程问题 查阅的大部分资料都是英文的,整理完毕之后,想翻译成中文,却发现很多名字翻译成中文很难表述清楚. 所以直接把整理好的资料发出来,大家就当顺便学习学习英语. 1. Thread Saf ...
- [C++]最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583)
Question 例题3-5 最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583) 如果x+x的各个数字之和得到y,就是说x是y的生成元.给出n( ...
- ue4配置分析记录
相关代码 UObject::CallFunctionByNameWithArguments ExecuteConsoleCommand << 配置.ini[???.类名] //要先 ...
- luogu P2387 [NOI2014]魔法森林
传送门 这题似乎不好直接做,可以考虑按照\(a_i\)升序排序,然后依次加边更新答案 具体实现方法是用lct维护当前的树,这里需要维护链上最大的\(b_i\).每次加一条边,如果加完以后没有环直接加, ...
- luogu P4148 简单题
传送门 这题真简单,直接把\(CDQ\)给ban掉了 其实数据范围比较小可以直接二维树状数组,我们看数据范围,发现点的个数比N还小,可以考虑用一些奇怪的数据结构 说的就是你,\(KD tree\) \ ...
- 导弹拦截 dp
n∗lognn*lognn∗logn写法,lis[i]的意义为:所有最长上升子序列长度为i的位置上的最小a数组元素值lis[i]的意义为:所有最长上升子序列长度为i的位置上的最小a数组元素值lis[i ...
- mouseover,mouseout与mouseenter,mouseleave
针对单个元素,使用感一样. 差异提现在有子元素的情况下: mouseover和mouseout在父元素和其子元素都可以触发,当鼠标穿过一个元素时,触发次数得依子元素数量而言. mouseenter和m ...
- mysql 原理 ~ 死锁问题
一 锁1 锁的定义 1 按照宏观角度 共享锁[S锁] 又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的 ...