android主副MIC錄音

最近在做一個項目,要求給主副MIC分別錄音,然後再單獨播放主副MIC錄製的音頻文件,再網上找了許久,沒有找到合適的就自己琢磨了一下AudioRecord和AudioTrack,然後曲線救國實現了改功能,以下就是全部代碼了。

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import static java.lang.Daemons.start;
import static java.lang.Daemons.stop;


public class AudioRecoderUtils {
    String TAG = "AudioRecoder";
    private boolean isRecording = false;
    private boolean isPlay = false;

    byte[] mBuffer = new byte[10485760];
    Handler mHandler = new Handler(Looper.myLooper()) {
    };
    static int mBufferCount = 0;
    AudioRecord audioRecord;
    AudioTrack mAudioTrack;
    //16K採集率
    int frequency = 16000;
    //錄音通道--立體音錄音
    int channel = AudioFormat.CHANNEL_IN_STEREO;
    //16Bit
    int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    AudioManager mAudioManager;

    public AudioRecoderUtils() {

    }

    public boolean getPlay(){
        return isPlay;
    }

//停止錄音
    public void StopRecord() {
        isRecording = false;
        if(audioRecord != null){
            audioRecord.release();
        }
    }

    private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch (focusChange) {
                case AudioManager.AUDIOFOCUS_LOSS:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    start();
                    break;
            }
        }
    };

//申請音頻焦點
    private void beforePlay(Context context) {
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
    }

//退出釋放
    public void releaseAudioManager(){
        if (audioRecord != null) {
            audioRecord.release();
        }
        if (mAudioTrack != null) {
            mAudioTrack.release();
        }
        if(mAudioManager != null){
            mAudioManager.abandonAudioFocus(mAudioFocusChange);
        }
    }

//開始錄音
    public void StartRecord(Context context) {
    	new Thread(new Runnable() {
        	public void run() {
        		mBufferCount = 0;
        		isPlay = false;
       		 beforePlay();
        		int bufferSize = AudioRecord.getMinBufferSize(frequency, channel, audioEncoding);
        		if (audioRecord != null) {
            		audioRecord.release();
       			 }
        		long count = 0;
       			 long start = System.currentTimeMillis();
        		audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, frequency, 			channel, audioEncoding, bufferSize);
        		isRecording = true;
        audioRecord.startRecording();
        while (isRecording) {
            int n = audioRecord.read(mBuffer, mBufferCount, 12000);
            if (n > 0) {
                mBufferCount += n;
                long cc = Math.round(((double) (System.currentTimeMillis() - start)) / 1000.0d);
                if (cc != count) {
                    count = cc;
                }
            } else if (n < 0) {

            }
        }
                    }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                savePCM(mBuffer, mBufferCount, "stereo.pcm");
            }
        }).start();
    }
/**
//播放音頻 --- 在這裏把主副MIC錄製的數據單獨提取出來,因爲是用的CHANNEL_IN_STEREO,
//注意,因爲把數據區分出來了所以在new AudioTrack的時候要用CHANNEL_IN_MONO單通道播放
//如果要播放錄製的原音可以就要用CHANNEL_IN_STEREO,直接用
//mAudioTrack.write(mBuffer, 0, mBufferCount);                         
//  mAudioTrack.play();
*/
    public void PlayRecord(boolean isLeft) {
        if (mAudioTrack != null) {
            mAudioTrack.release();
        }
        isPlay = true;
        mAudioTrack = new AudioTrack(3, 16000, 4, 2, mBuffer.length, 0);
        if (isLeft) {
            new Thread(new Runnable() {
                public void run() {
                    byte[] bsleft = new byte[(mBufferCount / 2)];
                    int i = 0;
                    while (i < mBufferCount - 1 && (i / 2) + 1 < mBufferCount / 2) {
                        bsleft[i / 2] = mBuffer[i];
                        bsleft[(i / 2) + 1] = mBuffer[i + 1];
                        i += 4;
                    }
                    savePCM(bsleft, bsleft.length, "left.pcm");
                    if (mAudioTrack != null) {
                        try {
                            mAudioTrack.write(bsleft, 0, bsleft.length);
                            mAudioTrack.play();
                        } catch (Exception e) {
                            isPlay = false;
                        }
                    } else {
                        isPlay = false;
                    }
                }
            }).start();
        } else {
            new Thread(new Runnable() {
                public void run() {
                    byte[] bsright = new byte[(mBufferCount / 2)];
                    int j = 2;
                    while (j < mBufferCount - 1 && (j / 2) + 1 < mBufferCount / 2) {
                        bsright[(j / 2) - 1] = mBuffer[j];
                        bsright[j / 2] = mBuffer[j + 1];
                        bsright[(j / 2) + 1] = 0;
                        j += 4;
                    }
                    savePCM(bsright, bsright.length, "right.pcm");
                    if (mAudioTrack != null) {
                        try {
                            mAudioTrack.write(bsright, 0, bsright.length);
                            mAudioTrack.play();
                        } catch (Exception e) {
                        }
                    } else {
                    }
                }
            }).start();
        }

    }

//把錄製的音頻以PCM的格式寫入存儲裏面
    public String savePCM(byte[] data, int count, String name) {
        Log.d(TAG, "開始寫入 count = " + count);
        String str = null;
        if (count <= 0) {
            return str;
        }
        try {
            File path = new File(Environment.getExternalStorageDirectory() + "/record/");
            if (!path.exists())
                path.mkdirs();
            File fout = new File(Environment.getExternalStorageDirectory() + "/record/" + name);
            OutputStream out = new FileOutputStream(fout);
            out.write(data, 0, count);
            out.close();
            Log.d(TAG, "寫入成功");
            return fout.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "寫入失敗");
            return str;
        }
    }
}

PlayRecord可以分別播放左右MIC的錄音音頻,在播放之後自動保存了一個PCM文件在內置存儲裏面,
所以要記得加SD卡存儲權限和錄音權限

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

一邊錄音一邊播放

    public void StartRecord() {
        mBufferCount = 0;
        beforePlay(this);
        int bufferSize = AudioRecord.getMinBufferSize(frequency, channel, audioEncoding);
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, frequency, channel, audioEncoding, bufferSize);
        mAudioTrack = new AudioTrack(3, frequency, channel, audioEncoding, mBuffer.length, 0);
        isRecording = true;
        audioRecord.startRecording();
        while (isRecording) {
            int n = audioRecord.read(mBuffer, mBufferCount, 12000);
            mAudioTrack.write(mBuffer, 0, mBuffer.length);
            if (n > 0) {
                mAudioTrack.play();
                mBufferCount += n;
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章