Programming, philosophy, pedaling.

Modernizing my 1980s sound system

Nov 7, 2022     Tags: howto, music, workflow    

This post is the third in a series of posts on my music setup:

Where the last two posts were primarily about software (Navidrome and beets, respectively), this post will be more about hardware (and a bit of software to control it). Hopefully it’ll be useful to others with older sound hardware, especially those who are compelled (as I am) to avoid buying a “connected” device that’ll stop working after just a few years1.

TL;DR: I used a spare Raspberry Pi (version 3, Model B), an old USB DAC, and HiFiBerryOS with some unauthorized patches. As a result, I can now stream to my 1980s speakers from any device on my LAN, including anything that speaks AirPlay or DLNA! To tie things together, I use pulseaudio-dlna on my desktop to play music from my Navidrome instance via Sonixd.


A couple of months ago, a relative gave me their old sound system: a pair of KEF C30s (circa 1985) and a Yamaha RX-495 receiver (circa late 1990s, I think?).

The front page of KEF's brochure for the C Series

As far as speaker tech goes, these are pretty barebones: the C30s are passive monitors, with a single connector (two binding post terminals for banana plugs).

The receiver is slightly fancier: it can hop between radio stations based on signal quality (fancy!) and has support for 4 “programmable” presets. Nothing compared to modern receivers, but not the simplest either.

I have fond memories of listening to these speakers as a kid, and I’m loathe to let perfectly good2 hardware get thrown away just because it’s considered obsolete. I also run my own music server and curate it obsessively, so I thought it would be nice to have a “serious” listening setup that could stream from my server.

Thus, the plan:

  1. Put the sound system together (no explanation required);
  2. Figure out how to get music to it “remotely” (meaning, from my server, phone, or other source);
  3. Figure out how to control it “remotely” (meaning, pause and play it while sitting in another room, without just muting it);
  4. Ideally, expose it on my home network for houseguests during parties.
  5. Even more ideally, in such a way that they can play their own music, not just whatever I have on my server.

…and, critically, to do it all with only equipment I already own3.

Failed attempts

Attempt 1: connect a laptop to it

This was my first thought: I could just leave a laptop on the same table as the receiver, connect it as the “aux” source, and people could queue up music as they like.

I didn’t have a spare laptop (they’re all in use), so I pulled my Asus Eee 701 netbook4 out of the closet and tried to set that up.

A picture of the Eee 701. (This thing. Not my picture.)

This didn’t go well:

This attempt ended pretty fast.

Attempt 2: FM broadcasting

The receiver has an FM mode and an FM antenna, and I happen to have a short-range FM transmitter5. It should have a range of a few dozen feet, so I can set it up in my office and have it reach the receiver without any problems.

A picture of a CZH-05B FM transmitter. (Again, not my picture, just the same model.)

From there, I just need to send music to the transmitter: it has RCA inputs, so I can adapt those to 3.5mm and adapt to anything common from there.

This worked surprisingly well for my own purposes: I transmitted for a couple of weeks, using either my computer or my phone as the music source. Still, there were downsides:

Progress: rpi-audio-receiver and HiFiBerryOS

At this point I remembered that (1) I own a couple of Raspberry Pis, and (2) that they have onboard audio. I had no idea if that onboard audio is good or not6, but surely someone has tried to use a Raspberry Pi as an audio receiver before?

Google confirms that someone indeed has: Nico Kaiser has a project that does exactly that. It even includes all kinds of goodies that are ideal for guest use, including Bluetooth7, AirPlay, and Spotify Connect support!

There seem to be a decent number of happy users of rpi-audio-receiver on the Internet, but I didn’t end up as one of them. Instead, rpi-audio-receiver’s README led me to the repository for HiFiBerryOS, which in turn led me to the HiFiBerry website.

A screenshot of the HiFiBerryOS website.

This looked like exactly what I wanted: a tiny, minimal-configuration distribution that accepts any number of sound sources and turns them all into a simple analog signal for my receiver.

To get started, I performed the standard dance of flashing an SD card for my Pi:

