簡述
部門有一個音頻識別項目,採樣率是16K 單通道,16Bit,最近需要接入視頻通訊SDK,使用的是Webrtc 音頻採樣率是48K,雙聲道,16bit,本來想着有API可以修改這個採樣率,但是SDK提供商說沒有,看了下源碼,確實不太好改,WebRtc 針對48K採樣率的音頻做了編碼處理等一些操作。只能劍走偏鋒?還好API提供了本地原始數據PCM的回調接口,可以將數據重採樣成16K,對此做一下記錄,加深印象!
重採樣後的音頻圖對比
PCM數據格式
PCM(Pulse Code Modulation)也被稱爲 脈碼編碼調製。PCM中的聲音數據沒有被壓縮,如果是單聲道的文件,採樣數據按時間的先後順序依次存入。(它的基本組織單位是BYTE(8bit)或WORD(16bit))
重採樣思路
同一時間的單位區間內 48000HZ採樣了3個點,16000HZ則採樣了1個點,即從48000HZ的文件中每讀取3個數據,就要根據這3個數據去推算得到1個數據,而這個數據對應的就是16000HZ文件中的一個數據。 本文采用的是取3個採樣點的第1個。
採樣點計算:
採樣率 * 聲道 * 深位 = 16000 * 1 * 16
在AudioRecord中讀取的時我們使用Byte數組讀取的,Byte數字佔用內存1個字節,也就是8位,但是音頻採樣點是16位一個,所以需要轉換成Short。
fun formatPcmByte2Short(dbyte: Byte, gbyte: Byte): Short =
(((0xFF and dbyte.toInt()) shl 0x8) or gbyte.toInt()).toShort()
重採樣
瞭解了PCM 數據格式後 重採樣比想象中要簡單一些,這裏只做了一些簡單的重採樣操作。
val mdRate = 16000
val srcRate = 48000
val srcChanel = 1
val srcBit = 16
val rate = srcRate / mdRate
val bitV = srcBit / 8
val srcQ = srcRate * srcChanel * srcBit / 8 / 1000
val bytes = ByteArray(srcQ)
var len: Int
val input = FileInputStream(File("C:\\Users\\Administrator\\Desktop\\test.pcm"))
val output = DataOutputStream(FileOutputStream(File("D:\\test.pcm")))
while (input.read(bytes).also { len = it } > 0) {
for (i in 0 until len step bitV * rate) {
val vls = formatPcmByte2Short(bytes[i], bytes[i + 1])
output.writeShort(vls.toInt())
}
}
input.close()
output.close()
參考資料
How to convert between (most) audio formats in .NET
PCM數據格式
【C語言】PCM音頻數據處理—降低採樣率