1. 程式人生 > >Android開發之PCM音訊採集

Android開發之PCM音訊採集

通過ijkplayer播放視訊,需求:移動端實現實時對講。即pcm音訊錄製實時推送到裝置端,本篇主要記錄pcm音訊採集

為保證語音連續性,bufferSize 1m在網不好的情況下可能出現語音時斷時續,需要調小bufferSize 到最合適的值


import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

/**
 * Created by idea on 2017/12/11.
 */

public class AudioRecordManager {

    private static AudioRecordManager instance;

    boolean isRecording = false; //true表示正在錄音

    AudioRecord audioRecord=null;

    int bufferSize=0;//最小緩衝區大小

    int sampleRateInHz = 8000;//取樣率

    int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; //單聲道

    int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //量化位數

    String TAG="AudioRecordManager";

    private AudioRecordManager(){
        //計算最小緩衝區
        bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);
        bufferSize= bufferSize>320?320:bufferSize;
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig, audioFormat, bufferSize);//建立AudioRecorder物件
    }

    public static AudioRecordManager getInstance(){
        if(instance==null){
            synchronized (AudioRecordManager.class){
                if(instance==null){
                    instance = new AudioRecordManager();
                }
            }
        }
        return instance;
    }

    /**
     * 開始音訊採集
     * @param onAudioRecordListener
     */
    public void startRecording(OnAudioRecordListener onAudioRecordListener) {
        setOnAudioRecordListener(onAudioRecordListener);

        if(audioRecord==null){
            audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig, audioFormat, bufferSize);//建立AudioRecorder物件
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                isRecording = true;
                try {
                    byte[] buffer = new byte[bufferSize];
                    audioRecord.startRecording();//開始錄音
                    while (isRecording) {
                        int bufferReadResult = audioRecord.read(buffer,0,bufferSize);
                        if(getOnAudioRecordListener()!=null){
                            getOnAudioRecordListener().onVoiceRecord(buffer,bufferReadResult);
                        }
                    }
                    audioRecord.stop();//停止錄音
                } catch (Throwable t) {
                    Log.e(TAG, "Recording Failed");
                }
            }
        }).start();
    }

    /**
     * 停止音訊採集
     */
    public void stopRecording() {
        isRecording = false;
        setOnAudioRecordListener(null);
    }

    public void onDestroy(){
        audioRecord.release();
        audioRecord = null;
    }

    public interface OnAudioRecordListener{

        /**
         * 採集到的音訊資訊資料回撥到上層,通過IdeaVideoView 傳送到裝置端
         * @param data
         */
        void onVoiceRecord(byte[] data,int size);

    }

    private OnAudioRecordListener onAudioRecordListener;

    public OnAudioRecordListener getOnAudioRecordListener() {
        return onAudioRecordListener;
    }

    public void setOnAudioRecordListener(OnAudioRecordListener onAudioRecordListener) {
        this.onAudioRecordListener = onAudioRecordListener;
    }
}

呼叫例項程式碼塊

/**
     * '開始採集音訊資料
     */
    public void startRecordVoice() {
        AudioRecordManager.getInstance()
                          .startRecording(new AudioRecordManager.OnAudioRecordListener() {

            @Override
            public void onVoiceRecord(byte[] data, int size) {
                //向ijkplayer傳送資料
                playerManager.pushVoice(data, size, new VideoView.OnPushVoiceCallback() {
                    @Override
                    public void onPushVoiceFail() {
                        onError();
                    }
                });
            }
        });
    }


    /**
     * 停止對講
     */
    private void stopPushVoice() {
        AudioRecordManager.getInstance().stopRecording();
    }