(四) AudioRecord录制pcm音频

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huanghuangjin/article/details/82807300
public class AudioRecordActivity extends BaseActivity {

    public static void startAudioRecordActivity(Activity activity) {
        activity.startActivity(new Intent(activity, AudioRecordActivity.class));
    }

    // AudioRecord
    @BindView(R.id.btn_audiorecord_start) Button mStartBtn;
    private AudioRecord mAudioRecord;
    private ExecutorService mExecutorService = Executors.newFixedThreadPool(5);
    private boolean isRecording = false;
    private int bufferSizeInBytes_re;
    // AudioTrack
    @BindView(R.id.btn_audiorecord_play) Button mPlayBtn;
    private AudioTrack mAudioTrack;
    private boolean isPlaying = false;
    private int bufferSizeInBytes_play;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_audiorecord);
        mUnbinder = ButterKnife.bind(this);

        // AudioRecord
        int audioSource = MediaRecorder.AudioSource.MIC; // 表示音频源,来自麦克风
        int sampleRateInHz = 44100; // 采样率
        int channelConfig = AudioFormat.CHANNEL_IN_STEREO; // 输入,声道设置:android支持双声道立体声和单声道。MONO单声道,STEREO立体声
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 样本格式
        bufferSizeInBytes_re = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 采样需要的缓冲区的大小
        mAudioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes_re);

        // AudioTrack
        bufferSizeInBytes_play = AudioTrack.getMinBufferSize(sampleRateInHz, AudioFormat.CHANNEL_OUT_STEREO, audioFormat);
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRateInHz, AudioFormat.CHANNEL_OUT_STEREO,
                audioFormat,
                bufferSizeInBytes_play, AudioTrack.MODE_STREAM, mAudioRecord.getAudioSessionId()); // AudioTrack 可以直接关联 AudioRecord 的SessionId,不关联也可以
    }

    private void stopRecord() { // 停止录音
        isRecording = false;
        if (mStartBtn!=null) mStartBtn.setText("开始录音");
        if (mAudioRecord.getState()==AudioRecord.STATE_INITIALIZED) { // 还有其他状态,RECORDSTATE_RECORDING 等
            LogUtils.d("mydebug---", "state == AudioRecord.STATE_INITIALIZED");
            mAudioRecord.stop(); // 停止
        }
    }

    private void stopPlay() { // 停止播放
        isPlaying = false;
        if (mPlayBtn!=null) mPlayBtn.setText("开始播放");
        mAudioTrack.pause(); // 立即暂停,mAudioTrack.stop函数会播放完缓冲队列中的数据,才停止
        mAudioTrack.flush(); // 清空缓冲区数据
    }

    @OnClick({R.id.btn_audiorecord_start, R.id.btn_audiorecord_play, R.id.btn_audiorecord_stop})
    void click(View view) {
        final String sdcrad = Environment.getExternalStorageDirectory().getAbsolutePath();
        switch (view.getId()) {
            case R.id.btn_audiorecord_start: // 开始录音
                stopPlay();
                if (!isRecording) {
                    isRecording = true;
                    mStartBtn.setText("录音中...");
                    mExecutorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(100);
                                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); // 声音线程的最高级别,优先程度较THREAD_PRIORITY_AUDIO要高
                            } catch (Exception e) {}

                            mAudioRecord.startRecording(); // 开始录音
                            byte buf[] = new byte[bufferSizeInBytes_re];
                            File file = new File(sdcrad+"/audiorecord.pcm");
                            FileOutputStream fos = null;
                            try {
                                fos = new FileOutputStream(file);
                                int len = -1;
                                while (isRecording) {
                                    len = mAudioRecord.read(buf, 0, bufferSizeInBytes_re); // 读取录制的音频(pcm),返回值为读取的长度
                                    if (len>0) fos.write(buf, 0, len); else stopRecord();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                            if (fos!=null) {
                                try {
                                    fos.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    });
                }
                break;
            case R.id.btn_audiorecord_play: // 播放录音
                stopRecord();
                if (!isPlaying) {
                    isPlaying = true;
                    mPlayBtn.setText("播放中...");
                    mExecutorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(100);
                                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); // 声音线程的最高级别,优先程度较THREAD_PRIORITY_AUDIO要高
                            } catch (Exception e) {}

                            mAudioTrack.play();
                            File file = new File(sdcrad+"/audiorecord.pcm");
                            FileInputStream fis = null;
                            try {
                                fis = new FileInputStream(file);
                                byte buf[] = new byte[bufferSizeInBytes_play];
                                int len = -1;
                                while (isPlaying && (len = fis.read(buf))!=-1) {
                                    mAudioTrack.write(buf, 0, len);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                if (fis!=null) {
                                    try {
                                        fis.close();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        stopPlay();
                                    }
                                });
                            }
                        }
                    });
                }
                break;
            case R.id.btn_audiorecord_stop:
                stopPlay();
                stopRecord();
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mAudioRecord!=null) {
            stopRecord();
            mAudioRecord.release();
        }
        if (mAudioTrack!=null) {
            stopPlay();
            mAudioTrack.release();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/82807300
今日推荐