上一章簡述了視頻採集相關知識,本章爲音頻採集,音頻採集相對視頻採集簡單了許多,在自定義基類中加入如下代碼
// 採樣率
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()