Android 录音

手机端录音,保存录音文件

1、录音、存储相关权限申请

2、编写录音工具类,主要是开始录音、停止录音、传递录音数据的方法

a、新建一个buffer类,缓冲数据

public class ByteRingBuffer {
    private byte[] m_buffer = null;
    private int m_head = 0;
    private int m_tail = 0;

    public ByteRingBuffer()
    {
        this(262144);
    }

    public ByteRingBuffer(int bufSiz)
    {
        this.m_buffer = new byte[bufSiz + 1];
        this.m_head = 0;
        this.m_tail = 0;
    }

    public boolean isFull()
    {
        return (this.m_tail + 1) % this.m_buffer.length == this.m_head;
    }

    public boolean isEmpty()
    {
        return this.m_tail == this.m_head;
    }

    public void clear()
    {
        this.m_head = (this.m_tail = 0);
    }

    public int getCapaSize()
    {
        return this.m_buffer.length - 1;
    }

    public int getBusySize()
    {
        if (this.m_head <= this.m_tail) {
            return this.m_tail - this.m_head;
        }
        return this.m_buffer.length - (this.m_head - this.m_tail);
    }

    public int getFreeSize()
    {
        return this.m_buffer.length - getBusySize() - 1;
    }

    public boolean put(byte[] buff, int offset, int size)
    {
        if ((buff == null) || (offset + size > buff.length)) {
            return false;
        }
        if (getFreeSize() < size) {
            return false;
        }
        int num_cpy = size;
        if (this.m_tail + num_cpy > this.m_buffer.length) {
            num_cpy = this.m_buffer.length - this.m_tail;
        }
        System.arraycopy(buff, offset, this.m_buffer, this.m_tail, num_cpy);
        if (size - num_cpy > 0) {
            System.arraycopy(buff, offset + num_cpy, this.m_buffer, 0, size - num_cpy);
        }
        this.m_tail = ((this.m_tail + size) % this.m_buffer.length);
        return true;
    }

    public boolean get(byte[] buff, int offset, int size)
    {
        if ((buff == null) || (offset + size > buff.length)) {
            return false;
        }
        if (getBusySize() < size) {
            return false;
        }
        int num_cpy = size;
        if (this.m_head + num_cpy > this.m_buffer.length) {
            num_cpy = this.m_buffer.length - this.m_head;
        }
        System.arraycopy(this.m_buffer, this.m_head, buff, offset, num_cpy);
        if (size - num_cpy > 0) {
            System.arraycopy(this.m_buffer, 0, buff, offset + num_cpy, size - num_cpy);
        }
        this.m_head = ((this.m_head + size) % this.m_buffer.length);
        return true;
    }
}

b、新建录音工具类

AudioRecorder

音频相关参数设置

bufferSize = AudioTrack.getMinBufferSize(16000,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
        mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, BufferSize);

开始录音

public synchronized void startRecord(IRecordCallback callback){
        mCallback = callback;
        if (mAudioRecord == null) {
            mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, BufferSize);
        }
        isRecord = true;
        mAudioRecord.startRecording();
        recordOutBuff = new byte[BufferSize];
        recordThread = new Thread(){
            @Override
            public void run() {
                while(isRecord){
                    int recordRet = mAudioRecord.read(recordOutBuff, 0, recordOutBuff.length);
                    if (recordRet != 0) {
                        // 持续的音频数据
                        saveRecordData(recordOutBuff);
                    }
                }
            }
        };
        recordThread.start();
    }

public void saveRecordData(byte data[]) {
        byte mByteBuffer[] = new byte[AUDIO_FRAME_DATA_LENGTH];
        mRingBuffer.put(data, 0, data.length);

        if (mRingBuffer.getBusySize() >= AUDIO_FRAME_DATA_LENGTH) {
            mRingBuffer.get(mByteBuffer, 0, AUDIO_FRAME_DATA_LENGTH);
            if(null != mCallback){
                mCallback.onAudioInputData(mByteBuffer);
            }
        }
    }

 

停止录音,释放资源

