Squeezelite + Rhasspy - Poor audio quality

I have been having great success using the ReSpeaker 2-mic hat on a pi zero as a Rhasspy satellite.
I also run a Logitech Media Server on my host machine for streaming music to dedicated players around the house.

While trying to get squeezelite running on the Rhasspy satellite i found something a little strange with the audio quality. With Rhasspy and Squeezelite running simultaneously, the audio quality coming from squeezelite is pretty terrible. (Sounds highly compressed?).
If i change the Rhasspy aplay device to something other than “sysdefault:CARD=seeed2micvoicec”, the Rhasspy audio out breaks, but the squeezelite audio output is vastly improved.

I don’t really know enough about this setup to know whats going on with aplay, but i would appreciate any support in getting pointed in the right direction.

EDIT: I have been digging through this post for ideas (Playing sound at the same time from Rhasspy (Docker) and the host) , the only major difference here is that my audio playback is working for both audio sources, its just very poor quality when it is working.

Some more info below:
cat /etc/asound.conf

defaults.pcm.rate_converter “samplerate”

pcm.!default {
type asym
playback.pcm “playback”
capture.pcm “capture”
}

pcm.playback {
type plug
slave.pcm “dmixed”
}

pcm.capture {
type plug
slave.pcm “array”
}

pcm.dmixed {
type dmix
slave.pcm “hw:seeed2micvoicec”
ipc_key 555555
}

pcm.array {
type dsnoop
slave {
pcm “hw:seeed2micvoicec”
channels 2
}
ipc_key 666666
}

When playing from Squeezelite with Rhasspy turned off, i get the below output from cat /proc/asound/card0/pcm0p/sub0/hw_params

access: MMAP_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 441
buffer_size: 1764

With Rhasspy enabled, it outputs the below

access: MMAP_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 16000 (16000/1)
period_size: 2000
buffer_size: 8000

It seems like with both running together, it is forcing the sample rate lower which is causing the poor squeezelite audio quality.

Well, after some rambling to myself and a lot of trial and error, i think i have it working now.

I used the below config to create two new “virtual” sound devices, and then link them to the dmix device which is set to output to the respeaker2. I also had to change the docker command for rhasspy to accept the asound.conf file from the host system.

/etc/asound.conf

pcm.mix {
type dmix
ipc_key 1024
ipc_perm 0666
slave {
pcm “hw:seeed2micvoicec”
period_time 0
period_size 1024
buffer_size 4096
rate 48000
format S24_3LE
}
bindings {
0 0
1 1
}
}

pcm.squeeze {
type plug
slave.pcm “squeeze_vol”
}

pcm.squeeze_vol {
type softvol
slave.pcm “mix”
control {
name “Squeezelite”
card 0
}
}

pcm.rhasspy {
type plug
slave.pcm “rhasspy_vol”
}

pcm.rhasspy_vol {
type softvol
slave.pcm “mix”
control {
name “Rhasspy”
card 0
}
}

Docker

docker run -d -p 12101:12101
–name rhasspy
–restart unless-stopped
-v “$HOME/.config/rhasspy/profiles:/profiles”
-v “/etc/localtime:/etc/localtime:ro”
-v “/etc/asound.conf:/etc/asound.conf”
–device /dev/snd:/dev/snd
–ipc=“host”
rhasspy/rhasspy --user-profiles /profiles --profile en

I just need to get the recording working again, but i think i am on the right track. Hope all this rambling helps someone else in the future. :grin:

1 Like

If you look at the default alsa.conf of the 2 mic

# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one


# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    slave.pcm "hw:seeed2micvoicec"
    ipc_key 555555 
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:seeed2micvoicec"
        channels 2
    }
    ipc_key 666666

The first part of the chain is the dmix and dsnoop which act as mixers/splitters for hardware pcm they relate to.
Then that is called from a plug which is a software auto conversion for rate and sample format.
Then its finally offered to the system as a default device with a asym bring play & capture together.

Not really sure why you have put in a softvol either?
But likely as rhasspy both records and plays at 16k S16_LE with no rate convertors or auto plug pcms your probably not going to have much luck.

The respeaker is setup so you should just have to pick the default system device.
Alsa is a never ending source of confusion but maybe if you add another pcm playback2 and use that for squeezelite all will play nice.

pcm.playback2 {
    type plug
    slave.pcm "dmixed"
}

I am never really sure inside and outside a container you should still have different IPC keys.
At a guess make a clone asound.conf somewhere with different ipc (just change the last number) and just share it in the docker container in /etc/asound.conf

It was mostly because the Rhasspy voice volume was too loud vs the Squeezelite volume. I wanted the seperate channels to control their volume.

Your recommendation just to add another playback device did not work, I am not sure why.

When browsing Rhasspy to select the audio device, it has them listed as “Pulse Audio Server {Device Name}”


