網頁js版音訊數字訊號處理:H5錄音+特定頻率訊號的特徵分析和識別提取

xiangyuecn發表於2023-02-27

音訊數字訊號處理 Audio DSP (Digital Signal Processing) 是一個複雜又專業的話題,本文介紹的是如何從音訊中實時分析和識別出特定頻率訊號的一種方法,對應的程式碼為可執行在瀏覽器中的html5網頁版(可移植);可用於識別環境中特定頻率的聲音、或噪聲、樂器彈奏的音調。

線上測試:FFT頻域分析ECharts頻譜曲線圖

900Hz頻率的摩爾斯電碼聲音訊譜曲線,為本文的主要分析物件,請見文末生成LOVE對應的電碼音訊檔案,然後把檔案拖入上面的這個線上測試頁面,即可得到此圖:

吉他6根空絃音訊譜曲線:

一、網頁中的音訊資料來源

H5網頁中獲取音訊資料的方法至少有三種:

  1. 透過網路請求下載得到音訊檔案二進位制內容(xhrfetch
  2. 透過input[type=file]選擇檔案,在用FileReader讀取獲得二進位制內容
  3. 透過瀏覽器的getUserMedia介面訪問裝置的麥克風,錄製得到音訊二進位制內容

不同音訊格式有不同的壓縮編碼方法,為了得到檔案內的音訊資料,我們需要解碼音訊檔案,得到音訊的取樣資料(PCM)才好進行下一步處理;.wav格式的檔案解碼簡單,它是一般是由wav頭+pcm資料組合而成的,直接去掉wav頭即完成解碼,其他檔案可透過AudioContextdecodeAudioData方法直接解碼成32位pcm再轉成16位pcm。

得益於現代瀏覽器的WebRTC功能加持,網頁也能實現豐富的音影片互動,可以實現網頁錄音,實時採集環境中的聲音得到pcm資料,GitHub Recorder是一個功能豐富的H5網頁錄音開源庫,可以方便的進行實時處理錄音資料。

二、FFT:時域轉頻域

我們得到音訊的取樣資料(PCM)後,可以將此資料按值的大小直接繪製出來,即可得到一個聲音的波形,此波形為音訊的時域波形:橫座標是時間,縱座標是取樣值的大小,比如在Audition中顯示如下圖所示(生成此音訊檔案請見文末)。

在時域波形上,我們能直觀的知道在某個時間點是否有聲音,和聲音的大小,但不知道這個聲音是否是我們需要的訊號,還是其他雜音;數字訊號分析的重頭戲出場了:FFT,快速傅立葉變換。

透過FFT可以將單個時域波形分解成N個不同頻率的波形,即時域訊號變換成頻域訊號,N取決於fftSize的大小,比如fftSize=1024,將得到512個頻率分量;在Audition中可以非常直觀的感受到頻域訊號的強度分佈,如下圖所示,900Hz的訊號非常亮(生成此音訊檔案請見文末)。

H5 js版的FFT的實現有很多開原始碼可以參考,或者直接使用瀏覽器提供的AudioContextcreateAnalyser介面來進行頻域資料變換;Recorder庫中的提供了2個FFT實現可以使用:extensions/lib.fft.jsdsp.lib.fft_exact.js,到上文中的線上測試中可以看到這兩檔案。

js版的FFT變換操作也比較簡單,Audition中用到的這個音訊檔案,在網頁中透過變換後得到的頻域資料,疊加繪製到一起即得到了文章開頭的第一張摩爾斯電碼聲音訊譜曲線圖,訊號非常明顯。

三、訊號的特徵分析

以文章開頭的“900Hz頻率的摩爾斯電碼聲音訊譜曲線圖”為例,我們透過頻譜分析,可以直觀的看到訊號最強的頻率波峰,能量非常集中,頻率值分散在900Hz附近,也就是說這段音訊中訊號的主要頻率為900Hz左右,和實際生成此摩爾斯電碼所使用的900Hz頻率一致。

分析得到了主要頻率,我們只關注這個主要頻率的波形曲線,也能直觀的看出和摩爾斯電碼規律一致的特徵:持續時間短的是滴(.),持續時間長的是嗒(-),嗒的長度是滴的3倍,滴嗒之間間隔1個滴的長度,字元之間間隔3個滴的長度(單詞之間間隔7個滴以上的長度)。

四、訊號的識別提取

分析出訊號的特徵後,就有辦法透過編寫程式碼來進行訊號的識別和提取,依舊是以上圖為例,我們來提取出裡面包含的摩爾斯電碼。

(1)過濾掉其他能量低的值,中只保留能量集中的幾個頻率

(2)程式程式碼中對這幾個頻率進行綜合分析判斷,每個波峰取和前面頻率相差不大的頻率當做有效波峰(這樣可有效排除掉雜波干擾),得到一條曲線

(3)根據曲線中的值的大小,較小的值全部當做0,高的保留,最終轉換得到斷斷續續的矩形波,有波峰的地方即為有訊號,得到每個波峰的持續時間,即可識別出滴(.)嗒(-),即為摩爾斯電碼

Q: 為啥不用PCM的音量大小來直接判斷訊號?

A: 最後的矩形波看起來和時域的波形包絡沒有多大區別,這是因為錄製的樣本中沒有比較大的背景雜音干擾;在沒有雜音干擾的情況下,直接用PCM的取樣值(或音量)來提取訊號也是可行的;但在有比較大的干擾的情況下(末尾那段雜音),時域就很難區分出是否是正確的訊號,頻域中分離出來的波形更能反映出原本的訊號。

如果是要根據聲音的頻率來判斷是什麼訊號,那就必須轉到頻域來識別處理,比如樂器的音調,時域是完全無法識別出是哪個調的。

附錄

  • Recorder用於html5錄音:https://github.com/xiangyuecn/Recorder,網頁中實時錄製獲得音訊資料。
  • 趣味摩爾斯電碼:小程式,微信版和位元組抖音版,將文字LOVE轉換成摩斯碼並播放,錄製得到上文中使用的摩爾斯電碼音訊;內建電碼翻譯功能,可以實時錄製音訊並解析出電碼,本文所總結的內容即為其音訊識別成電碼所使用的原理。

【完】

相關文章