GioF71 / squeezelite-docker

Easily run SqueezeLite with Alsa or PulseAudio output with Docker. Bluetooth support. Upsampling 2x 4x 8x with "Goldilocks" settings by Archimago
Apache License 2.0
33 stars 10 forks source link

[Feature Request] Custom asound.conf for 7.1 USB Sound Card with 8 individual channels #283

Closed dreitakter closed 5 months ago

dreitakter commented 5 months ago

Hi. Thanks for develop this great docker :)

I want to use your container for audio playback to a specific output of a USB 7.1 Soundcard. I have found a asound.conf that works locally

asound.conf

######################################################################### ## CUSTOM ASOUND.CONF by mfd https://knx-user-forum.de/member/7968-mfd ######################################################################### ## Channel splitting your UA0099 USB sound card to get up to four ## independent stereo outputs (...and more ) ######################################################################### ## stereofront = the FRONT labeled green jack ## stereosurround = the SURROUND labeled black jack ## stereocenter = the CENTER / BASS labeled yellow jack ## stereoback = the BACK labeled black jack ## stereoall = all stereo outputs ## ## for up to eight mono output channels use: ## ## monofrontl = the FRONT labeled green jack - tip ## monofrontr = the FRONT labeled green jack - ring ## monosurroundl = the SUROUND labeled black jack - tip ## monosurroundr = the SUROUND labeled black jack - ring ## monocenterl = the CENTER / BASS labeled yellow jack - tip ## monocenterr = the CENTER / BASS labeled yellow jack - ring ## monobackl = the BACK labeled black jack - tip ## monobackr = the BACK labeled black jack - ring ######################################################################### ######################################################################### ## labels and colors could be different for differnt vendors or ## versions of the device (Logilink, Sewell, Sweex, ...) ######################################################################### ## put this file into your /ect/asound.conf ######################################################################### pcm.logilink { # alias for our sound card type hw # must be hw in our case card 1 # check your correct card number by typing device 0 # 'aplay -l' in your terminal } # the 1st usb card on the Raspi shows as # card 1: Device [USB Sound Device], device 0: USB Audio [USB Audio] ctl.logilink { type hw card 1 device 0 } pcm.dmixer { type dmix ipc_key 1024 # must be unique number on your system ipc_perm 0666 # neccesary for normal user to have access slave.pcm "logilink" slave { period_time 0 period_size 1024 buffer_size 4096 rate 44100 channels 8 } bindings { 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 } } pcm.!default { type plug slave.pcm "dmixer" } pcm.stereofront { type plug slave { pcm "dmixer" channels 8 } ttable.0.0 1 ttable.1.1 1 } pcm.stereocenter { type plug slave { pcm "dmixer" channels 8 } ttable.0.2 1 ttable.1.3 1 } pcm.stereoback { type plug slave { pcm "dmixer" channels 8 } ttable.0.4 1 ttable.1.5 1 } pcm.stereosurround { type plug slave { pcm "dmixer" channels 8 } ttable.0.6 1 ttable.1.7 1 } pcm.stereoall { type plug slave { pcm "dmixer" channels 8 } ttable.0.0 1 # input left and right to all 4 l+r outputs ttable.1.1 1 ttable.0.2 1 ttable.1.3 1 ttable.0.4 1 ttable.1.5 1 ttable.0.6 1 ttable.1.7 1 } pcm.monofrontl { type route slave { pcm "dmixer" channels 8 } ttable.0.0 1 # in-channel 0, out-channel 0, 100% volume ttable.1.0 1 # in-channel 1, out-channel 0, 100% volume } pcm.monofrontr { type route slave { pcm "dmixer" channels 8 } ttable.0.1 1 ttable.1.1 1 } pcm.monocenterl { type route slave { pcm "dmixer" channels 8 } ttable.0.2 1 ttable.1.2 1 } pcm.monocenterr { type route slave { pcm "dmixer" channels 8 } ttable.0.3 1 ttable.1.3 1 } pcm.monobackl { type route slave { pcm "dmixer" channels 8 } ttable.0.4 1 ttable.1.4 1 } pcm.monobackr { type route slave { pcm "dmixer" channels 8 } ttable.0.5 1 ttable.1.5 1 } pcm.monosurroundl { type route slave { pcm "dmixer" channels 8 } ttable.0.6 1 ttable.1.6 1 } pcm.monosurroundr { type route slave { pcm "dmixer" channels 8 } ttable.0.7 1 ttable.1.7 1 }

