2024, May 05    

For many years I've wanted to experiment with software defined radios, listening to signals around the globe that can be received at home. I've often found myself on the WebSDR websites listening to foreign radio or obscure signals, curious as to what they are / why they exist. As I've managed to complete many items on the todo list I decided to get started with the technology and see what I could achieve / how deep the rabbithole goes. As it turns out, quite deep...

There are many pieces of hardware available to get started with SDR, and while it would be temping to go straight to a LimeSDR/KiwiSDR/HackRF One, none of these are a cheap starting point. I decided to go the route of the RTL-SDR v4 dongle (available from many retailers including Amazon), which can be purchased in kit form to make things easier (as it contains an antenna / extension cable / tripod / window mount). For the uninitiated, the origins of these dongles are that of TV/DVB-T USB tuner dongles (commonly produced by companies such as Hauppauge) that allow you to watch live TV on a computer. I recall using these many years ago, specifically 6 of them to cover all DVB multiplexes simultaneously, creating an easy way to stream live TV across a network (work projects can actually be fun). Given the hardware provided is small / unobtrusive, it makes for a great way to get started and makes fitting somewhere permanant easy (or at least easier than a 10m antenna bolted to the side of the house).

As with most technology there are always quirks, and this hardware is no different. The v4 version of this dongle requires a modified driver (out-of-kernel) to work correctly, and sadly (at time of writing) there doesn't appear to be a DKMS package to cover this. Thankfully, the build process for the driver is straightforward and on both Raspbian and Ubuntu Server it worked without issue. One script later and I have an easy way to build the driver/utilities (required each time the kernel is upgraded). A quick test via the CLI shows the USB adapter is found / is able to stream data (so far so good).

Choosing the software to use is where the waters get very muddy. For those running Linux interactively / directly there is GNU Radio (a comprehensive piece of software) and multiple similar applications that work well. For those that are using other platforms / want to use it in a remote access fashion it starts to get interesting. My first thought around this was to use a containerised application and give it access to the USB device, however it didn't take long to see that not only was Docker Hub short on offerings, the majority of them were out of date (in some cases by years). This was the first point where my confidence in getting a working solution was knocked...

My first hope (that was subsequently shattered) was to use the same software as WebSDR, creating a web-based listener that would allow me to listen on any modern device. Unfortunately, the software is only available to users that host publically, which for someone starting out isn't initially viable. Thankfully, a piece of software called OpenWebRx exists which aims to provide the same (technically more) functionality while being open-source. A few commands in Docker later and the software was installed / I had a working UI. Great I thought, but then I stumbled across the next quirk (actually a restriction). The software is designed for more professional users who want to share prediscovered stations / broadcasts within specific (fixed) frequency ranges, removing the ability for moving the base channel. In short, you can only listen to broadcasts around this base frequency, and the range depends on the capability of your device. As the RTL-SDR as 2.4 MHz of bandwidth when tuned to a frequency, this is like listening to Radio 1 and finding you can't listen to anything else as the needle is fixed. Truth be told it took me longer than it should have to determine this is why I couldn't change frequency in an easy fashion, wasting time believing it was a driver issue and that something in the compilation / installation had gone wrong.

After discovering an obscure GitHub issue that highlighted the restriction around base frequency, I was pointed in the direction of OpenWebRx+. This is a fork of OpenWebRx but is designed to be more user-friendly, allowing the retuning / changing of the base frequency via the UI. Back to Docker I went, thinking things would be simpler this time as it should be a similar process to install, and a new container was created. Did it work? No... The UI was badly broken due to files being unavailable. Thinking it might be a bad nightly build I started investigating, only to find that as my system had IPv6 disabled it wasn't starting one of the background services correctly. A quick tweak to the confirmation to disable IPv6 support and the UI was functional, though after seeing block events in the firewall logs due to the container attempting to download files from the internet, I wasn't confident it would function correctly. Thankfully the UI did work and I was able (after reading the manual) to tune to different stations and listen to basic FM radio. A measure of success at this point, but I still felt there was more to gained / more to be had from this setup. As I still wanted to have an app running locally (but fed data from a remote source) there was still work to do.

