上一章简述了视频采集相关知识,本章为音频采集,音频采集相对视频采集简单了许多,在自定义基类中加入如下代码
// 采样率
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()