音頻PCM 48K to 16K 重採樣

簡述

部門有一個音頻識別項目,採樣率是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音頻數據處理—降低採樣率

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