自定義音視頻基類二

上一章簡述了視頻採集相關知識,本章爲音頻採集,音頻採集相對視頻採集簡單了許多,在自定義基類中加入如下代碼

// 採樣率
    private val sampleRateInHz = 44100

    // 音頻通道 立體聲:
    val stereo = AudioFormat.CHANNEL_IN_STEREO

    lateinit var audioRecord: AudioRecord
    
    //audioRecord能接受的最小的buffer大小
    private var bufferSizeInBytes: Int = 0

    //錄音線程
    private var recordingJob: Job? = null

    /**
     * 初始化AudioRecord
     */
    fun initAudioRecord(channelConfig: Int = AudioFormat.CHANNEL_IN_MONO) {
        //audioRecord能接受的最小的buffer大小
        bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT)
        audioRecord = AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes)
    }

    /**
     * 開始錄音
     */
    fun startRecording() {
        recordingJob = GlobalScope.launch(Dispatchers.IO) {
            if (bufferSizeInBytes > 0) {
                audioRecord.startRecording()

                while (isActive) {
                    val buffer = ByteArray(bufferSizeInBytes)
                    val len = audioRecord.read(buffer, 0, buffer.size)
                    if (len > 0) {
                        //音頻編碼
                        audioCoding(buffer, len)
                    }
                }
            } else {
                launch(Dispatchers.Main) {
                    showToast("請先初始化AudioRecord類")
                }
            }
        }
    }

    /**
     * 音頻編碼
     */
    abstract fun audioCoding(buffer: ByteArray, len: Int)

    /**
     * 結束錄音
     */
    fun endRecording() {
        if (audioRecord.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
            audioRecord.stop()
        }
        if (audioRecord.state == AudioRecord.STATE_INITIALIZED) {
            audioRecord.release()
        }
        recordingJob?.cancel()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cameraDevice?.close()
            for (surface in outputs) {
                surface.release()
            }
            endRecording()
            releaseBackgroundThread()
        }
    }

使用也很簡單,繼承這個基類必須實現該方法

    /**
     * 音頻編碼,注意這裏是在子線程中的
     */
    override fun audioCoding(buffer: ByteArray, len: Int) {

    }

當然在使用前必須進行初始化操作

//初始化AudioRecord
initAudioRecord()

然後在合適的地方調用

//開始錄音
startRecording()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章