Skip to content

Commit

Permalink
Simplify language to something readable.
Browse files Browse the repository at this point in the history
  • Loading branch information
mjablons1 committed Feb 26, 2023
1 parent d344dcd commit 50752c8
Showing 1 changed file with 24 additions and 19 deletions.
43 changes: 24 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# raspberry-pi-headless-spotify-streamer
## A simple, reliable, headless spotify streamer setup using Raspberry Pi.
## A simple, reliable, headless Spotify streamer setup using Raspberry Pi.

<img
style="display: block;
Expand All @@ -8,13 +8,13 @@
width: 70%;"
src="graphics/concept_diagram.png"/>

If you want to easily control your spotify streaming from any spotify client session, playback high quality and, once configured, forget all about your RPi streamer, this is for you.
If you want to easily control your Spotify streaming from any Spotify client session, playback high quality and, once configured, forget all about your RPi streamer, this is for you.

Its
It's:

* Easy to set up and easy to run.
* Robust against RPi restarts.
* RPi does not need to "know" your spotify credentials.
* RPi does not need to "know" your Spotify credentials.

<details>
<summary>Click to learn more</summary>
Expand All @@ -28,7 +28,7 @@ Its
* RPi (I used RPi 2B equipped with a USB WIFI adapter and with Debian 11, bullseye image)
* USB class-compliant audio interface (I used MOTU M6)

