Lan Audio 2

All the pages here are not really designed to be used by the wider internet - they are mostly for my own reference.

However, should anyone wish to contact me regarding them, please feel free at: www |at| adoxa |dot| co |dot| uk

The aim is to have a LAN based audio distribution system, with the following specification:

  • Client/Server based arrangement
  • - Server is the central control point. All media/playlists, etc. are retrieved via here.
  • - Clients connect to server for media/playlists and are controlled via the server.
  • An arbitrary number of zones or groups into which each client can be placed.
  • Each zone will play the same thing.
  • A web-based control system on the server to remotely control all the clients/groups.

After various trials with different configurations, the following seems to be the most reliable:

  • Server machine runs five (currently) MPD instances, all of which feed into a single stream server (Snapserver).
  • Each client can connect to one of five (currently) possible streams generated by the server.
  • Each stream has synchronised playback to all connected clients.
  • Anything that can stream into a named pipe on the server can also be added as a stream.

I've settled on using Snapcast as the audio distribution system as it is relatively simple to setup, has pre-built Raspberry Pi packages, has quite a low processing requirement (for the clients), and easy-ish to control programatically.

MPD is used as a source of all the streams as it is also quite lightweight and has a wide variety of input types via plugins, and is easily controlled remotely. One of the five instances is the Master MPD, and the rest are setup as slaves to it - the master holds the library list, etc, and all the slaves get their information from it. This saves having multiple, possible inconsistent sets of library lists, etc.

After having slight dropout issues using a Raspberry Pi 2B as the server (the source of which remains unidentified), I bought a NUC6 to act as the server, which doesn't exhibit the dropout problem, and also has more processing power available. Also, having much more memory, a proper SSD, and network controller provide a much better platform.

The server having added CPU power and proper 1GBs network controller is potentially needed as if there are many WiFi connected clients, OGG streams may be needed rather than the current FLAC - Vorbis being a lossy audio format like MP3, but the conversion is done on the fly by the Snapserver, which is quite CPU intensive, unlike lossless FLAC encoding. I'll get some data together soon regarding data rates and CPU use for compressing streams, but as an example, a Raspberry Pi 2B running the Snapserver with a single active stream using FLAC, uses about 5-10% CPU. Changing to Vorbis VBR 0.5 quality upped it to 25-30%. Having two such streams pushed CPU use above 60%.

Each client is a Raspberry Pi of some description. The Snapcast client will install and run fine on any Pi version using the headphone socket as the sound output, however, even to my ears, the audio quality is not very good. Also, just using a Pi as a client requires that you have an amplifier and speakers for output, which means more trailing cables and mains sockets. To get round this, I use an Amp + DAC card for the Pi called X400, which has a 30W output - more than enough to power speakers for a single normal sized room.

The clients each have the Snapclient installed/configured, and pretty much nothing else. After a client test, there isn't anything else needing to be done. Currently only one of the 4 clients I have working uses wireless - the rest are all LAN based. Due to the flakiness of the WiFi signal in my house, the current FLAC streams will probably need to be changed for Vorbis ones, reducing the needed bandwidth. More details to be posted once I've got more WiFi clients configured.

Two of the current clients use wired ethernet via mains cable adaptors. So far, even with the very variable pings times using these devices, there have been no dropouts of the audio stream. This is an improvement over using RTP multicasting which seemed to be very susceptible to picking up lag from the ethernet mains adaptors and getting out of sync.

Since the clients don't do much after being setup, the OS can probably be run as a Read Only system, thus allowing the clients to simply have the power switched off at the mains to shut them down, rather than having to have the OS do a proper shutdown to avoid potentially scrambling the SD card filesystem. This would make it much simpler from the user point of view too.

The server side of the setup has also been changed to pull all the MPD instances into one place, and instead have multiple audio streams via the Snapserver. Currently I have 5 copies of MPD running feeding into five FIFO pipes for the Snapserver to provide the 5 audio streams. Each MPD can be controlled independently of the others since they're setup to use different ports (6600, 6601, 6602, …). This means you can use any MPD client anywhere on the network to connect to control the audio stream source, and the Snapcast Android controller to control the Snapserver from anywhere to move clients between stream groups, and to mute/rename/etc. them.

The software control side of things is a little more problematic as Apple devices have few if any apps for controlling MPD/Snapcast. The way I do it currently is to use a bit of software called YMPD which is a simple standalone web application that can be used to control an MPD instance. I've modified to to allow the control of the Snapserver as well, although not everything can be managed by it currently. Ideally, YMPD needs to be able to:

  • Connect to several MPD clients at once.
  • Manage the Snapserver streams (add/remove/rename/mute/unmute clients and groups).
  • Run on the media server machine.
  • Provide better handling of playlists.
  • Provide Smart playlists.

