實時PCM轉換DSD實作
自從我開始開發XAMP2之後,基本上算是很頻繁的更新,直到今年開始竟然有人開始提了issule,
[SUGGESTION] Add PCM to DSD "resampling"喔... 有這功能的撥放器都要收費耶~ 思前想後都覺得有難度(雖然之前有想挑戰看看), 後來那位外過仁兄提供了一個不錯的參考專案PCM-DSD_Converter接著我就著手開始 首先要想一下這個Converter要放在DSP哪邊呢? 因為Converter所以一定是最後輸出要處理的,所以必須要換掉最終寫出的資料的SampleWriter。
在PCM-DSD_Converter源碼中,作者先把音源split兩個聲道,再把這兩個聲道採樣成目標SampleRate,再把這兩個聲道各為做Delta-Sigma輸出為0和1的資料,最後合併兩聲道的資料輸出DSD檔案。
優化
處理各聲道firfilter都跑一次FFT轉換
作者為了加速轉換速度還使用OpenMP和FFTW,雖然使用了OpenMP進行平行化(各聲道)處理,但是每次都要重新初始化FFTW(firfilter)相關資料,要實時轉換的話就不能這樣做了太費時了。
檔案當作緩衝區
Split各聲道各一個檔案,Delta-Sigma輸出各聲道一個檔案,轉換工具的話倒是可以如此處理,如果要考慮實時轉換,在記憶體上操作會比較有效率一點。
實作
Split各聲道為double格式
因為XAMP早已透過3rd lib(BASS)已經檔案來源轉換為float格式。
OpenMP 或是 FFTW
OpenMP有平台相依的問題,改用XAMP內建的thread pool處理,FFTW也早已在XAMP使用了。
輸出DOP或是Native DSD格式
因為只是個PCM轉換為DSD的工具,我們必須要還要將資料轉換為DOP或是Native DSD格式。
這是這個轉換過程比較花時間的過程。目前XAMP已經支援DOP格式撥放,以下是DOP轉換過程:
PCM(float) -> INT (24/32)格式 -> 音效卡
從DSD檔案到PCM(float)這段過程,均由3rd lib(BASS)做到,但是要從Delta-Sigma輸出到PCM(float)過程倒是頭一次。
Delta-Sigma(1bit) -> 合併8bit為1byte -> 轉換DOP格式 -> DOP(float)-> INT (24/32)格式 -> 音效卡
合併合併8bit為1byte過程在PCM-DSD_Converter源碼就有,閱讀DOP格式文件得知道,每個24bit 都有DOP Marker(0x05, 0xFA),所以格式為 0x05 L1 0x05 R1, 0xFA L2 0xFA R2, 0x05 L3 0x05 R3...,最後還將格式轉換為INT (24/32),所以必須要將結果轉為INT格式,並除上8388608(INT24 MAX)轉換為浮點數。看似過程很簡單,直接這幾天發現0xFA需要MSB必須要補上0xFF(v |= 0xFF000000u)。
TODO
- FFT運算實在太耗時並且在處理多維陣列時候效率太差,導致整個程式Debug模式之下效率很差。
- 在一個可能需要實時輸出音效程式上,Converter效率太差會拖卡聲音的品質,為了改善此現象,目前採用將ThreadPool綁定某個CPU上,不讓消耗CPU 0的的計算資源。
留言
張貼留言