More late-night searching revealed another popular SDR app called SDR# (by Airspy), which amongst other benefits has the ability to stream the device over the network (without using a web interface). While there doesn't appear to be a MacOS client, the server component can run on Linux and opens up the ability to stream to other software. As the software is precompiled its a quick download / install, and within 5 minutes it was running and ready to stream data. Grabbing another piece of software (SDR++) provided the MacOS client, gettings things into a great position for remote streaming (or so I thought). With everything configured the connection was established and audio started coming through, however the audio was periodically glitchy resulting in a bad experience. Switching back to the web interface confirmed this issue wasn't present when listening to it via a web browser, thus began the investigation / frustration.

SDR Display 1
Success! (finally)

While I'm all for troubleshooting, wasting a day trying to fix an issue which actually is due to the app not having a buffer to handle the tiniest of network glitches, is not exactly fun / confidence-inspiring. Starting with the basics of checking the network is performing as it should, disabling every possible component on the system to reduce context-switching / interrupts, switching to a low=latency kernel, switching physical hardware, all in vain. After much frustration, I came across another obscure GitHub issue (and sadly more negativity / toxicity) regarding audio corruption that might be related to the network. The amount of comments regarding WiFi not being able to support the required bandwidth, how it was all a bad idea, is disheartening to say the least. WiFi isn't what it once was, and with speeds exceeding Gigabit Ethernet the constant skepticism frankly should have died with 802.11b. Regardless, the issue confirmed that the software doesn't have a buffer and that the slightest glitch in in the stream would cause a framing issue and the audio corruption. The suggestion of adding a buffer was met with yet more negativity, yet again highlighting why novice users are put off. Sadly for me, the only fix (workaround) is to ensure as direct of a connection as possible, or switch back to the web-based interface. Another quirk that caused an issue was the Codec daemon (deployed as a dependency) comsuming 100% CPU across two cores. Investigating this revealed that not having IPv6 enabled on the platform causes it to get stuck in a loop (hence the wasted CPU cycles), thankfully a configuration change fixed this.

As a last attempt and trying to improve the situation I decided to try the SDR++ server component instead of Spyserver. Unfortunately the pre-built binaries aren't available for my choice of platform, and attempting to use the standard 64-bit version resulted a page full of errors and frequent crashes. Some trial and error later and I had a cleanly compiled version of the code, disabling all the unwanted parts, and having only the required functionality. Thankfully it worked and audio was streaming with the matched software, however the periodic audio corruption was still present (thankfully not that often). Still, now I have the ability to switch between the web interface or a native stream. That said, it didn't take long to realise that the additional plugins in OpenWebRx+ outweigh those in SDR++, even on basic things like listening to DAB radio.

With usable progress made it was time to expand the hardware, opting to buy another RTL-SDR v4 dongle in order to use both devices at the same time (one via web, one remotely). Thankfully this part was easy, though both pieces of software (OpenWebRx+ and SDR++) don't make it easy to mask out a device so that only one of them can be chosen. More experimentation on attempting to get decent AM/LW radio failed, even with a Ham-It-Up converter. Adding a wideband low noise amplifier (separate to the LW testing) worked well, to the point I ordered another one to improve overall noise levels.

With the AM/LW radio still being illusive I ordered a cheap loop antenna to see if that would improve the situation. Emphasis on the cheap at this point, as it did so little you could barely tell, and honestly it doesn't look the part either. With stress levels on the rise again, I decided to move away from the RTL-SDR devices and purchased a RSPdx-R2. This piece of kit is a serious step-up from the previous devices, having three antenna ports (with one of them being specifically for AM/LW/MW) and a much better receiver. First impressions were great, noticing that when listening to FM radio the RDS display in OpenWebRx+ actually worked, detailing both the station and the track currently playing. Sadly, even with this improved hardware my cheap loop antenna was still useless.

So where is everything at you may ask... Well, listening to anything FM upwards appears to work well for the most part (DAB is still partially problematic due to compatibility issues between the underlying dablin software and OpenWebRx+). AM radio is still a challenge, however a proper loop antenna (to the tune of around £600) is on order which should resolve the situation. The Raspberry Pi 4 has been reinstalled, stripped to the bare minimum, and runs the required software with ease. Going forward (once the final antenna arrives), I will finally be able to listen to broadcasts from around the globe (audio or otherwise), and experiment with the various decoder plugins.

As for what's next, other than finding obscure radio stations that pique my interest, more work on compiling the software is definitely next. There are plugins for various datasources, some sattellite, even DAB radio (looking at you SDR++), that I'd like to get running on the local client (and potentially other plugins for OpenWebRx+). If I can get things working smoothly (and get a half-decent upload speed, thanks BT) I might look at adding it to the public list for others to use.