I’m setting up a four channel sound lab for young coders to practice Python on, and I must be close to success but the output channel mapping is resisting .
Our rig:
Raspberry Pi 4B / 4M
Manjaro ARM Linux Release: 23.02
pipewire using libpipewire 0.3.65 + ALSA module
pactl says libpulse 16.1.0
wireplumber
2 x USB audio adapters
Audio is checked out, each adapter functioning fine as a stereo device.
Our plan is:
Python + sounddevice (portaudio) module
→ pulse ‘default’ device based on module-combine-sink
→ 2 x USB audio adapters
[1] The loaded module does some weird mapping. Method:
pactl load-module module-combine-sink sink_name="fourplay" slaves=alsa_output.usb-Plugable_Plugable_USB_Audio_Device_000000000000-00.2.analog-stereo,
alsa_output.usb-Plugable_Plugable_USB_Audio_Device_000000000000-00.analog-stereo channel_map=left,right,rear-left,rear-right channels=4 remix=no
- generates a pipewire ID. Then we:
pactl set-default-sink fourplay
… successful
wpctl status
shows (a bit odd):
└─ Streams:
...
81. output.fourplay_alsa_output.usb-Plugable_Plugable_USB_Audio_Device_000000000000-00.analog-stereo
93. output_1 > Plugable USB Audio Device:playback_FL [paused]
94. output_2 > Plugable USB Audio Device:playback_FR [paused]
95. output_RL
96. output_RR
83. output.fourplay_alsa_output.usb-Plugable_Plugable_USB_Audio_Device_000000000000-00.2.analog-stereo
79. output_1 > Plugable USB Audio Device:playback_FL [paused]
97. output_2 > Plugable USB Audio Device:playback_FR [paused]
98. output_RL
99. output_RR
Settings
└─ Default Configured Node Names:
0. Audio/Sink fourplay
Then, with Python:
>>> import sounddevice as sd
>>> print(sd.query_devices())
0 bcm2835 Headphones: - (hw:1,0), ALSA (0 in, 8 out)
1 Plugable USB Audio Device: - (hw:3,0), ALSA (2 in, 2 out)
2 Plugable USB Audio Device: - (hw:4,0), ALSA (2 in, 2 out)
3 pipewire, ALSA (64 in, 64 out)
* 4 default, ALSA (64 in, 64 out)
>>> import soundfile as sf
>>> data,fs = sf.read("noise.wav")
>>> sd.play(data,mapping=[1]) # appears in FL and RL outputs (left channel on both cards, should only be FL)
>>> sd.play(data,mapping=[2]) # right ditto
>>> sd.play(data,mapping=[3]) # silence
>>> sd.play(data,mapping=[4]) # right ditto
The best guesses I have are:
- ‘remix=no’ is being ignored?
- my channel maps are rubbish?
The Pulse Wiki FAQ shows a technique of specifying the channel names when loading the original device modules, but …
pactl load-module module-alsa-sink device="hw:3,0" sink_name=output0 channel_map=front-left,front-right channels=2
Failure: No such entity
Gripe: there being six different ways to name/identify a device, none of which work universally.
Any advice?
inxi --audio
Audio:
Device-1: bcm2711-hdmi0 driver: vc4_hdmi
Device-2: bcm2711-hdmi1 driver: vc4_hdmi
Device-3: bcm2835-audio driver: bcm2835_audio
Device-4: JMTek LLC. Plugable USB Audio Device type: USB
driver: hid-generic,snd-usb-audio,usbhid
Device-5: JMTek LLC. Plugable USB Audio Device type: USB
driver: hid-generic,snd-usb-audio,usbhid
Sound API: ALSA v: k5.15.92-1-MANJARO-ARM-RPI running: yes
Sound Server-1: PipeWire v: 0.3.65 running: yes