Android音视频开发入门(三)

任务目标

用AudioRecord采集PCM数据到SDCard,并用AudioTrack播放采集的PCM数据,最后实现读写wav文件。

AudioRecord采集PCM数据

AudioRecord可以记录从硬件设备输入的音频,生成PCM格式的音频数据。有三个读取数据的方法可以选择read(byte[], int, int), read(short[], int, int) 或 read(ByteBuffer, int),用户可以根据最方便的存储格式来选择使用那个方法。

1.实现一个AudioRecord实例

看一下AudioRecord的构造方法
public AudioRecord (int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
API介绍上有这么一段
Class constructor. Though some invalid parameters will result in an IllegalArgumentException exception, other errors do not. Thus you should call getState() immediately after construction to confirm that the object is usable.

类构造函数。一些无效的参数会导致IllegalArgumentException异常,但是不会返回其他错误。因此你应该在AudioRecord构造函数之后立马调用getState()方法来确定AudioRecord对象是否可用。
我看好多人都没有调用这个函数,不过也没有太大影响。下面分析一下构造函数的参数

- audioSource: 音源,常用麦克风MediaRecorder.AudioSource.MIC,也可以是通话的话音( MediaRecorder.AudioSource.VOICE_CALL,MediaRecorder.AudioSource.VOICE_DOWNLINK即对方声音,MediaRecorder.AudioSource.VOICE_UPLINK即本方声音 )
- sampleRateInHz: 采样率,单位是Hz(赫兹)。如8000,16000,11025,22050,44100等,这儿选择44100是目前所有的设备都支持的采样率。
-channelConfig: 声道数,分为单声道(AudioFormat.CHANNEL_IN_MONO)和立体声(AudioFormat.CHANNEL_STEREO)。因为有的设备不支持立体声,这儿我们选择单声道。
-audioFormat: 音频格式,AudioFormat.ENCODING_PCM_16BIT、AudioFormat.ENCODING_PCM_8BIT和AudioFormat.ENCODING_PCM_FLOAT可选,同样为了设备支持直接选择ENCODING_PCM_16BIT.
-bufferSizeInBytes: 最小缓冲区大小,可通过getMinBufferSize()方法确定。设置的值比getMinBufferSize()还小则会导致初始化失败。注意: 这个大小并不保证在负荷下的流畅录制,应根据预期的频率来选择更高的值,AudioRecord实例在推送新数据时使用此值。

2.初始化一个Buffer

该buffer大小要大于等于AudioRecord读取数据的buffer大小

3.调用startRecording()

startRecording()之后就可以不断调用 read函数取得声音数据。这个函数是阻塞试的,下层没有足够的数据会停在它里面。一般来说,在一个独立线程里处理录音的数据采集比较好。

4.写数据

创建一个数据流,一边从AudioRecord读取声音数据到初始化的buffer,一边将buffer中的数据导入数据流

5.停止采集并关闭数据流

以上就是采集PCM数据的步骤,不要忘记添加权限,写数据需要读写权限,用麦克风录音需要麦克风权限

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

我之前就是忘记请求麦克风权限导致getState()获取的状态总是0(未初始化成功状态)。下面是部分代码

	/**
     * 采集PCM数据线程
     */
    private class RecordThread extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            //返回成功创建AudioRecord对象所需要的最小缓冲区大小
            //注意:这个大小并不保证在负荷下的流畅录制,应根据预期的频率来选择更高的值,AudioRecord实例在推送新数据时使用此值。
            int mMinBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);
            //创建AudioRecord
            mRecord = new AudioRecord(MediaRecorder.AudioSource.MIC/*用麦克风采集*/, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, mMinBufferSize);
            //API提示创建AudioRecord后立马调用getState获取其可用状态
            int state = mRecord.getState();
            Log.w("record state", "state =" + state);
            //这儿为了方便看到采集的pcm数据直接写入到sd卡中
            File file = new File(Environment.getExternalStorageDirectory().getPath(), "record.pcm");
            if (file.exists()) {
                boolean isDelete = file.delete();
                Log.w("file delete", "isDelete = " + isDelete);
            }
            try {
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
                outputStream = new DataOutputStream(bufferedOutputStream);
                byte[] buffer = new byte[mMinBufferSize];
                mRecord.startRecording();
                isRecording = true;
                while (isRecording) {
                    int read = mRecord.read(buffer, 0, buffer.length);
                    //如果读取音频数据没有出现错误,则将数据写入到文件
                    if (AudioRecord.ERROR_INVALID_OPERATION != read) {
                  
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值