音频这方面很博大精深,我这里肯定讲不了什么高级的东西,最多也只是一些基础类知识,首先,我们要介绍一下AndroID他提供的录音类,实际上他有两个,一个是MediaRecorder,还有一个就是我们今天要用到的AudioRecord,那他们有什么区别呢?
一.区别
MediaRecorder和AudioRecord都可以录制音频,区别是MediaRecorder录制的音频文件是经过压缩后的,需要设置编码器。并且录制的音频文件可以用系统自带的Music播放器播放。
而AudioRecord录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。
PCM可能更加可以理解为音频的源文件
二.优缺点
AudioRecord
主要是实现边录边播以及对音频的实时处理,这个特性让他更适合在语音方面有优势
优点:语音的实时处理,可以用代码实现各种音频的封装
缺点:输出是PCM格式文件,如果保存成音频文件,是不能够被播放器播放的,所以必须先写代码实现数据编码以及压缩
MediaRecorder
已经集成了录音、编码、压缩等,支持少量的录音音频格式,大概有,aac,amr,3gp等
优点:集成,直接调用相关接口即可,代码量小
缺点:无法实时处理音频;输出的音频格式不是很多,例如没有输出mp3格式文件
三.准备工作
我们要实现的是一个实时的去录音,播放,停止等功能的测试案例,那我们肯定要准备点什么,比如说,我这里先创建一个项目――PCMSample
然后写个布局
layout_main.xml
<?xml version="1.0" enCoding="utf-8"?><linearLayoutxmlns:androID="http://schemas.androID.com/apk/res/androID"androID:layout_wIDth="match_parent"androID:layout_height="match_parent"androID:orIEntation="vertical"androID:padding="10dp"><buttonandroID:ID="@+ID/startAudio"androID:layout_wIDth="match_parent"androID:layout_height="wrap_content"androID:background="@drawable/button_bg"androID:text="开始录音"androID:textcolor="@androID:color/white"/><buttonandroID:ID="@+ID/stopAudio"androID:layout_wIDth="match_parent"androID:layout_height="wrap_content"androID:layout_marginBottom="10dp"androID:layout_margintop="5dp"androID:background="@drawable/button_bg"androID:enabled="false"androID:text="停止录音"androID:textcolor="@androID:color/white"/><buttonandroID:ID="@+ID/playAudio"androID:layout_wIDth="match_parent"androID:layout_height="wrap_content"androID:background="@drawable/button_bg"androID:enabled="false"androID:text="播放音频"androID:textcolor="@androID:color/white"/><buttonandroID:ID="@+ID/deleteAudio"androID:layout_wIDth="match_parent"androID:layout_height="wrap_content"androID:layout_margintop="5dp"androID:background="@drawable/button_bg"androID:text="删除PCM"androID:textcolor="@androID:color/white"/><ScrollVIEwandroID:ID="@+ID/mScrollVIEw"androID:layout_wIDth="match_parent"androID:layout_height="0dp"androID:layout_margintop="5dp"androID:layout_weight="1"><TextVIEwandroID:ID="@+ID/tv_audio_succeess"androID:layout_wIDth="wrap_content"androID:layout_height="wrap_content"androID:text="初始化完成...."androID:textcolor="@color/colorAccent"/></ScrollVIEw></linearLayout>
可以预览一下
这里我给按钮加了一个扁平的效果,实际上写了一个xml,很简单
button_bg.xml
<?xml version="1.0" enCoding="utf-8"?><selector xmlns:androID="http://schemas.androID.com/apk/res/androID"><item androID:state_pressed="true"><shape><corners androID:radius="30dp"/><solID androID:color="@color/colorPrimary"/></shape></item><item androID:state_pressed="false"><shape><corners androID:radius="30dp"/><solID androID:color="@color/colorPrimaryDark"/></shape></item></selector>
好的,回到正题,我们这里有四个按钮,分别是开始。停止,播放,和删除,我们就是要实现这四个功能,在此之前,我们还需要做的事情就是添加权限,因为我们要录音和写内存卡文件,所有需要这两个权限即可
<!--录音--><uses-permission androID:name="androID.permission.RECORD_AUdio" /><!--读取SD卡--><uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" />
这里初始化什么的就不说了,我们直接进入正题
四.开始录音
开始录音的话,这里,我们定义一个变量isRecording去控制,这样就比较好结束了,而且要注意的是,录音是不能放在UI线程的,你懂的,所以我们可以写一个开始录音的方法
//开始录音public voID StartRecord() {Log.i(TAG,"开始录音");//16K采集率int frequency = 16000;//格式int channelConfiguration = AudioFormat.CHANNEL_CONfigURATION_MONO;//16Bitint audioEnCoding = AudioFormat.ENCoding_PCM_16BIT;//生成PCM文件file = new file(Environment.getExternalStorageDirectory().getabsolutePath() + "/reverseme.pcm");Log.i(TAG,"生成文件");//如果存在,就先删除再创建if (file.exists())file.delete();Log.i(TAG,"删除文件");try {file.createNewfile();Log.i(TAG,"创建文件");} catch (IOException e) {Log.i(TAG,"未能创建");throw new IllegalStateException("未能创建" + file.toString());}try {//输出流OutputStream os = new fileOutputStream(file);bufferedoutputstream bos = new bufferedoutputstream(os);DataOutputStream dos = new DataOutputStream(bos);int bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioEnCoding);AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,audioEnCoding,bufferSize);short[] buffer = new short[bufferSize];audioRecord.startRecording();Log.i(TAG,"开始录音");isRecording = true;while (isRecording) {int bufferReadResult = audioRecord.read(buffer,bufferSize);for (int i = 0; i < bufferReadResult; i++) {dos.writeShort(buffer[i]);}}audioRecord.stop();dos.close();} catch (Throwable t) {Log.e(TAG,"录音失败");}}
首先,这里我们了解一下采样率,编码,音频流等基本的概念,剩下的大多是读写流的 *** 作了,我们通过创建一个AudioRecord去写pcm文件,定义一个while循环,用我们刚才定义的isRecording控制,所以,我们的点击事件就
case R.ID.startAudio:Thread thread = new Thread(new Runnable() {@OverrIDepublic voID run() {StartRecord();Log.e(TAG,"start");}});thread.start();printLog("开始录音");buttonEnabled(false,true,false);break;
这里要注意一下thread.start();开启线程,同时打印出log,具体代码如下
//打印logprivate voID printLog(final String resultString) {tv_audio_succeess.post(new Runnable() {@OverrIDepublic voID run() {tv_audio_succeess.append(resultString + "\n");mScrollVIEw.fullScroll(ScrollVIEw.FOCUS_DOWN);}});}
这里,我为了防止ANR,所以控制了一下按钮的焦点
//获取/失去焦点private voID buttonEnabled(boolean start,boolean stop,boolean play) {startAudio.setEnabled(start);stopAudio.setEnabled(stop);playAudio.setEnabled(play);}
好的,我们运行一下
看起来没什么变化,但是你去内存卡中就会发现多了一个pcm文件
当然,你只是点击启动录音是不会生成这个pcm文件的,你需要点击停止停止录音的按钮
五.停止录音
停止录音很简单,我们控制通过改变写入流就好了
case R.ID.stopAudio:isRecording = false;buttonEnabled(true,false,true);printLog("停止录音");break;
这样才会生成PCM
六播放音频
现在有了PCM我们可以试着去播放了,写一个播放的方法
//播放文件public voID PlayRecord() {if(file == null){return;}//读取文件int musicLength = (int) (file.length() / 2);short[] music = new short[musicLength];try {inputStream is = new fileinputStream(file);BufferedinputStream bis = new BufferedinputStream(is);DatainputStream dis = new DatainputStream(bis);int i = 0;while (dis.available() > 0) {music[i] = dis.readShort();i++;}dis.close();AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,16000,AudioFormat.CHANNEL_CONfigURATION_MONO,AudioFormat.ENCoding_PCM_16BIT,musicLength * 2,AudioTrack.MODE_STREAM);audioTrack.play();audioTrack.write(music,musicLength);audioTrack.stop();} catch (Throwable t) {Log.e(TAG,"播放失败");}}
正如上面所说,我们播放需要用到AudioTrack,调用他的play方法以及设置一些参数即可
七.删除音频
删除音频只需要删除这个pcm文件就行
//删除文件private voID delefile() {if(file == null){return;}file.delete();printLog("文件删除成功");}
这就是大致的录音逻辑,虽然看起来很简单,但是这正是现在很多语音和音频的最基础部分,特别是语音,如果你从事语音的工作,我相信你会感谢我的!
好了,最后放上完整的代码:
MainActivity
package com.liuguilin.pCMSample;import androID.media.AudioFormat;import androID.media.AudioManager;import androID.media.AudioRecord;import androID.media.AudioTrack;import androID.media.MediaRecorder;import androID.os.Bundle;import androID.os.Environment;import androID.support.v7.app.AppCompatActivity;import androID.util.Log;import androID.vIEw.VIEw;import androID.Widget.button;import androID.Widget.ScrollVIEw;import androID.Widget.TextVIEw;import java.io.BufferedinputStream;import java.io.bufferedoutputstream;import java.io.DatainputStream;import java.io.DataOutputStream;import java.io.file;import java.io.fileinputStream;import java.io.fileOutputStream;import java.io.IOException;import java.io.inputStream;import java.io.OutputStream;public class MainActivity extends AppCompatActivity implements VIEw.OnClickListener {public static final String TAG = "PCMSample";//是否在录制private boolean isRecording = false;//开始录音private button startAudio;//结束录音private button stopAudio;//播放录音private button playAudio;//删除文件private button deleteAudio;private ScrollVIEw mScrollVIEw;private TextVIEw tv_audio_succeess;//pcm文件private file file;@OverrIDeprotected voID onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentVIEw(R.layout.activity_main);initVIEw();}//初始化VIEwprivate voID initVIEw() {mScrollVIEw = (ScrollVIEw) findVIEwByID(R.ID.mScrollVIEw);tv_audio_succeess = (TextVIEw) findVIEwByID(R.ID.tv_audio_succeess);printLog("初始化成功");startAudio = (button) findVIEwByID(R.ID.startAudio);startAudio.setonClickListener(this);stopAudio = (button) findVIEwByID(R.ID.stopAudio);stopAudio.setonClickListener(this);playAudio = (button) findVIEwByID(R.ID.playAudio);playAudio.setonClickListener(this);deleteAudio = (button) findVIEwByID(R.ID.deleteAudio);deleteAudio.setonClickListener(this);}//点击事件@OverrIDepublic voID onClick(VIEw v) {switch (v.getID()) {case R.ID.startAudio:Thread thread = new Thread(new Runnable() {@OverrIDepublic voID run() {StartRecord();Log.e(TAG,false);break;case R.ID.stopAudio:isRecording = false;buttonEnabled(true,true);printLog("停止录音");break;case R.ID.playAudio:PlayRecord();buttonEnabled(true,false);printLog("播放录音");break;case R.ID.deleteAudio:delefile();break;}}//打印logprivate voID printLog(final String resultString) {tv_audio_succeess.post(new Runnable() {@OverrIDepublic voID run() {tv_audio_succeess.append(resultString + "\n");mScrollVIEw.fullScroll(ScrollVIEw.FOCUS_DOWN);}});}//获取/失去焦点private voID buttonEnabled(boolean start,boolean play) {startAudio.setEnabled(start);stopAudio.setEnabled(stop);playAudio.setEnabled(play);}//开始录音public voID StartRecord() {Log.i(TAG,"录音失败");}}//播放文件public voID PlayRecord() {if(file == null){return;}//读取文件int musicLength = (int) (file.length() / 2);short[] music = new short[musicLength];try {inputStream is = new fileinputStream(file);BufferedinputStream bis = new BufferedinputStream(is);DatainputStream dis = new DatainputStream(bis);int i = 0;while (dis.available() > 0) {music[i] = dis.readShort();i++;}dis.close();AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,"播放失败");}}//删除文件private voID delefile() {if(file == null){return;}file.delete();printLog("文件删除成功");}}
如果你想去调试这些pcm文件做音频测试的话,我推荐使用Audacity这个软件,可以看到,我直接点击左上角的file-导入-源文件,然后设置16K
这样就可以调试了
最后,放一张完整的截图
以上所述是小编给大家介绍的AndroID音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能全部内容,希望文章能够帮你解决Android音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)