In my first article about the PiCar project I made a list of goals, and among them was the ability to “play audio from my iPhone”. While I could have accepted the minimal viable solution of connecting the LINE IN from the USB sound card adapter to an AUX jack on the front panel, I wanted something more user friendly. It’s my radio dammit!
Wouldn’t it be cool if I could just connect my iPhone over a wireless network and stream music to the piCar radio like “You know, the thing!”. Maybe someone has done this already?
Music on the internet
Back in the prehistoric days (for all you zoomers) people needed a way to play all that music they downloaded from Napster on their computers. Apple Computer not wanting to be left out of the picture, bought an app called SoundJam, and as a matter of fact, the developers who wrote it, and renamed it iTunes. Computers at the time usually had pretty marginal sound systems. So someone thought it would be a good idea to allow them to stream the audio to a remote device that could be hooked up to the home stereo system.
So back in 2004, Apple created the the AirPort Express, an update to their WiFi router that sported an audio line-out jack.
To stream digital audio to these new devices, Apple put together a proprietary protocol stack called Remote Audio Output Protocol (RAOP). RAOP piggybacked on top of the RTSP/RTP protocol.
And so you have to do any setup to find the server Apple also made its easy to use by supporting the multicast DNS protocol, aka Bonjour.
Side note: Back in the 90s I was running a number of mailing lists and under-the-radar conferences about cryptography and networking. One of the lists, net-thinkers was the catalyst for a really smart fellow named Stuart Cheshire who made Bonjour happen.
At the time though, the music industry executives were effectively blindsided by all the technological advancements were occurring and responded by suing everyone they could.
As a result Apple tried to maneuver their way around the legal fray by specifying that the RAOP protocol would use “encryption” to prevent anyone from copying the protected music.
Apple dubbed the RAOP protocol suite with the official trademark AirPlay
Funny thing about that encryption.
The best I can tell, the engineers at Apple busted needed a good enough solution to satisfy the lawyers. So what they did, was to encrypt the data stream using AES-128 in CBC mode with a random session key that they transported during protocol negotiation wrapped with an RSA 2048 bit key. Which was perfectly acceptable, and considered state-of-the-art at the time.
Since the music was streaming at real time, there are not so fearful that it would a major channel for music piracy. Oh and of course since it was proprietary, no one would be able to figure it out, right!
Well, it didn’t take long for those zany computer hackers out there on the internet to reverse engineer the system. Notably one fellow, Jon Lech Johansen quickly figured out how the protocol worked.
Interesting thing about that RSA key. Apple solved the key distribution problem by simply including a copy of the private key in the airport express software. Oh yeah, and to anyone else who licensed it by joining the Apple MFi cult.
Soon enough another fellow, James Laird alledgely took apart his girlfriend's AirPort Express and extracted the RSA private key. This enabled James Wah to construct a software emulation of the Airport Express called Shairport.
Shairport Sync
Shairport was pretty cool. But as with most open-source projects it required an endless amount of dedication and hard work to keep the ball rolling. James must have figured he needs a life beyond this and quit maintaining the code.
But Mike Brady stepped up back in 2014, forked the code, and created shairport-sync on Github. Shairport-Sync runs on Linux, FreeBSD and most notably, really well on Raspberry Pi. Mike then continued to move forward and added a plethora of features and bug fixes. Some of which include:
Outputs audio to ALSA, sndio, PulseAudio, Jack Audio, unix pipe, etc
Metadata from the source, such as Album Name, Artist Name, Cover Art, etc
MQTT support
Support for the Apple ALAC decoder
Output bit depths of 8, 16, 24 and 32 bits, rather than the standard 16 bits.
Output frame rates of 44,100, 88,200, 176,000 or 352,000 frames per second.
Limited AirPlay 2 support for audio sources
Mike put an amazing amount of time into this code, and in addition his instructions on building the code are flawless comprehensive and worked the first time.
Mike should be rewarded for his efforts and if you decide to use this his code I urge you to drop him a few bucks or at least a thank you note.
“Nothing compensates like cash.” — Guillermo Ortiz.
Shairport Sync on the piCar
So much for the history lesson. Shairport-Sync was perfect for what I need to do on the piCar project and interfaced well with the code I described in part 6 to stream audio to ALSA. Since what needed was a stream of 16 bit PCM data that I could redirect to my audio output processing thread. Which ultimately sends it off to the Digital to Analog converter (DAC) that drives the audio amplifier.
One of the shairpoint-sync build options allows you to select a backend that writes raw audio to be output through a unix pipe. This data is at a rate and format used by the audio CD red standard. And it matches how I setup my alsa output processor code.
Once connected, the audio you send from the iPhone to the raspberry pi gets pumped to the unix pipe at /tmp/shairport-sync-audio
.
You can open this pipe just like any unix file.
Once my code collects at least 4K bytes of data, using the standard unix read
API, it is sent to alsa using snd_pcm_writei.
And audio is played out the speaker.
There is alway room for meta-data
What would be the fun of having that cool VFD on our radio if I couldn't show the song and artist name playing. Well Mike was kind enough to add code to shairpoint-sync
to pipe meta-data supplied by the source to a unix pipe at /tmp/shairport-sync-metadata
.
Mike even posted some sample code to help you understand out how to decode it.
It’s pretty simple. Each piece of meta-data has a 4 character string for designated ssnc
(for 'shairport-sync') for all metadata coming from Shairport Sync itself, such as start/end delimiters, etc or core
for all the regular meta data coming from iTunes, etc.
In addition there is another 4 character code that is specific to that subtype: For example for ssnc
you might see
pbeg
- play stream begin.pend
- play stream end.
And for core
you might see:
asar
- along with a string for song artistminm
- along with a string for song name
I take this meta-data and do a slight bit of massaging on it before I display it. The data can be in Unicode format. After some experimentation I found that some artists like “Blue Öyster Cult” happen to have characters in their names that my Noritake VFD didn’t quite like.
Depending on the kind of display you have, you might need to normalize the metadata strings. A common way to handle Unicode processing is to use something like libicu, but it way too much cowbell for what I need. Instead, I used tiny-utf8 to decode the bytes. I then wrote a simple pattern matching utility to remove the diacritics and replace them with equivalent ASCII that was close enough.
One more thing…
Since this is running on a car radio, The raspberry Pi needs to host its own isolated WiFi network. There are a few options here. It could can look like a base station and provide a dhcp sever or better yet host as Wi-Fi Direct.
Once again, Mike was kind enough to write up some notes notes how to setup the Raspberry Pi so it automatically starts up shairpoint-sync and how to setup the dhcp host and how to speed up the boot time.
My next step is to setup the pi to emulate Wi-Fi direct, so I won’t have to keep specifying the Wifi network when I move back and forth from my car.