天天看點

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以上系統需要手動開啟權限。

源碼位址