$ # taken from https://github.com/hifiberry/hifiberry-os/releases
$ wget https://github.com/hifiberry/hifiberry-os/releases/download/v20221028/hifiberryos-pi3.zip
$ unzip hifiberryos-pi3.zip
$ # /dev/sdc is my flash medium
$ dd if=hifiberryos-20221028-pi3.img of=/dev/sdc bs=4M

Once flashed, I booted the Pi and followed HiFiBerry’s WiFi configuration steps. This was incredibly nice, since I didn’t need to muck around with an Ethernet cord or special configuration files8 — I simply connected to the temporary WiFi network being broadcast by the Pi itself, gave it a name (“leben”), configured a new WiFi network, and told HiFiBerryOS to forget its own network. It obeyed dutifully, and about a minute later I had http://hifiberry.local available on my LAN9.

Critically, I did all of this configuration from my phone, which still astounds me: I’ve never had such a painless experience configuring an OS and hardware before, much less a free OS running on a dinky little Raspberry Pi.

A small setback

At this point, I could actually see the Pi on my network, available as an AirPlay device:

A screenshot of my iPhone's sound picker, with the Pi as an option.

I connected to it successfully, hit play on a song, and…nothing happened.

More precisely, the Pi’s little web UI claimed that something was playing (the metadata is even correct!), but no sound was being produced:

The HiFiBerryOS UI claiming that music is playing, but with no sound coming out.

I initially assumed this was a problem with the Pi’s onboard audio (I’d never used it before), so I switched to a cheap Griffin “iMic” USB DAC that I’ve had floating around for years:

A photo of the Pi plugged into a USB DAC, which is then plugged into a 3.5mm audio jack.

…and still no audio. I knew that the DAC and the speakers/receiver themselves were working, so it had to be something about either AirPlay (unlikely, since discovery and metadata exchange were both working) or HiFiBerryOS itself.

A little bit of Googling later, and I found the reason: HiFiBerryOS intentionally does not support either onboard audio:

A forum posting by an admin explaining that onboard audio is not supported (linked above).

or USB DACs:

Another forum posting explaining that USB DACs are not supported (linked above).

This is an understandable position on their part: their revenue seems to derive primarily from sales of their own sound cards and related equipment, which they’ve designed and tested to meet their own quality and reliability standards. Supporting whatever junk people happen to plug in would inevitably require dedicated engineering resources, as well as fielding support to frustrated “customers” who haven’t actually bought anything.

As understandable as it is, I was still disappointed — I was so close to completing a sound setup without having to buy any new equipment.

I also knew that this limitation in HiFiBerryOS had to be in software, not hardware: it’s all just Linux (and probably ALSA) under the hood, meaning that USB audio should work right out of the box10. So, I resolved to hack it together.

HiFiBerryOS with a USB DAC

Fortunately for me, HiFiBerryOS comes with a SSH server installed and running by default, with default credentials of root:hifiberry.

I shelled in, and confirmed that Linux had indeed registered my USB DAC correctly:

# lsusb
Bus 001 Device 004: ID 077d:07af Griffin Technology, Inc iMic USB audio system
Bus 001 Device 003: ID 0424:ec00
Bus 001 Device 002: ID 0424:9514
Bus 001 Device 001: ID 1d6b:0002 Linux 5.15.72-v7 dwc_otg_hcd DWC OTG Controller

I also confirmed my ALSA theory by checking for the “standard” ALSA command-line tools:

