Read my book

I wrote books about Webpack and React. Check them out!

Tuesday, January 15, 2013

Raspberry Pi as an Internet Radio

I own a Tivoli Model Two table radio. It's a great set. I'm particularly happy about the sound quality. Unfortunately it has been a pain to keep it in tune due to the amount of FM channels around. I have wanted to solve this problem for quite a while.

As I happened to have an extra Raspberry Pi around that got me thinking. What if turned that into an internet radio and then fed the audio to my Tivoli via its aux input? During my research I noticed several people (1, 2) have already done this.

It isn't entirely trivial to set up. You'll need some hardware and a little bit of software work to make it happen. Since I'm not entirely comfortable having a naked Pi around I bought a case from ModMyPi. While at it I bought a microSD adapter to avoid having an SD card jutting from the side. Obviously I needed to purchase a mini-stereo cable (male-male) to hook up the Pi with Tivoli.

Setting Up Raspberry Pi and SSH

If you are starting from scratch, you might want to study Engadget's surprisingly good article about how to set Raspberry Pi up. In order to make the Pi "headless", you'll want to set up SSH. The whole basic procedure goes like this:

  • Execute rm /etc/ssh/ssh_host_* && dpkg-reconfigure openssh-server at Pi. This is just a security precaution to avoid man in the middle type of attacks.
  • Figure out the IP address of your Pi using ifconfig. You should see multiple addresses there. In my setup I use a WLAN dongle so I needed to use its IP (192.168.something.something).
  • Connect to your Pi from some remote computer at your network using ssh raspi_ip -l pi. This assumes you'll be using the default account provided with Raspbian image.
  • To make it easier to connect, define an alias at ~/.ssh/config . The configuration should look something like this:
    • Host rpi 192.168.something.something
    • Hostname 192.168.something.something
    • User pi
  • To make it faster to connect (avoid password), set up a ssh key. You can achieve this using two commands. Use ssh-keygen on Pi side. In order to copy the key to your remote, use ssh-copy-id rpi . Note that this depends on the alias we just defined.

Installing Audio Dependencies

After you have SSH set up you'll need to install some dependencies required by audio. The following command should install all the needed ones. I've compiled this from various sources. Here we go: sudo apt-get install alsa-utils mpg321 lame mpd mpc .

In addition you'll likely want to configure the analog output (mini-stereo one) to be used. You can do this using amixer like this: amixer cset numid=3 1 .

Setting Up Streaming

Now we should have our audio set up. If you want to do some sanity check, curl a wav file to the Pi (curl some_address > test.wav) and play it (aplay test.wav). If everything went fine, you should hear a sound via your sound system. You should use an active system as the output of Pi is quite weak by default.

We still have to do one thing. We need to make it stream some radio channel. We can use mpc for this. Figure out the address of your channel (Shoutcast, Finnish Channels) and execute mpc add your_channel. To start the playback, just do mpc play . Obviously mpc stop works too.

Adding Support for pls and m3u Playlists

Sometimes it can be difficult to find a link to the stream fo the channel you happen to be interested in. Fortunately there is a way to configure mpd to accept pls and m3u. The following steps should suffice on Raspberry Pi:
  • cd /usr/share/doc/mpc/examples/
  • sudo cp mpd-* /usr/bin
  • cd /usr/bin
  • sudo chmod u+x mpd-*
Now you should have access to mpd-m3u-handler.sh and mpd-pls-handler.sh commands. These take a file argument. In order to get that file simply wget the m3u or pls (wget playlist.pls) of your radio station and pass it to the command.

Conclusion

I hope this brief post gave you an idea how to set up your Raspberry Pi to stream some radio channel. Now that we've got the basic set up done we can move into the interesting stuff. It would be nice to be able to control the whole thing via some kind of a web service for instance. Perhaps that would make a nice sequel to this post.