自学内容网 自学内容网

Android 录音AudioRecord

AudioRecord是安卓多媒体框架中用于录制音频的工具。它支持录制原始音频数据,即PCM数据,PCM数据不能被播放器直接播放,需要编码压缩成常见音频格式才能被播放器识别。通常生成PCM文件之后可将PCM文件转成WAV文件一般的播放器便可直接播放了。

接下来处理AudioRecord操作。

1.初始化AudioRecord

先了解几个概念:

audioSource:音频来源
sampleRateInHz:采样率,以赫兹为单位。目前,只有44100Hz是保证在所有设备上都可以使用的速率(最适合人耳的),但是其他速率(例如22050、16000和11025)可能在某些设备上可以使用;如果用于语音识别的话根据不同厂商需要采用不同的采样率
channelConfig:音频通道的配置
audioFormat:音频数据的格式
bufferSizeInBytes:在录制期间写入音频数据的缓冲区的总大小(以字节为单位)

初始化操作:

int mBufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2;
AudioRecord mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
        16000,
        AudioFormat.CHANNEL_IN_MONO,//双声道
        AudioFormat.ENCODING_PCM_16BIT,
        mBufferSize);

 2.开始录音

 /**
     * 录制pcm文件
     * @param pcmFilePath pcm文件路径
     */
    public void startRecord(String pcmFilePath) {
        if (isRecord) {
            return;
        }
        this.mPcmFilePath=pcmFilePath;
        isRecord = true;
        RecordThread recordThread = new RecordThread();
        mExecutorService.execute(recordThread);
    }

 class RecordThread implements Runnable {

        @Override
        public void run() {
            mAudioRecord.startRecording();
            FileOutputStream fos = null;
            try {
                Log.i(TAG, "文件地址: " + mPcmFilePath);
                fos = new FileOutputStream(mPcmFilePath);
                byte[] bytes = new byte[mBufferSize];
                while (isRecord) {
                    mAudioRecord.read(bytes, 0, bytes.length);
                    fos.write(bytes, 0, bytes.length);
                    fos.flush();
                }
                Log.i(TAG, "停止录制");
                mAudioRecord.stop();
                fos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

3.结束录音

/**
     * 停止录制
     */
    public void stopRecord() {
        isRecord = false;
    }

4.将录音生成的pcm文件转成wav文件

/**
     * pcm文件转wav文件
     * @param pcmFile pcm文件
     * @param wavFile wav文件
     */
    public void pcm2Wav(File pcmFile, File wavFile) {
        if (!pcmFile.exists()){
            throw new RuntimeException(pcmFile.getAbsolutePath()+",there is no pcm file");
        }
        mExecutorService.execute(new PcmToWavThread(pcmFile,wavFile));
    }


    class PcmToWavThread implements Runnable {
        File pcmFile;
        File wavFile;

        public PcmToWavThread(File pcmFile, File wavFile) {
            this.pcmFile = pcmFile;
            this.wavFile = wavFile;
        }

        @Override
        public void run() {
            if (!wavFile.exists()){
                try {
                    wavFile.createNewFile();
                    PcmToWavUtil util=new PcmToWavUtil(mSampleRate,mChannel,mFormat);
                    util.pcmToWav(pcmFile.getAbsolutePath(),wavFile.getAbsolutePath());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

 pcm文成wav文件方法如下:

/**
     * pcm文件转wav文件
     *
     * @param inFilename 源文件路径
     * @param outFilename 目标文件路径
     */
    public void pcmToWav(String inFilename, String outFilename) {
        FileInputStream in;
        FileOutputStream out;
        long totalAudioLen;//总录音长度
        long totalDataLen;//总数据长度
        long longSampleRate = mSampleRate;
        int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2;
        long byteRate = 16 * mSampleRate * channels / 8;
        byte[] data = new byte[mBufferSize];
        try {
            in = new FileInputStream(inFilename);
            out = new FileOutputStream(outFilename);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;

            writeWaveFileHeader(out, totalAudioLen, totalDataLen,
                    longSampleRate, channels, byteRate);
            while (in.read(data) != -1) {
                out.write(data);
                out.flush();

            }
            Log.e(TAG, "pcmToWav: 停止处理");
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 加入wav文件头
     */
    private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                     long totalDataLen, long longSampleRate, int channels, long byteRate)
            throws IOException {
        byte[] header = new byte[44];
        // RIFF/WAVE header
        header[0] = 'R';
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        //WAVE
        header[8] = 'W';
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        // 'fmt ' chunk
        header[12] = 'f';
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        // 4 bytes: size of 'fmt ' chunk
        header[16] = 16;
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        // format = 1
        header[20] = 1;
        header[21] = 0;
        header[22] = (byte) channels;
        header[23] = 0;
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        // block align
        header[32] = (byte) (2 * 16 / 8);
        header[33] = 0;
        // bits per sample
        header[34] = 16;
        header[35] = 0;
        //data
        header[36] = 'd';
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
        out.write(header, 0, 44);
    }

5.释放资源

/**
     * 释放资源
     */
    public void release() {
        if (mAudioRecord != null) {
            mAudioRecord.release();
        }
        if (mExecutorService!=null){
            mExecutorService.shutdown();
        }
    }

至此录音功能即可实现了,如果想要测试可以直接使用MediaPlayer方法进行录音播放


原文地址:https://blog.csdn.net/xia09222826/article/details/139082918

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!