发霉派发射 FM 最简单的方法是从 GitHub 找个相关的 repo 然后装上。
但是那样音质太菜了,所以有了本文。
注意!
在大部分国家私自架设电台属于违法行为,执行操作前请务必三思。
前期准备
- 使用树莓派兼容 GPIO 接口的开发板 x1(要有 3.5mm 接口和 I2C)
- 一片 KT0803K/L 模块 x1(大约 30CNY)
- 3.5mm 公对公线 x1(白嫖一根)
- 几根杜邦线,包含一根大约 70cm 的(用几根接起来也行)
- 需要放送的节目(Podcast 或者直播源)
基本操作
首先,把 KT0803 模块和 PI 接起来(I2C/音频/电源)。
需要注意的是,树莓派的 3.5mm 接口作为音频输出可能要改一下 SD 卡里的配置文件。
如果不考虑音质,接下来要做的是安装编译安装一下这个 rpi-kt0803k 。
指令使用 sudo rpi-kt0803k -c 77000
即可使能模块在 77.0MHz 发射 FM 信号。
如果你不配置,那么芯片默认从 86.0MHz 发射。
此时,使用 ffplay 或 mpg123 之类的播放器随便放点音乐,
应该就能使用收音机在你设定的频率接收到了。
但是这么做的结果是,接收设备上听起来通常声音比其他电台小很多,
而如果直接增大音量,虽然能降低背景噪音,但让爆音出现频率变高。
噪音抑制
KT0803 系列芯片本身容易被噪声干扰,如果不播放任何音频空开很容易听到有规律的电流噪声。
解决这一问题的最简单方法是增益输出音量,在 ffmpeg 里可以直接写 volume=3db
意为增加 3db 音量。
这么做确实能提高平均音量,但同时也增加了最大音量时爆音的概率。
为解决这一问题,需要像真实的电台一样,对声音进行压缩和压限,
保证进入模块的信号处于较高音量状态。
当然,加钱的情况下还可以通过更换带纹波抑制的电源为设备单独供电解决。
如果你使用的是 KT0803L,芯片已经内置了压缩器,不过目前控制程序还未提供这一支持。
所以暂时用 ffmpeg 替代一下。
在操作前,请在 alsamixer 中将音量设置到 -1db 的位置。
接着 ffmpeg 里是这样写的:ffmpeg -thread_queue_size 512 -i xxx.mp3 -filter_complex "compand=attacks=0:points=-80/-75|-45/-15|-27/-9|0/-7|20/-7:gain=5" -ar 48000 -f wav - | ffplay -nodisp -
本身 filter 其实可以在 ffplay 直接调用,
但因 ffplay 在某些方面特性不明,故在此仅作为渲染输出使用。
-thread_queue_size
:照 ffmpeg 提示增加的
-i
:文件输入
-filter_complex
:滤镜设定
compand
:压缩器
points
中使用竖线隔开的是各组控制点的增益,
比如 -45/-15 意思为将音量为 -45db 的信号提升到 -15db。gain=5
则意味着最终再整体增加 5db。
建议在编写适用自己节目的参数前,
可以使用 ffmpeg 的 volumedetect
滤镜检测一下音频中各种音量比例,以此作为调教参考。
Lofi 增强
ffmpeg 有很多奇奇怪怪的滤镜可以用来实时处理音频,afir 就是其中一个。
afir 是一个用来运行卷积音频处理的滤镜,可以用来还原脉冲响应样本效果。
脉冲响应样本可以从这里下载到。
使用方法很简单,首先将脉冲响应样本文件名中的空格去掉,然后把拓展名改为 wav。
接着使用 ffmpeg 加载,并配上压缩器:ffmpeg -thread_queue_size 512 -i xxx.mp3 -filter_complex "aresample=48000:resampler=soxr,afir,compand=attacks=0:points=-80/-65|-65/-30|-45/-15|-27/-9|0/-7|20/-7:gain=5" -i ctn.wav -f wav - | ffplay -nodisp -
在使用样本前,请随便找个播放器打开样本(wav 是个播放器都能播放),然后将样本使用的采样率填入 aresample 参数。
例如这里使用的是 48kHz 的样本,就填写 48000。
然后将脉冲样本的 wav 文件放到当前目录,并加入命令。例如这里使用的脉冲样本文件名为 ctn.wav。
需要注意的是,使用 afir 时可能需要重新调整压缩器参防止爆音。
远程控制与定时重启
咱使用这套东西转发收音机收不到的电台,所以就有了这两个问题:
- 网络阻塞卡了怎么办
- 听腻了换台要怎么办
第一个问题的解决办法很简单,在把执行 ffmpeg 脚本的 systemd 服务绑定定时器,每隔一段时间重启服务就行。
下边是咱使用的 systemd 配置
定时器:
[Unit]
Description=Auto restart PIFM
[Timer]
OnCalendar=*:15/30
Persistent=true
[Install]
WantedBy=multi-user.target
与定时器绑定执行的服务:
[Unit]
Description=Restart service
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart hd-radio.service
执行 ffmpeg 的服务:
[Unit]
Description=Hardware FM Broadcast Daemon Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/bash /home/alarm/hd_radio.sh
WorkingDirectory=/home/alarm
[Install]
WantedBy=default.target
接着是换台的问题。
因为 cli 管理不是很方便,于是干脆糊了一个。
原理极其简单,选定需要广播的源,点击确认,从模板生成一份 shell,
重启管理 ffmpeg 的 systemd 服务即可。
后记
东西已经写了挺久了,只是代码丑陋不方便拿出来,
不过直播源还是可以分享一下的(其实都是可以随便找到的)。
推荐一下 ABC 的音乐节目,主持人废话很少,仅网络传送的节目则是纯音乐放送。
美中不足的是,虽然有在线节目单,但似乎后端经常炸裂。
# BBC
'wssc': 'http://bbcwssc.ic.llnwd.net:80/stream/bbcwssc_mp1_ws-einws',
'asia': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_asianet_mf_p',
'radio1': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio1_mf_p',
'radio2': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio2_mf_p',
'radio3': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio3_mf_p',
'radio4': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio4fm_mf_p',
'radio5': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio5live_mf_p',
'radio6': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_6music_mf_p',
'radio1xtra': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio1xtra_mf_p',
'radio4extra': 'http://bbcmedia.ic.llnwd.net:80/stream/bbcmedia_radio4extra_mf_p',
# ABC
'abcnews': 'http://live-radio01.mediahubaustralia.com/PBW/aac/',
'abctriplej': 'http://live-radio01.mediahubaustralia.com/2TJW/aac/',
'abctriplejnearthed': 'http://live-radio01.mediahubaustralia.com/UNEW/aac/',
'abcdoublej': 'http://live-radio01.mediahubaustralia.com/DJDW/aac/',
'abccountry': 'http://live-radio01.mediahubaustralia.com/CTRW/aac/',
'abcclassic': 'http://live-radio01.mediahubaustralia.com/2FMW/aac/',
'abcclassic2': 'http://live-radio01.mediahubaustralia.com/FM2W/aac/',
'abcjazz': 'http://live-radio01.mediahubaustralia.com/JAZW/aac/',
'abcjazzlow': 'http://abcradiolivehls-lh.akamaihd.net/i/abcjazz_1@327288/master.m3u8',
# RTHK
'rthk1': 'http://stm.rthk.hk/radio1',
'rthk2': 'http://stm.rthk.hk/radio2',
'rthk3': 'http://stm.rthk.hk/radio3',
'rthk4': 'http://stm.rthk.hk/radio4',
'rthk5': 'http://stm.rthk.hk/radio5',
'rthkpth': 'http://stm.rthk.hk/radiopth',
# OTHERS
'aninfo2': 'http://itori.animenfo.com:443', # http://www.animenfo.com/radio/listen.m3u
'gensokyo': 'http://149.56.102.152:8000/', # http://stream.gensokyoradio.net:8000/listen.pls?sid=1
'japanaradio': 'http://audio.misproductions.com/japan48k'# http://www.japanaradio.com/free/48kaacp.pls