數字麥克風PDM訊號採集與STM32 I2S介面應用(二)
在使用STM32的數字麥克風I2S介面時,計算取樣率讓人頭疼,晶片手冊上沒有明確的說法,而手冊上的計算方法經過測試卻和實驗不符。藉助搜尋引擎,大部分資料都是來自於開發板賣家或開發板論壇,主要是咪頭採集然後配置WM89系列解碼晶片,然後配合FatFS、MP3解碼等模式,主要是講解I2S錄音、儲存、放音等。外文資料得到的也寥寥無幾,也沒有找到講解STM32數字麥克風配置、計算的文件。加上網上資料轉載、抄襲、淺嘗輒止的筆記教程,這些更是讓檢索大海撈針,過程艱辛一言難盡,有些網文三言兩語抑或作者都沒有搞清楚隨手一寫,有些是作者搞清楚了但藏著掖著最關鍵的點沒說,有些是跟著別人現成的教程做了一邊又寫了一篇筆記卻沒有增加任何新東西,種種緣由搞得技術圈文章氛圍差到極點讓人惱火。
我的需求是音訊特徵點檢測,所以把聲音錄製然後傳輸到PC上是首要任務,經過多次摸索,終於瞭解一二,現在分享出來方便後來者,恐水平有限有未發現的錯誤而誤導他人,在文尾附上STM32 I2S和PDM採集相關的原廠資料以作參考。
儘管內容龐雜,但爭取一文講清楚數字麥克風單聲道模式的PDM訊號採集,PDM到PCM解碼,以及上位機驗證分析如python/matlab指令碼讀取錄音檔案和播放,頻譜分析等。
1、 STM32 I2S介面標準和資料格式
這些內容參考STM32晶片程式設計手冊,基本上就是4個模式,以及16位32位資料格式,若使用SPI/I2S介面通訊還要有MSB、LSB配置。
2、 STM32 I2S取樣率的配置
STM32的時鐘配置和資料格式決定了音訊訊號的取樣率,如下計算。在使用了ST CUBE MX後,下面的計算過程也省略了,直接配置感測器的資料格式、介面標準、取樣率就可以了。
上面是STM32晶片手冊給出的資訊,在做音訊採集時候,發現這和實測效果相差較遠,原來這組公式並不適合PDM訊號的數字麥克風。PDM麥克風只是利用了STM32的I2S訊號時鐘和資料線,它的取樣只是按照bit取樣,每一個sample為1bit,要轉換為類似於AD/DA的取樣值,還需要進行PDM2PCM轉換,ST給出了一個驅動包,可以進行類似轉換,可以參考AM3998和UM2372手冊。
下面的公式才是PDM麥克風與STM32 I2S介面配合時使用的取樣率計算方法,其中FS是PDM bit sample的取樣率,DIV是PDM到PCM的抽樣因子,經過抽樣,把bit sample變為類似於模擬取樣的sample。
例如下面的配置,PDM取樣率為32khz,單聲道應用,那麼PDM2PCM使用64抽取比,則真實的音訊取樣率為16*2*32khz/64 = 16khz。
/* I2S2 init function */ void MX_I2S2_Init(void) { hi2s2.Instance = SPI2; hi2s2.Init.Mode = I2S_MODE_MASTER_RX; hi2s2.Init.Standard = I2S_STANDARD_MSB; hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B; hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_32K; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL; hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; if (HAL_I2S_Init(&hi2s2) != HAL_OK) { Error_Handler(); } }
此時PDM的時鐘頻率為32khz*16*2=1024khz,測量結果如下驗證了該分析結論。
STM32F407的I2S IP核是按照左右聲道來處理音訊訊號的,所以其SW腳訊號頻率為32khz。
3、PDM和PCM訊號
PDM調製器將緩衝模擬訊號轉換為序列脈衝密度調製訊號,時鐘輸入( CLK)用於控制PDM調製器。PDM訊號無法直接驅動DA進行聲音播放,PDM訊號要變為聲音訊號還需要進行下采樣,經過一次低通濾波和抽樣,然後成為PCM訊號。
PDM是一種調製形式,用於表示數字域中的模擬訊號。它是1位數字取樣的高頻資料流。在PDM訊號中,脈衝的相對密度對應於模擬訊號的幅度。大量的1s對應於高(正)幅度值,而大量的0s對應於低(負)幅度值,交替的1s和0s對應於幅度值0。
PDM轉為PCM訊號,需要進行濾波和抽取。PDM訊號取樣率就是I2S的clk時鐘頻率,可見這是一個高頻取樣,按bit取樣的訊號。PCM訊號是目標音訊的取樣率,比如高保真44khz,PDM2PCM的抽樣因子M,則M=PDM頻率/音訊取樣率。
ST 提過了PDM2PCM的軟體包,可以完成上面的工作。
軟體包原始碼沒有開源,使用手冊也簡潔的讓人抓狂,我覺得可能是因為ST更高階的MCU直接帶了硬解碼,所以對中低端MCU I2S介面的軟解碼關注度也不夠。幸好之前做過訊號處理工作,一些概念和內在邏輯能猜個八九不離十,使用起來沒有任何難度就上手了,這個軟體包使用時需要配置下面幾個引數。
1)初始化PDMFilter,包括取樣率,低通高通濾波器截止頻率,通道個數。
typedef struct { uint16_t Fs; float LP_HZ; float HP_HZ; uint16_t Out_MicChannels; char InternalFilter[34]; } PDMFilter_InitStruct;
2)完成引數初始化後呼叫濾波器初始化函式。
Void PDM_Filter_Init (PDMFilter_InitStruct * Filter)
3)最後呼叫下面函式完成PDM2PCM的抽取。
PDM_Filter_XX_XX(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter)
ST提供了多種PDM2PCM的抽取方法。
int32_t PDM_Filter_64_MSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter); int32_t PDM_Filter_80_MSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter); int32_t PDM_Filter_64_LSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter); int32_t PDM_Filter_80_LSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter);
參考文件:
1、如何將PDM數字麥克風連線到STM32微控制器
AN5027 使用STM32 32位Arm® Cortex® MCU連線PDM數字麥克風
2、 PDM audio software decoding on STM32 microcontrollers
AN3998在STM32微控制器上的PDM軟體音訊解碼
3、 UM2372_用於STM32F4_F7_H7的PDM2PCM軟體包介紹
STM32Cube PDM2PCM software library for the STM32F4/F7/H7 Series
4、 基於 STM32 I2S 的音訊應用開發介紹
基於 STM32 I2S 的音訊應用開發介紹
尊重原創技術文章,轉載請註明。
https://www.cnblogs.com/pingwen/p/11301935.html