It may be easier to write a new client from scratch rather than try to shoehorn everything into the existing YMPD codebase.

Media Archive

This is where the actual audio files and playlists are located. In order for MPD to be able to use the data, there needs to be at least a readonly share on this machine, accessible by the media server, and all the media clients.

Personally, I use a Debian Linux server for this with Samba supplying a media share.

I think that the media server can be pretty much anything that can create a Samba/Windows share that can be at least read-only. Being able to write also allows playlists to be written if they're kept in the same directory tree as the audio. It also means that any of the clients can write to the audio files as well, which isn't a good idea. I'll have to move the playlists directory outside the music one and have a separate share for it.

Media Server

This is where all the audio is played and processed into one or more streams by Snapserver. All the actual audio data and playlists are kept on the Media Archive machine.

A Snapcast server instance is installed on this machine.

Install Debian Unstable on this machine - set hostname to 'media'.

Set ssh to run automatically on boot.

Set Media Archive share to mount automatically on boot - (fstab).

Update LAN DHCP server with MAC address and IP for media server and restart DHCP Server

sudo apt update
sudo apt upgrade
sudo install joe mpd alsa-tools alsa-utils telnet snapserver

There may be issues with the snapserver package not running properly - the .service file may need fixing by hand.

Do sudo joe /etc/mpd.conf and set music_directory “<mountpoint>” and playlist_directory “<mountpoint>” which get the audio files and playlists from the named share, alter bind_to_address to 'any', output to pipe, set port

To test, do telnet localhost 6600 which should display something like OK MPD 0.19.0 one one line - means MPD is working

Duplicate /etc/mpd.conf 4 times (mpd1.conf, etc.).

Duplicate /etc/default/mpd 4 time (mpd1, mpd2, etc.).

Duplicate systemd mpd file 4 times (mpd1, etc.).

Duplicate system mpd.socket file 4 times.

Edit mpd.conf - socket numbers, pid dir, and setup as slaves to the 6600 instance.

Repeat telnet test above for 6600, 6601, 6602, 6603, 6604

To test, do telnet localhost 6600, then update, then status, which should include updating_db: 1 near the end. Means MPD is getting audio file metadata from the source.

To add proper details to this.

Clients

These will have Snapclient running on it, output via ALSA.

Download Raspian Lite image from here

Unzip, and copy image onto a micro SD card dd if=/home/….img of=/dev/sdd bs=1M status=progress

Mount the 2 new created partitions on the SD

Do touch …/boot/ssh so the ssh server will automatically start on boot

Edit …/boot/cmdline.txt and add ip=192.168.0.x for temp static IP

Do scp snapclient_0.14.0_armhf.deb to RPi/home/pi/

Edit (as root) RPi/etc/hostname and set proper hostname

To add setup for X400 card

Unmount SD card, insert in RPi and boot

Do ssh pi@192.168.0.x

Do sudo apt update, sudo apt upgrade, sudo apt install joe alsa-tools alsa-utils

Do sudo joe /boot/cmdline.txt and remove ip=… item

Update DHCP server with hostname/mac from RPi

Do sudo dpkg -i snapclient… to install the snapcast client

Do sudo joe /etc/default/snapclient and add -h media

Do alsamixer and raise volume of PCM to c95%

For audio mixing, create /etc/asound.conf

pcm.!default {
  type mmap_emul
  slave.pcm "dmixer"
}

pcm.dmixer {
  type dmix
  ipc_key 1024
  ipc_perm 0660
  ipc_gid audio
  slave {
    pcm "hw:0,0"
    period_time 0
    period_size 1024
    buffer_size 8192
    rate 44100
    format "S16_LE"
    channels 2
  }
  bindings {
    0 0
    1 1
  }
}

ctl.mixer0 {
  type hw
  card 0
}

Restart RPi

Progress Notes

Hardware

The new setup of a NUC6 server with multiple Snapserver streams, each being supplied with audio data from a dedicated MPD instance seems to work rather well. I currently have 4 Raspberry Pi clients setup, one using WiFi, one using ethernet over mains, and 2 having direct ethernet connections. Streaming FLAC to all at once is fine. Having a second FLAC stream to 2 clients each also works fine. Need to see how having more WiFi clients affects things. May need to use Vorbis encoding to reduce bandwidth usage.

