用 Astrometa DVB-T2 聽 FM 廣播

算是接續「用 Astrometa DVB-T2 收數位無線電視台 (DVB-T)」這篇的內容,上篇有提到在台灣可以收 DVB-T 的數位電視內容,另外也有提到裡面的 RTL2832U 可以收 FM 廣播。

RTL2832U 在 Linux 下面的 FM 介面不是 /dev/radio0 這種 Radio Interface,而是透過 SDR 的方式,會產生出 /dev/swradio0 操作。

所以可以用 rtl_fm 這個工具從 SDR source 轉成 PulseAudio 吃的格式,像是要聽 107.7MHz 的台北之音,可以用這樣的指令聽:

sudo rtl_fm -f 107700000 -s 441000 -r 44100 | aplay -r 44100 -f S16_LE

但這樣做會是 mono (單聲道),這點可以從「Stereo FM receiving with RTL-SDR and Gnuradio - part 1」這邊的這張圖了解發生了什麼事情:

最低的地方會是左右聲道混在一起的 L+R 的單聲道訊號,這個方式可以讓很早期不支援兩聲道 (立體聲) 的 FM 收音機還是可以正常收聽,也剛好是 rtl_fm 時用到的地方。

而接下來是 19kHz 表示支援立體聲的訊號,然後從 23~53kHZ 的地方是 L-R 的訊號,最後面是 RDS 資料。

所以要把這包東西轉成 L 與 R 不是單純抽兩段 source 出來就解決了,而是需要在頻域上運算。

接著就是找看看有沒有已經做完的工具可以從 SDR source 運算然後播放,就找到 LuaRadio 這個專案,依照他的要求安裝 dependency,然後就可以直接跑了:

./luaradio examples/rtlsdr_wbfm_stereo.lua 107700000

在「rtlsdr_wbfm_stereo.lua」這頁的說明可以看到整個 flow 拉了很多處理。

不過在我的桌機上面,他會跳出三個 gnuplot 的視窗一直搶 window focus,要終止的話得按住 Ctrl-C 不放,然後點 terminal 想辦法讓 terminal 收到 Ctrl-C 才能停掉,看起來應該是 bug...

從 code 裡面可以看到他會偵測是否有 DISPLAY 這個環境變數來決定要怎麼做,所以本來以為改掉 DISPLAY 就可以了:

DISPLAY= ./luaradio examples/rtlsdr_wbfm_stereo.lua 107700000

不過看起來會卡住,還是得直接把相關的 code 都註解掉才行。

anyway,從官方給的圖可以看到整個收到的頻譜,以及 L+R 與 L-R 的樣子,也可以看到 19kHz 那邊有根訊號表示這是兩聲道:

這樣至少是有軟體可以聽立體聲了...