用Raspberry Pi打造真正的“豆瓣FM”

想用床头的收音机收听豆瓣FM吗?如果你有一台Raspberry Pi,这个愿望就可以满足。

Raspberry Pi,中文名树莓派,是一台廉价的单板机,ARM架构,可以运行Linux操作系统,它由英国的树莓派基金会开发,目的是以低价硬件及自由软件促进校园中的计算机科学教育。是的,它设计初衷其实是给小朋友们学电脑用的,不是给你们这些Geek来折腾玩的。

用Raspberry Pi搭建一个豆瓣FM的调频广播台其实并不是一件很困难的事情,为实现这个目标,要解决的两个问题是:

  • 从豆瓣FM网站上下载MP3音乐码流并解码
  • 把音频信号调制成调频信号发射出去

造轮子的事情不要自己做,这两个问题其实已经都解决了:Github上的fmd项目实现了一个通过本地声卡播放豆瓣FM的服务器;这篇文章则介绍了如何写程序对音频信号进行调制并控制Raspberry Pi的GPIO端口把信号发送出去。所以剩下的事就是把它们组合起来就可以了。

组合代码这种脏活累活我也给大家做好了,可以从Github上获取。嗯,这份代码目前的质量是It just works,各位make一下就好,没事就不要vim它了……

git clone git://github.com/lifanxi/fmd.git

代码下载后在Raspberry Pi上可以直接make编译,如果缺少依赖,可能需要安装libcurl4-openssl-dev, libjson0-dev, libmpg123-dev, libao-dev这些依赖包(我用的是Raspbian发行版)。

fmd的使用方法可以参考Github上的说明,我所实现的扩展就是在fmd.conf配置文件中可以把driver配成”pifm”,然后把device配成88MHz~108MHz之间的某个指定的调频发射频率值(这是大多数国家调频收音机所支持的频率范围,如果你有别的无线电接收设备,这个值也可以设成是<250的任意值)来实现FM广播的发射。当driver配成pifm而不是默认的alsa时,fmd就会工作在FM广播模式。

注意,由于FM发射的代码需要直接mmap /dev/mem设备,所以把driver配成pifm让fmd工作在FM广播模式时,需要以root权限来执行fmd。以root权限运行fmd时,注意HOME目录可能会变成/root,所以相关配置文件也得改放到/root/.fmd中。

fmd运行起来后,按照文档的说明,可以telnet到127.0.0.1:10098上或用fmc执行play命令开始广播,把收音机(带收音功能的手机当然也可以)调到device参数所指定的频率上就可以收听了。

如果你的收音机离你的Raspberry Pi太远,收音效果不好,可以在Raspberry Pi主板上的GPIO 4口上插一根20cm左右长的杜邦线做天线,广播范围和信号强度就会大大提高了。

Raspberry Pi正在102.4 MHz上播放豆瓣FM的音乐

Raspberry Pi正在102.4 MHz上播放豆瓣FM的音乐

目前这个豆瓣FM广播台还有两个大问题需要解决:

  • 立体声调频广播:现在实现的版本是单声道的,理论上应该也可以把音频调制成立体声的。这需要一些我所不具备的调频广播的知识,待我有空再钻研钻研。
  • CPU占用率:现在的版本在做调制和发射时,对CPU的占用率比较高。如果Raspberry Pi正在忙于做别的事情的话,你可能会听到一些杂音或者是唱机/磁带机没电了的时候的音响效果。

其实吧,这样收听豆瓣FM可真是多此一举。直接把耳机插在Raspberry的耳机插孔用fmd播放不就完事了么……天行健,君子以折腾不息!

用Raspberry Pi打造真正的“豆瓣FM”》上有100条评论

  1. ./fmd: error while loading shared libraries: libmpg123.so.0: cannot open shared object file: No such file or directory 出现这个怎么解决,我没法用apt-get install来安装,所有的库都是我自己下载然后编译的,你能提供一下这个库么

    • 既然都是您自己编译安装的,那libmpg123您肯定是安装了的吧,不然fmd编译也过不了啊。找找看libmpg.so.0在你的/usr/local/lib等目录中都没有吗?尝试指定一下LD_LIBRARY_PATH试试?
      http://www.freemindworld.com/tmp/libmpg123.so.0 可以下载我的Pi上的对应文件,该地址有效期10天,我的系统是Raspbian(Hard-float)。

      • 是啊,一开始fmd编译不通过,我一个一个下载库的源码然后编译,每编译一个库安装后我都尝试一次fmd的编译,最后fmd编译成功不报错了,运行的时候就提示没libmpg.so.0这个文件。我一开始安装的是libmpg的最新版,直接执行mpg123报错也说找不到libmpg.so.0。后来我下载了个比较旧的0.68版,编译安装后可以执行mpg123,但是fmd仍然说缺那个文件。
        另外我的系统也是Raspbian(Hard-float),我没法通过apt-get update来更新软件源,总是会提示checksum mismatch。换了几个源也不行。有法解决么,我ubuntu上也存在这个问题,听说是墙导致的。

        • deb http://raspbian.caro.net/raspbian/ wheezy main contrib non-free rpi
          这是我目前在用的源,工作正常。之前是用清华的源,现在好像不能用了。
          Checksum mismatch我以前电脑上用Debian时在公司的网络上也时不时发生,在家里就没问题,我怀疑是某些网关设备的问题。
          mpg123可以用但还是报没有libmpg.so.0的话,看看mpg123编译时是不是用了静态链接了?用ldd查查mpg123有没有链接到libmpg.so.0,或者干脆全盘找找libmpg.so.*看看。

  2. 新的问题又来了,我telnet
    Trying 192.168.1.141…
    telnet: connect to address 192.168.1.141: Connection refused
    telnet: Unable to connect to remote host
    这个怎么办?fmc因为我不是linux系统也没法用,在树莓派上编译成功,但是运行提示Illegal instruction。还有我怎么能使用音频输出口来播放,而不是用fm呢,我直接用alsa和default提示找不到设备。

    • telnet时指定了跟配置文件中一致的端口号吧?可以到~/.fmd目录中看看自动生成的log文件,看有没有什么有用的信息。Connection refused意味着你所telnet的端口没有打开,多半是进程没有起来吧。
      我没遇到过Illegal instruction的问题,这个感觉像是编译链接时没有指定正确的平台,但既然你是在Raspberry Pi上编译的,那理论上不应该有这个问题。
      我在我的笔记本的Linux上用alsa和default会报找不到设备,但在Raspberry Pi上是正常的,我没有深入看过这个问题的根本原因……抱歉。