Would be nice to be able to plug in a random music source and have it fed into a stream - the media machine being in the livingroom. NUC should be Ok for this as it looks Ok, and is very quiet. Need to alter the LED thingy on the front to be more restrained than it is currently. Need to feed Line In through ALSA to a FIFO pipe for Snapserver. Could also try and get ALSA to mix all local audio into a single audio feed and then into a pipe so a media player could be run locally and fed into a stream as well.

Need some sort of case for the RPi + X400 board. The X400 isn't really designed well for this - the phono out and volume knob are on the same end edge which is also the RPi's SD end. Have to see if I can hack something together.

Software

Basic test of MPD/snapcast/Alsa synchronised audio. Seems to work as advertised. Two clients (a plain Raspberry Pi b+, and a Debian laptop) both setup to use a third Debian PC as stream source via ethernet cable, and left running over 18 hours. Still in sync after that time. Currently set up to stream FLAC.

Further test using a RPi2b as the master, a RPi3 via wireless, and a RPi2b as clients, only using PI onboard audio. Works very well. There was the occasional phasing effect, and a brief drop-out, but overall a good result over a couple of hours. Maybe the buffer size needs to be increased to cope with wireless irregularities.

Need to test performance of Audio Injector sound card on the RPi. Seems to work fine.

Need to test audio sync with Vorbis to minimise data rate. Seems to be fine. Need to do a listening test to see if I can hear any difference between Vorbis VBR 0.5, and FLAC.

Need to test audio sync over mains ethernet. This seems to be fine - as long as the spurious large changes in ping time don't get too great, which they haven't to date. Using WiFi would be better really as it would save a mains socket, save power (the mains/ethernet adapters get pretty hot even when doing nothing), and reduce trailing cables.

Allow hardware/software mixing on server for multi-source synched audio.

Found a I2S DAC and 20W stereo Amplifier board for the Raspberry Pi here which looks good, if anything for reducing the cable count. It's available via Amazon as well - search for 'Yosoo X400 Multifunction Expansion Board' for £23. This works well, and I've ordered some more. Volume is more than adequate for a small/standard sized room. One has been running in the kitchen client for a couple of months and has had no issues.

Finally got client output audio mixing working. It seems to be a bit over-complex. Need to see if it can be simplified. Not sure if this is actually needed now as there isn't an MPD instance on the RPi clients.

Need to get the OS running in Read Only mode - not to save SD card wear, but to allow for powering off by switching off mains.

Get some Wharfedale Diamond 9.1 speakers to listen to.

Web Control

Started this from scratch using YMPD as a base. This is a simple web based front end to MPD, and can control playback, modify playlists, create and save playlists, search and add tracks/albums from the library, handle internet streams. Once compiled, it runs from a single executable file and includes its own web socket server, and all HTML/JavaScript/etc. stuff all rolled up.

Lots of fun learning C, JavaScript, JQuery, Sammy, Bootstrap. Hmmm.

Added Snapcast listing of Clients.

Changed menu to icons rather than text to shrink it down a bit.

Added muting/unmuting of Clients.

Added naming of Clients.

Added Connected/Unconnected status of Clients.

Added showing the Artist name in Play Queue.

Removed need to get the entire playlist contents every second when playing a stream.

Updates Now Playing titles when stream contents change - ugly but there's no standard for streamed meta-data.

Need to find a way to pick a random track from the MPD library without having to download the whole thing.

Added permanently enbolding the currently playing track in the Play Queue (it used to go on and off irregularly).

Removed screen margins for very high pixel count screens (> 1200).

Added command line switches for Snapserver host and port.

Added another icon for Snapserver Groups.

Added listing of groups and streams.

Added adding/removing Clients from groups.

Added setting Stream for a Group.

Need to redo the Stream stuff as it looks really ugly. Add extra column for it?

Need smart playlists (all Artist, after certain date, never played, etc.).

Need to be able to connect to several MPD clients at once.

Save/Load playlists from local client.

Have Shutdown, Restart buttons for remote clients.

It may be easier to write my own client. We Shall see.

I've started writing a program from scratch that will allow the control of multiple instances of MPD, and also multiple instances of SnapServer (not sure how useful having more than one server is, but why not?). It has a dedicated page here.

Pictures

Can't go wrong with some pictures!

The Play Queue and general menu layout The Play Queue and modified menu bar.

Snapserver Clients page The SnapServer Clients page.

SnapServer Groups page The SnapServer Groups page.

  • lan_audio_2.txt
  • Last modified: 2018/08/11 19:56
  • (external edit)