天天看点

Android使用AudioRecord录制pcm裸数据

第六章讲音视频的采集,首先是音频采集。Android录音可以采用MediaRecorder,这个API是比较上层的,直接可以输出通常的音频格式文件,但是相对的就失去了一些灵活性。AudioRecord可以直接录制PCM裸数据,当然也可以用OpenSL ES来进行录制,然而API过于繁琐,对于音频来说,audioRecord其实已经满足大部分需求了。话不多说,直接分析代码,书上的源码我用kotlin重新写了一遍,毕竟项目里没有用kotlin,写一写不要忘的太快也是可以的。

确定录制PCM的格式

按照书上的说法,考虑到性能使用单声道录制,采样率也是通常使用44100,这个采样率保证声音的完整性,数据格式我们每个数据使用的是16bit,这个可以兼容大部分安卓手机。

companion object {
        var SAMPLE_RATE_IN_HZ = 
        private val CHANNEL_CONFIGURATION = AudioFormat.CHANNEL_IN_MONO
        private val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
        val instance = AudioRecordRecorderService()
    }
           

获取音频缓冲区的大小

我们使用系统的api来获取大小,最好不用自己计算

bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT)

初始化并开启录音

初始化

fun initMeta() {
        audioRecoder?.release()

        bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT)
        audioRecoder = AudioRecord(AUDIO_SOURCE, SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT, bufferSizeInBytes)

        if (audioRecoder == null || audioRecoder?.state != AudioRecord.STATE_INITIALIZED) {
            SAMPLE_RATE_IN_HZ = ;
            bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT)
            audioRecoder = AudioRecord(AUDIO_SOURCE, SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT, bufferSizeInBytes)
        }

        if (audioRecoder?.state != AudioRecord.STATE_INITIALIZED) {
            throw AudioConfigurationException()
        }
    }



           

开启录音,注意需要检测一下状态

fun start(filePath: String) {
        audioRecoder?.run {
            if (state != AudioRecord.STATE_INITIALIZED) {
                null
            } else {
                startRecording()
            }
        } ?: throw StartRecordingException()
        isRecording = true
        recordThread = Thread(RecordThread(), "RecordThread")
        outputFilePath = filePath
        recordThread?.start() ?: throw StartRecordingException();
    }
           

开启线程持续读取pcm数据

简单读取数据并写入文件而已

inner class RecordThread : Runnable {
        override fun run() {
            outputStream = FileOutputStream(outputFilePath)

            val audioSamples = ByteArray(bufferSizeInBytes)
            outputStream.use {
                while (isRecording) {
                    val audioSampleSize = getAudioRecordBuffer(bufferSizeInBytes, audioSamples)
                    if (audioSampleSize != ) {
                        outputStream?.write(audioSamples)
                    }

                }

            }

        }

    }
           

最后使用Android studio或者adb导出文件,然后使用ffplay进行播放

ffplay -f s16le -sample_rate 44100 -channels 1 -i pcm文件的路径

Android使用AudioRecord录制pcm裸数据

相当简单的逻辑,不需要多说,只需要了解pcm的一些采样格式的配置即可,最后需要提醒6.0以上系统需要手动开启权限。

源码地址