天天看点

自定义音视频基类二

上一章简述了视频采集相关知识,本章为音频采集,音频采集相对视频采集简单了许多,在自定义基类中加入如下代码

// 采样率
    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()
           

继续阅读