Generating FM MPX on a Raspberry Pi 3
It’s been possible to turn your Raspberry Pi into a little FM transmitter for quite a while now. Download the right software, attach a wire to the GPIO pin in and you’re broadcasting a surprising distance.
But what about stereo or RDS? Turns out that you can team your Pi up with your exciter and get the whole lot for less than you expect. With the right parts and configuration, you can generate the multiplexed signal that feeds a transmitter (or “exciter” as you’ll hear it called) straight out of a Raspberry Pi 3.
That’s great but what exactly does it mean? Let’s look at what makes up a broadcast FM signal. Before going into a transmitter or exciter that’ll do the actual frequency modulation, we build up a baseband signal from a few different parts.
Between 0 and 15kHz you get the mono audio mix, that’s left and right combined into one. This is the bit that survives best when you’re struggling from poor reception. Not bad as a fallback option really.
At 19kHz is a steady tone called the “pilot tone”. It’s used to indicate that there’s a stereo transmission and turns on that little red light on your radio. As you can guess, it means we can be a little sneaky and turn the light on without actually broadcasting in stereo.
In reality, you’re more likely to see transmissions deliberately in mono. If you’re after a robust signal in challenging terrain, you’re better leaving that stereo light off.
To encode the actual stereo audio, L-R sits between 23kHz and 53kHz, centring on 38kHz (2x 19kHz). The way it’s encoded is slightly different from how the L+R bit is done (it’s a double sideband signal rather than raw audio) but is combined with L+R to generate the left and right channels. Specifically (L+R)+(L-R) gives 2L and (L+R)-(L-R) gives 2R.
Finally for us, centred at 57kHz (3x 19kHz), you’ll find RDS. This is the bit that carries the text you see on your radio’s display and can also trigger that really annoying feature where traffic bulletins burst in over your favourite CDs.
Ok, that’s underselling it a bit. It can also inform your tuner as to what frequencies other transmitters are on and it can even carry traffic or telemetry data as well.
So, taking that into account, that’s around 60kHz of multiplexed “audio” signal you need to feed into your transmitter or exciter. Accounting for something called the Nyquist Frequency that applies to digital systems and it turns out you need a sample rate of at least 120kHz.
So, the Raspberry Pi’s built in audio interface isn’t quite going to do the job for us. Thankfully the Cirrus Logic (ex-Wolfson Audio) audio interface for the Pi exists. Even better, it works with the Pi 3.
Getting it going involves a little bit of work. You start by installing the full Raspbian desktop image onto a micro SD card and running it on the Pi. That gets the operating system installed but doesn’t get the sound card working.
Turns out you need to replace the kernel with one that has the driver in it. While admittedly it feels like stepping back into the early days of Linux where compiling a kernel was an alarmingly regular suggestion for getting things working, there is a way round in this case. If you go to this website, not only will you find pre-compiled kernels but you’ll also find full instructions for installing all the required tools.
If you’re planning on following the steps in here for yourself, it’s worth noting that you will need MMAP support and you really do need the initialisation scripts. Is it embarrassing to admit that one caught me out?
Either way, you’ll also need the software I used to generate the multiplexed signal – Stereo Tool. There’s a version pre-compiled for the Raspberry Pi 2 that also works just as well on the Pi 3.
Now, I’ll admit this is commercial software. However, it’s available free to try (great for experimenting) and actually does the job really well. As I’ve stated in previous posts, it competes with some hardware audio processors you see in live deployment today.
Getting it going on Linux does require you to know and work with jackd – one of the many audio frameworks you could bump in to. The benefits of jackd include the ability to directly connect any audio software tool, source or destination together. This is something I took advantage of in the experiment I set up – a web stream from VLC plumbed through Stereo Tool and output from the Cirrus Audio interface.
While generating the multiplexed signal involved simply ensuring the sample rate of jackd was set to 192kHz and turning on the right options in Stereo Tool, there was a couple of catches. There’s not quite enough “grunt” in the Pi to both process the audio and generate the multiplexed signal. It’s a shame but not really a surprise. Desktop systems sometimes struggle to meet the challenge and the original Raspberry Pi struggled to perform MP3 encoding in real time.
While thankfully the audio stream I was pulling was already processed, it’s something you’d need to consider if your were ever brave enough to take this live to air. Especially as running anything more than simple clipping will cause audible stuttering.
That said, the Pi has somewhat proven itself a solid option for streaming audio for broadcast, especially with software such as OpenOB. Generating the multiplexed signal for FM transmission isn’t much of a stretch from there.
Another problem is a more practical one – there’s no case I’ve come across that supports both the Pi and the Cirrus Logic audio interface. Leaving an exposed circuit board in a remote location doesn’t strike me as the most reliable option.
Admittedly, that’s a minor issue. The neat bit was being able to generate the signal on a small, low-priced computer with little effort. Even if it wouldn’t be the most practical solution for such a case in the real world.
Now, if only I had an exciter kicking about, I’d love to show you the thing actually working on a real FM receiver…