mikebrady / shairport-sync

AirPlay and AirPlay 2 audio player
Other
7.15k stars 567 forks source link

[Problem]: ALSA mono output device? #1877

Open acmay opened 1 month ago

acmay commented 1 month ago

What happened?

I have single speakers in rooms and I want to do mono output from the left/right channels instead of stereo. But I can't seem to get it to work.

I did the split setup described here for ALSA https://bootlin.com/blog/audio-multi-channel-routing-and-mixing-using-alsalib/

Using alsa speaker test it works as expected, but when I use the mono output device in Shairport-sync, I get a warning print and it doesn't seem to work.

I have configure Shairport-sync in mono mode.

Is there a better way to do this?

Relevant log output

Jul 13 15:37:51 pie5 shairport-sync[1137038]: warning: audio_alsa: Channels count (2) not available for device "kcenter": Invalid argument

System Information.

Raspberry Pi 5

Configuration Information.

root@pie5:/etc# uname -a
Linux pie5 6.6.31+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.6.31-1+rpt1 (2024-05-29) aarch64 GNU/Linux
root@pie5:/etc# /usr/bin/shairport-sync -V
3.3.8-libdaemon-OpenSSL-Avahi-ALSA-jack-pa-dummy-stdout-pipe-soxr-convolution-metadata-mqtt-dbus-mpris-sysconfdir:/etc

PulseAudio or PipeWire installed?

How did you install Shairport Sync?

A package manager (apt, apt install, yum, pkg, etc.)

Check previous issues

acmay commented 1 month ago

I see this line with a hard code 2, and I am not sure if I can just change this and try it. https://github.com/mikebrady/shairport-sync/blob/4d20657bae0768e0ad121d4216b9c266732910e4/audio_alsa.c#L563

acmay commented 1 month ago

This change does seem to work and play ok, but I don't see how outpl change adjusts the write size. I haven't really done other audio API work so I have no idea how to really double check it or if there are some good test files.

diff --git a/audio_alsa.c b/audio_alsa.c
index 092781a6..e32f8c1f 100644
--- a/audio_alsa.c
+++ b/audio_alsa.c
@@ -560,7 +560,8 @@ static int actual_open_alsa_device(int do_auto_setup) {
     return ret;
   }

-  ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
+  //ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
+  ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 1);
   if (ret < 0) {
     die("audio_alsa: Channels count (2) not available for device \"%s\": %s", alsa_out_dev,
         snd_strerror(ret));
diff --git a/player.c b/player.c
index 46ef100f..46f7a541 100644
--- a/player.c
+++ b/player.c
@@ -100,6 +100,7 @@

 #include "activity_monitor.h"

+#define ONE_OUT 1
 // make the first audio packet deliberately early to bias the sync error of
 // the very first packet, making the error more likely to be too early
 // rather than too late. It it's too early,
@@ -2396,7 +2397,8 @@ void *player_thread_func(void *arg) {

               for (j = 0; j < conn->output_sample_ratio; j++) {
                 *outpl++ = ll;
-                *outpl++ = rl;
+                if (!ONE_OUT)
+                  *outpl++ = rl;
               }
             }
           } break;
@@ -2444,7 +2446,8 @@ void *player_thread_func(void *arg) {

               for (j = 0; j < conn->output_sample_ratio; j++) {
                 *outpl++ = ll;
-                *outpl++ = rl;
+                if (!ONE_OUT)
+                  *outpl++ = rl;
               }
             }
           } break;

mikebrady commented 1 month ago

Thanks for the post. Not quite sure what you're after, but if you want to get monophonic output from both channels of a stereo DAC, then the playback_mode setting in the general section of Shairport Sync configuration file can be used – just set it to "mono". This causes the left and right channels to be mixed equally and the result sent to both the left and right channels of the DAC.

acmay commented 1 month ago

I have a multroom in-ceiling speakers. 4 of the rooms are small so they only have one speaker. I am hoping to keep cost down by using the left channel for one room, and the right channel for another room. So both as mono-speakers. I would like them to be 4 separate airplay targets as cheaply as possible.

I did set the mono mode in the general section, but then I still needed the other changes to get it to work. Hopefully I can see about dynamically checking on the channel count of the audio device. I have no idea on the other audio server setups (jack/pulse) to see if they have another way to do this type of configuration.

I saw the other issues on doing more than one shairplay instance and I will see about that part next.

cbrunnkvist commented 1 month ago

@acmay Maybe you can try to better explain what it is you are after, the goal or simplified schematic of your ideal setup? From what I can tell, the RPi5 has one 3.5 mm stereo out. You say that you want to connect mono speakers, so you run shairport-sync in mono mode. So, what's missing?

cbrunnkvist commented 1 month ago

Additionally: I'm not sure if using an RPi5 for a such a low-power task as this represents the best way to keep costs down ;-)

acmay commented 1 month ago

The RPi5 is the first test device and I can use a cheaper one later.

With the current mono mode, I would always get the same thing playing in both rooms. I want different airplay streams to go each room so each person in the rooms can listen to something they want.

The other cost is in the amps to run the speakers.