# which aplay amixer
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: system [iMic USB audio system], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 1: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 [HifiBerry DAC HiFi pcm5102a-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

So, in principle, all I needed to do was figure out how HiFiBerryOS was configuring ALSA, and tell it to use card 0 instead of card 1 (which is presumably where the HiFiBerry would be, if one was installed).

Fortunately, someone on HiFiBerry’s forums had already figured this out: there’s a shell script at /opt/hifiberry/bin/reconfigure-players that contains a detect_hw function like this:

# Find the correct input and output hardware devices
# this is important if additional USB hardware is connected
detect_hw () {
 HW=`aplay -l | grep hifiberry | awk -F: '{print $1}'`
 HW_SHORT=`echo $HW | awk '{print $2}'`

…which would normally detect their hat-style DAC on card 1:

# aplay -l | grep hifiberry | awk -F: '{print $1}'
card 1

To “fix” it, all I had to do was patch detect_hw to discover card 0 instead, which I did by greping for the “iMic” string instead of “hifiberry”:

# Find the correct input and output hardware devices
# this is important if additional USB hardware is connected
detect_hw () {
 HW=`aplay -l | grep iMic | awk -F: '{print $1}'`
 HW_SHORT=`echo $HW | awk '{print $2}'`

I saved the file, used the HiFiBerry OS Web UI to reboot the Pi, tried playing a song again and…it worked!

Click to play on YouTube.

Streaming from my Linux desktop

This made me very happy: I could now stream from my phone, as could anybody else on my home LAN.

macOS also worked right out of the box, presumably via the same kind of AirPlay discovery.

That only leaves my desktop, which runs Linux (specifically, Ubuntu LTS). I already have a nice local player setup there (streaming from Navidrome using Sonixd), and I’d ideally I’d reuse it without any substantial changes.

As far as Linux audio goes, the solution here was shockingly easy: I use PulseAudio for my desktop audio and HiFiBerryOS supports DLNA streaming, so I installed pulseaudio-dlna and ran it:

$ sudo apt install -y pulseaudio-dlna
$ pulseaudio-dlna

This immediately discovered the Pi and added it to my PulseAudio sinks, allowing me to set it as my default via pavucontrol:

A screenshot of pavucontrol, showing the DLNA sink.

Once again, I played a song…and everything worked again! The latency between play/pause toggles is noticeable (about 1.5 seconds), but that’s not a dealbreaker for me.

As a curiosity, streaming via pulseaudio-dlna makes HiFiBerryOS think it’s receiving from a Chromium instance:

A screen should of the Web UI, showing that it thinks Chromium is streaming.

(This again doesn’t matter to me, since I don’t plan on checking the Web UI much. But it’s funny.)

Summary and next steps

To summarize, I now have:

The end result: anybody on my network (including friends and family during parties) can take over the “aux” without needing to find the cable, mess with Bluetooth pairings, &c — all they need is to be on my WiFi. An of course, selfishly and lazily, I no longer have to move 20 feet to change the music. Progress!

I’ve been working on and using open source software for a while now, but this little weekend project really drove home the value of open standards and free, pluggable, reusable work from hobbyists (like myself): I was able to do reuse hardware and software that I already owned and had configured, without having to worry about planned obsolescence or woeful security practices by random companies that feel the need to add “smarts” or Internet connectivity to their products11.

There are still some things I’d like to do:

I’ll probably do a successor post for those, at some point.

Finally, I’m going to plug the Ko-fi donation pages for the maintainers of Navidrome and Sonixd:

  1. Read: when the company that makes it no longer has any financial incentive to support their older products. 

  2. As it turns out, the woofer in one of the speakers is broken. But that will hopefully be an easy fix. 

  3. In an effort to reduce frivolous tech purchases on my part (and have some fun with junk in my closet). 

  4. Remember netbooks? 

  5. Specifically, I have the CZH-05B. I kept it on the lowest possible power mode and confirmed that it never exceeded FCC Section 15 limits (200 feet). 

  6. I still don’t. 

  7. Apparently it doesn’t work well at all with the Pi’s onboard Bluetooth. I don’t have an external Bluetooth dongle, so this wouldn’t have worked for me anyways. 

  8. I’m still salty about Raspbian’s manual user and SSH configuration, much less WiFi. 

  9. This was just for initial testing purposes. I subsequently plugged it into my network via Ethernet, and everything there was automatic. 

  10. Insofar as audio on Linux can ever be said to work “right out of the box.” 

  11. This isn’t to claim that any of this is particularly secure, by default (see e.g. the default SSH credentials for HiFiBerryOS). But I’d wager that it isn’t that different from the woeful state of commercial IoT security, minus the incentives for neglect (loss center) and obsolescence. Plus I can secure it myself, rather than treating NAT as a security boundary. 

Discussions: Reddit Twitter Mastodon