The key software component will be an application called [spotifyd](https://github.com/Spotifyd/spotifyd). What's most interesting for us is that spotifyd supports Spotify Connect which is a feature that makes your RPi show up as a viable playback device in your official spotify application. You can find all instructions how to get it working here [Spotifyd Wiki](https://spotifyd.github.io/spotifyd/installation/Raspberry-Pi.html?search=ystesystem).
The key software component will be an application called [spotifyd](https://github.com/Spotifyd/spotifyd). Spotifyd supports Spotify Connect which is a feature that makes your RPi show up as a viable playback device in your official Spotify application. You can find all instructions how to get it working here [Spotifyd Wiki](https://spotifyd.github.io/spotifyd/installation/Raspberry-Pi.html?search=ystesystem).

Thanks, bye!

Expand All @@ -37,7 +37,7 @@ Thanks, bye!
<details>
<summary>...well yes of course, there is a catch.</summary>

If you are any demanding you will notice immediately that the audio quality with the defaults is much worse than streaming directly from your laptop over USB into your audio interface.
If you are any demanding you will notice immediately that the audio quality with the defaults is much worse than streaming from your laptop directly into your audio interface.

To make full use of your audio interface while streaming off RPi a few details need polishing. This article is mainly to help you know what need to be changed and where to get good audio quality while running within the computation limits of even an old RPi like the B2.
</details>
Expand All @@ -46,7 +46,7 @@ To make full use of your audio interface while streaming off RPi a few details n

## The setup (starting from the beginig)

We will first define a service in Debian to make it simple for spotifyd to be launched each time the system boots, without the need of any intervention from the user. We set off by creating a service definition file (you need to copy a file template from below so its best to start from desktop first):
We will first define a service in Debian. This will make it simple for spotifyd to be launched each time the system boots, without the need of any intervention from the user. We set off by creating a service definition file (you need to copy a file template from below so its best to start from desktop first):

```console
startx
Expand All @@ -72,7 +72,7 @@ After=network-online.target
[Service]
ExecStart=/usr/bin/spotifyd --no-daemon
Restart=always
RestartSec=12
RestartSec=8

[Install]
WantedBy=default.target
Expand Down Expand Up @@ -143,7 +143,7 @@ While it worked for me like this i heard:

## Optimization

Since this is old RPi and we are in a desktop env it should be expected to sweat and perhaps not all hope is lost, if we can boot to cmd line instead the CPU loads should be much lower. We can also tweak some defaults for sound quality that may be low. Therefore now come the optimization part!
An old RPi in a desktop env should be expected to sweat and perhaps not all hope is lost, if we can boot to cmd line instead the CPU loads should be much lower. We can also tweak some defaults for sound quality that may be low. Optimization - here we come!

### Set the maximum streaming bitrate in spotifyd

Expand Down Expand Up @@ -197,7 +197,12 @@ Kiss your desktop last goodbye and...
sudo reboot now
```

After restarting the spotifyd service should start automatically and make your RPi visible as playback device on your mobile phone really quickly now. You should hear less clicks, hopefully. Quality still more or less terrible. Excited? Lets optimize some more.
You should now observe:
* Your RPi becomes visible as playback device on your mobile phone really quickly now, confirming spotifyd is up on reboot.
* There should be way less clicks, hopefully.
* Quality may still be more or less inadequate.

Excited? Lets optimize some more.

### Check hw capability settings to check what sampling rate is actually used

Expand Down Expand Up @@ -254,7 +259,7 @@ pacmd list-sinks

Sample rate and buffer size are definitely two points that could use some improvements.

I initially started looking for some alsa config files that would contain these settings but could not find any. It turned out that Debian uses Pulseaudio server between your app and alsa and it happens to control sample rate and buffer sizes, alsa just consumes them:
I initially started looking for some alsa config files that would contain these settings. It turned out however that Debian uses Pulseaudio server between your app and alsa and it happens to control sample rate and buffer sizes, alsa just consumes them:

<img
style="display: block;
Expand All @@ -265,13 +270,13 @@ I initially started looking for some alsa config files that would contain these
width: 60%;"
src="graphics/streaming_path.png" />

AS a separate item, we have the performance issue (sill occasional clicks even in cmd line mode) To see what's cooking with the performance
As a separate item, we have the performance issue (sill occasional clicks even in cmd line mode) To see what's cooking with the performance

```console
top
```

Both Pulseaudio and Spotifyd consumed 15-25% of the CPU time each.... thats way too much! Let's see what can be done.
Pulseaudio and Spotifyd consumed 15-25% of the CPU time each.... thats way too much! Let's see what can be done.


</details>
Expand All @@ -298,7 +303,7 @@ cp /etc/pulse/daemon.conf ~/.config/pulse/
vim ~/.config/pulse/daemon.conf
```

This file readily contains a lot of commented defaults. Don't forget to remove the semicolon before each line you wish to modify, here are the ones I modified (I checked quite a few combination but tried to make as few changes as possible in the end since I'm otherwise a great fan of, well, default defaults):
This file readily contains a lot of commented defaults. Don't forget to remove the semicolon before each line you wish to modify. I checked quite a few combination but tried to make as few changes as possible in the end since I'm otherwise a great fan of, well, default defaults. Here are the points of change:

```console
-----daemon.conf-------------------------------
Expand Down Expand Up @@ -329,15 +334,15 @@ default-fragment-size-msec = 200

<details>
<summary>Click to expand</summary>
The default resampling was actually optimized for computation but since this impacts quality i have eventually pushed it up to sinc resampling. To offset that computation cost (and probably few other) in half I set <a href="https://wiki.archlinux.org/title/PulseAudio#Configuration">enable-remixing = no</a> - this effectively reduced streaming from 4 channels to 2 channels only. Checking with CPU loads Pulseaudio went to about half right a way. The last settings set a huge, 2x200ms buffer to minimize clicks from buffer underrun. (this also puts a large lag between your app controls and the sound output but then think of how expensive RPi4 is and forget all about it)
The default resampling was actually optimized for computation but since this impacts quality i have eventually pushed it up to sinc resampling. To offset that computation cost (and probably few other) I set <a href="https://wiki.archlinux.org/title/PulseAudio#Configuration">enable-remixing = no</a> - this effectively reduced streaming from 4 channels to 2 channels only on my MOTU M6. Checking the loads- Pulseaudio went to about half the CPU time right a way. The last settings set a huge, 2x200ms buffer to minimize clicks from buffer underrun. (this also puts a large lag between your app controls and the sound output but then think of how expensive RPi4 is and forget all about it)

</textarea>

</details>

----

After making these changes restart the Pulseaudio and spotifyd services and check again the alsa settings to confirm the new settings are in effect, you should see sample rate and buffer size updated now:
After making these changes restart the pulseaudio and spotifyd services. Then check the audio settings again- you should see sample rate and buffer size updated now:

```console
systemctl --user restart pulseaudio.service
Expand All @@ -347,15 +352,15 @@ pacmd list-sinks

----

This is it. With all these changes I was finally happy with the sound quality (and I'm a real pain-in-the-ass guy in that respect, as you can tell by now).
This is it. With these changes I was finally happy with the sound quality (and I'm a real pain-in-the-ass guy in that respect, as you can tell by now).

<details>

<summary>Click to expand</summary>

I noticed much later that with very very loud music that uses compressors src-sinc-best-quality actually causes clipping. You can overcome this by pulling spotify app volume down by a nod or two though. You can also try other resampling methods.
I noticed much later that with very very loud music that uses compressors src-sinc-best-quality actually causes clipping. You can overcome this by pulling Spotify app volume down by a single nod. You can also switch to other resampling methods.

In this place some of you may wonder what should resampling change. It's definitely a good question and I have no clear answer to that, after all when we resample we begin signal reconstruction starting at the sample data as streaming from the service provider. This said I can hear a clear improvement going from 41kHz to 96kHz. I expect that, for once, some of the materials are in 48kHz format to begin with so we don't squander that down to 41kHz. Moreover, by upsampling we actually increase the bit depth of the data points above 16bit and that may be audible as well. Finally we've reduced the compression by requesting 320kB/s data stream instead of the default 160kB/s - here there i no doubt this is audible and has pretty much the same effect as going from normal to very high sound quality setting in the official spotify app.
In this place some of you may wonder what's the point of upsamplng. It's definitely a good question and I have no clear answer to that, after all when we resample we begin signal reconstruction starting at the sample data as streaming from the service provider. This said I can hear a clear improvement going from 41kHz to 96kHz. I expect that, for once, some of the materials are in 48kHz format to begin with so we don't squander that down to 41kHz. Moreover, by upsampling we actually increase the bit depth of the data points above 16bit and perhaps that may be audible as well. Finally we've reduced the compression by requesting 320kB/s data stream instead of the default 160kB/s - here there is no doubt, this is audible and has pretty much the same effect as going from normal to high, or very high sound quality setting in the official Spotify app.

</textarea>

Expand Down

0 comments on commit 50752c8

Please sign in to comment.