public synchronized void stopRecord(){
                if(isRecord) {
            try {
                isRecord = false;
                recordThread.join();
            } catch (Exception e) {

            }
            if (mAudioRecord != null) {
                mAudioRecord.stop();
                mAudioRecord.release();
                mAudioRecord = null;
            }
        }
    }

完整的工具类:

public class AudioRecorder {
    private static final String TAG = "AudioRecorder";

    private int BufferSize = 0;
    private IRecordCallback mCallback;

    private ByteRingBuffer mRingBuffer;
    //每一帧数据的长度
    private static final int AUDIO_FRAME_DATA_LENGTH = 1280;

    private boolean isRecord = false;
    //录音工具录
    private AudioRecord mAudioRecord;
    private Thread recordThread;
    private byte[] recordOutBuff;

    public AudioRecorder(){
        mRingBuffer = new ByteRingBuffer();
        BufferSize = AudioTrack.getMinBufferSize(16000,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
        mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, BufferSize);
    }


    /**
     * 录音
     * @param callback
     */
    public synchronized void startRecord(IRecordCallback callback){
        Log.v(TAG, "startRecord ");
        mCallback = callback;
        if (mAudioRecord == null) {
            mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, BufferSize);
        }
        isRecord = true;
        mAudioRecord.startRecording();
        recordOutBuff = new byte[BufferSize];
        recordThread = new Thread(){
            @Override
            public void run() {
                while(isRecord){
                    int recordRet = mAudioRecord.read(recordOutBuff, 0, recordOutBuff.length);
                    if (recordRet != 0) {
                        saveRecordData(recordOutBuff);
                    }
                }
            }
        };
        recordThread.start();
    }

    /**
     *
     */
    public void saveRecordData(byte data[]) {
        byte mByteBuffer[] = new byte[AUDIO_FRAME_DATA_LENGTH];
        mRingBuffer.put(data, 0, data.length);

        if (mRingBuffer.getBusySize() >= AUDIO_FRAME_DATA_LENGTH) {
            mRingBuffer.get(mByteBuffer, 0, AUDIO_FRAME_DATA_LENGTH);
            if(null != mCallback){
                mCallback.onAudioInputData(mByteBuffer);
            }
        }
    }

    /**
     * 停止录音
     */
    public synchronized void stopRecord(){
        Log.v(TAG, "stopRecord ");
        if(isRecord) {
            try {
                isRecord = false;
                recordThread.join();
            } catch (Exception e) {

            }
            if (mAudioRecord != null) {
                mAudioRecord.stop();
                mAudioRecord.release();
                mAudioRecord = null;
            }
        }
    }
}

 

调用方法:

AudioRecorder audioRecorder = new AudioRecorder();
audioRecorder.startRecord(callback);

回调CallBack里面定义接口

onAudioInputData(byte[] byte);传递录音数据

可以在此回调方法里面,保存录音数据或直接将录音数据传递给服务端

 

如保存到文件:

// 创建文件,保存数据
public void createFile(String fileDir, String fileName) {
        synchronized (lock) {
            if (null != fileName) {
                try {
                    File dir = new File(fileDir);
                    if (!dir.exists()) {
                        dir.mkdir();
                    }
                    //保存录音文件
                    File file = new File(fileDir + "/" + fileName + ".pcm");
                    file.createNewFile();
                    Log.d(TAG, "createFile file path = " + file.getPath());
                    fileOutputStream = new FileOutputStream(file);
                } catch (Exception e) {
                    e.printStackTrace();
                    fileOutputStream = null;
                }
            }
        }
    }
// 停止录音时关闭读写
public void closeFile() {
        synchronized (lock) {
            if (null != fileOutputStream) {
                try {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                    fileOutputStream = null;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    fileOutputStream = null;
                }
            }
        }
    }

写入文件:在回调方法里面写入,开始录音后,会持续写入文件

@Override
        public void onAudioInputData(byte[] data) {
            //录音数据定入文件
            synchronized (lock) {
                try {
                    //音频写入文件
                    if (null != fileOutputStream) {
                        fileOutputStream.write(data, 0, data.length);
                    }
                } catch (Exception e) {
                    Log.e(TAG, "----录音异常");
                }
            }
        }

停止录音后,可以根据文件名获取文件

 

你可能感兴趣的:(录音,音频)