The asound.conf splits the 7.1 USB-Soundcard into 8 individual channels.

With aplay -D stereofront test.wav the first two channels playing test.wav outside the container on the host.

If the Parameter SQUEEZELITE_AUDIO_DEVICE is set to "stereofront" the container log shows [22:17:38.919198] test_open:281 playback open error: No such file or directory [22:17:38.919593] output_init_common:401 unable to open output device: stereofront

Outside of the container on the host, the "virtual" devices are working but inside the container the "virtual" devices can not be used.

I think this could be solved if a custom asound.conf could be used inside the container.

Or is there another chance get this working?

GioF71 commented 5 months ago

Hello, so it seems that you already have a working asound.conf. If so, maybe you can just mount that file to the container: under "- volumes", add a new line which should say:

- /etc/asound.conf:/etc/asound.conf:ro

Pay attention to the indentation in the compose file. Let me know if this helps.

dreitakter commented 5 months ago

Nice. Thank you 👍 This works :)

But this leads to another Problem: I have now setup 4 Docker. Every Docker uses the working asound.conf -> works

Every Docker can play musik to a different channel of the usb-soundcard -> works

BUT if I want to play sound at the same time to differnt channels of the same usb-soundcard, only the first channel can play music. All Containers are using the same device "/dev/snd" and this leads to the problem. The first container that want to play music is blocking the device. The other containers cant use the device anymore.

Is it possible to start multiple instances of squeezelite in one container?

GioF71 commented 5 months ago

Hello, good to hear that. Unfortunately it's a partial success :-(

About your question: no, and it's generally a bad idea to run more applications in the same container. Unless maybe if one is an helper to the other. Kind of defeats the purpose of containerization. Why not just keeping track of the individual command lines, installing the squeezelite binary on the host system, and create 4 systemd services? I can help you with that if it sounds right for you.

dreitakter commented 5 months ago

Ok, I tested this by myself and it could work. I have started 3 more squeezelite processes manually in the container with the same commandline except playername and outputdevice. All 4 Stereochannels can play music individual at the same time :)

BUT how should this be configured? How can I tell the container to open 4 instances of squeezelite with different parameters?

Would it be possible to parse the variables SQUEEZELITE_NAME and SQUEEZELITE_AUDIO_DEVICE like this: SQUEEZELITE_NAME = "Player1|Player2|Player3|Player4" SQUEEZELITE_AUDIO_DEVICE = "stereofront|stereoback|stereosurround|stereocenter"

And run the "Start-Script" multiple times with the variables above?

Found some infos to split a string to an array and do a loop: IFS='|' read -r -a SQUEEZELITE_NAME_ARRAY <<< "$SQUEEZELITE_NAME" IFS='|' read -r -a SQUEEZELITE_AUDIO_DEVICE_ARRAY <<< "$SQUEEZELITE_AUDIO_DEVICE" for index in "${!SQUEEZELITE_NAME_ARRAY[@]}" do echo "${SQUEEZELITE_NAME_ARRAY[index]}" echo "${SQUEEZELITE_AUDIO_DEVICE_ARRAY[index]}" ` START instance of sqeezelite with all parameters done`

dreitakter commented 5 months ago

Hello, good to hear that. Unfortunately it's a partial success :-(

About your question: no, and it's generally a bad idea to run more applications in the same container. Unless maybe if one is an helper to the other. Kind of defeats the purpose of containerization. Why not just keeping track of the individual command lines, installing the squeezelite binary on the host system, and create 4 systemd services? I can help you with that if it sounds right for you.