I am not running pulse at all on the pi, should i be?

No pulse prob makes the docker situation and setup more problematic, just that if you had picked the Desktop version of RaspiOS its now installed by default in the image.

I guess if you do a search for the gstreamer rhasspy output code on the forum and rather share get rhasspy to use squeezlite as an output.
I dont know squeezelite as more of a snapcast fan but even that is becoming foggy as haven’t used for a while but presume there is a socket on squeezelite that you can broadcast to?

But maybe if you set the output of Squeezelite to 16k S16_LE as much high quality audio is that both would just work together.
As only high end audiophile snobs seem to be able to tell the difference between 48Khz S24_3LE and more standard formats as you are still playing through some low end Pi hardware so your studio grade audio settings seem a little OTT.
Is there a squeezelite config so you can set the same as rhasspy.

ALSA

Plays WAV files on the local device by calling the aplay command. Should work with ALSA and PulseAudio.

Add to your profile:

"sounds": {
  "system": "aplay",
  "aplay": {
    "device": ""
  }
}

If provided, sounds.aplay.device is passed to aplay with the -D argument. Leave it blank to use the default device.

You may set sounds.aplay.volume to a value in [0, 1] where 0 is off and 1 is full volume. This can be changed at runtime through the rhasspy/audioServer/setVolume message or the /api/set-volume HTTP endpoint.

WAV audio sent to this service is automatically inspected for an INFO chunk. If present, it’s value is deserialized a JSON object and a “volume” property will used to determine the final playback volume (e.g., { "volume": 0.5 }).

I did originally look at doing this, however its a big complicated as it involved backup up the current playing playlist, sending the TTS, then restoring the playlist that was playing. It will be my fallback plan should i not be successful with this.

I would also normally agree with the sound quality being overkill, but the difference between the two is very noticable.

Just to confirm, Rhasspy listing all the asound.conf adapters as “Pulse Audio Sound Server” is normal?

Also, if i play music via Squeezelite, then start up rhasspy, the audio output for both works at the same time as expected at the better audio quality. But if i stop playing music on Squeezelite and the audio connection times out (After 5 minutes i think) it then will start playing back again at the lower audio codec.

The pcm.capture adapter also doesnt show up in Rhasspy as an input device.

I would say you have pulse audio running as well.

Pulse audio actually runs on top of alsa you never really get rid of alsa but pulseaudio takes control.

Maybe due to squeezlite install? I just don’t now squeezelite but presume someone here will get you running.

No worries, let me get the alsa config working without squeezelite for now.
Thanks for the help so far.

1 Like

Quick update, with a fresh install of the Pi Zero and Rhasspy, i was still unable to get it to play to any of the alsa playback devices from Docker, I could only get it to play to the hw:0,0 device. I am very unfamiliar with Docker, so i switched over to the Debian install. I have it working pretty great so far with Squeezelite playing at a much improved audio quality, and Rhasspy able to play audio on top of Squeezelite.

1 Like

You got it working :slight_smile:

docker run -d -p 12101:12101 \
      --name rhasspy \
      --restart unless-stopped \
      -v "$HOME/.config/rhasspy/profiles:/profiles" \
      -v "/etc/localtime:/etc/localtime:ro" \
      --device /dev/snd:/dev/snd \
      rhasspy/rhasspy \
      --user-profiles /profiles \
      --profile en

Docker is an isolated container so it sounds like you never had alsa setup inside as even though the device was shared it has its own files inside the docker conatiner.

-v "$HOME/.config/rhasspy/profiles:/profiles" \

As an example that shares $HOME/.config/rhasspy/profiles and in the container makes it avail at /profiles.
So to share /etc/asound.conf

-v "/etc/asound.conf:/etc/asound.conf" \

I am never sure if the IPC keys should be different and you should just clone one somewhere with different.
cp /etc/asound.conf /etc/asound2.conf or where ever or whatever you want to name it.
Then

-v "/etc/asound2.conf:/etc/asound.conf" \

Kill and delete the running docker and then run the docker run again.

To connect to a running docker and see what is going on inside

docker exec -it <mycontainer> /bin/bash

then its just the same as ssh without ssh all commands are internal and aplay -l might look very different as you are in the container.

Thanks so all your help so far!
Do you think there is any benefit for me to try get it working in docker? Now that its at least in a working state, i don’t mind spending a bit more time with another device to try get it working with Docker if that is at least the future vision for Rhasspy.

You have it working but once get over the first hurdles with docker and grasp a couple of the initial commands then docker is really useful to isolate applications / services and have instances running over a virtual network.

You got the deb install running but sometimes you can run into dependency hell with all-in installs and docker is just great for that with near zero overhead.

once you grasp docker is essentially a separate computer running on yours and how to connect and setup its pretty amazeballs as much as it can confuse.