Thanks for your input. Yes you are right. This is a very special case which not fit into the containerization. The Host System is an unraid-server (NAS) and I dont want to run services on the host directly.

I think the better solution for me will be to setup a VM and passthrough the USB-Soundcard.

Thanks for your help :)

GioF71 commented 4 months ago

Hello, about this aspect:

Would it be possible to parse the variables SQUEEZELITE_NAME and SQUEEZELITE_AUDIO_DEVICE like this: SQUEEZELITE_NAME = "Player1|Player2|Player3|Player4" SQUEEZELITE_AUDIO_DEVICE = "stereofront|stereoback|stereosurround|stereocenter"

That should then be done for all the other variables as well. It's also quite impractical, the compose file could easily become hard to read. However, if you were determined to do this, you could just configure the first output, then, via a script, run the other docker exec commands, using bash -c "command &" maybe with some nohup if needed.

About your solution, would you run long speaker cables (meaning you have 4 amps close to your host) or long signal cables? The former is ok, the latter is not IMO. Long unbalanced cables behave like antennas and this would result in lots of interferences, and generally poor quality.

Considering that squeezelite and lms already support synchronized playback, can you install individual devices in each room? You can even repurpose any old single board computer, or maybe some old android tv box with coreelec or armbian. We also regular builds for the armv5 platform so this image should run almost everywhere.

Let me know if this helps.

GioF71 commented 4 months ago

Last thing about your card, wouldn't "stereoall" do for you? I understand it would send the same stereo signal to all the stereo outputs.

dreitakter commented 4 months ago

Last thing about your card, wouldn't "stereoall" do for you? I understand it would send the same stereo signal to all the stereo outputs.

Sadly no, because I need 4 individual channels for 4 individual rooms

dreitakter commented 4 months ago

Hello, about this aspect:

Would it be possible to parse the variables SQUEEZELITE_NAME and SQUEEZELITE_AUDIO_DEVICE like this: SQUEEZELITE_NAME = "Player1|Player2|Player3|Player4" SQUEEZELITE_AUDIO_DEVICE = "stereofront|stereoback|stereosurround|stereocenter"

That should then be done for all the other variables as well. It's also quite impractical, the compose file could easily become hard to read. However, if you were determined to do this, you could just configure the first output, then, via a script, run the other docker exec commands, using bash -c "command &" maybe with some nohup if needed.

About your solution, would you run long speaker cables (meaning you have 4 amps close to your host) or long signal cables? The former is ok, the latter is not IMO. Long unbalanced cables behave like antennas and this would result in lots of interferences, and generally poor quality.

Considering that squeezelite and lms already support synchronized playback, can you install individual devices in each room? You can even repurpose any old single board computer, or maybe some old android tv box with coreelec or armbian. We also regular builds for the armv5 platform so this image should run almost everywhere.

Let me know if this helps.

I think I will give it a try with a modified command line.

In my house are speaker-cables in every room which leads to the basement into one central place. The longest cable is 7m. The cables are already into the walls. Hopefully this will work as aspected.

I have 12 Rooms so I need 12 individual outputs. For this I have 3x 7.1-Usb-Sound-cards

GioF71 commented 4 months ago

In my house are speaker-cables in every room which leads to the basement into one central place. The longest cable is 7m. The cables are already into the walls. Hopefully this will work as aspected.

I have 12 Rooms so I need 12 individual outputs. For this I have 3x 7.1-Usb-Sound-cards

Ok, sorry if I mentioned the potential issue, of course you know it already :-) Yours must be a nice house, congrats!

GioF71 commented 4 months ago

Last thing about your card, wouldn't "stereoall" do for you? I understand it would send the same stereo signal to all the stereo outputs.

Sadly no, because I need 4 individual channels for 4 individual rooms

I wrongly assumed that you wanted to play the same music to multiple locations sorry