ideoforms / signalflow

A sound synthesis framework for Python, designed for clear and concise expression of complex musical ideas
https://signalflow.dev
MIT License
167 stars 14 forks source link

Linux Sound Card Issue on Ubuntu 23.10 #105

Open filip-franek opened 7 months ago

filip-franek commented 7 months ago

These are my system and audio sound specs:

$ inxi -Fx
System:
  Host: thinkpad-yoga-x1-gen8 Kernel: 6.5.0-10-generic arch: x86_64 bits: 64
    compiler: N/A Desktop: Unity Distro: Ubuntu 23.10 (Mantic Minotaur)
...
Audio:
  Device-1: Intel Raptor Lake-P/U/H cAVS vendor: Lenovo
    driver: sof-audio-pci-intel-tgl bus-ID: 00:1f.3
  API: ALSA v: k6.5.0-10-generic status: kernel-api
  Server-1: PipeWire v: 0.3.79 status: active

$ cat /proc/asound/cards
 0 [sofhdadsp      ]: sof-hda-dsp - sof-hda-dsp
                      LENOVO-21HQ001SUS-ThinkPadX1YogaGen8

$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
pipewire
    PipeWire Sound Server
default
    Default ALSA Output (currently PipeWire Media Server)
hw:CARD=sofhdadsp,DEV=0
    sof-hda-dsp, 
    Direct hardware device without any conversions
hw:CARD=sofhdadsp,DEV=3
    sof-hda-dsp, 
    Direct hardware device without any conversions
hw:CARD=sofhdadsp,DEV=4
    sof-hda-dsp, 
    Direct hardware device without any conversions
hw:CARD=sofhdadsp,DEV=5
    sof-hda-dsp, 
    Direct hardware device without any conversions
hw:CARD=sofhdadsp,DEV=31
    sof-hda-dsp, 
    Direct hardware device without any conversions
plughw:CARD=sofhdadsp,DEV=0
    sof-hda-dsp, 
    Hardware device with all software conversions
plughw:CARD=sofhdadsp,DEV=3
    sof-hda-dsp, 
    Hardware device with all software conversions
plughw:CARD=sofhdadsp,DEV=4
    sof-hda-dsp, 
    Hardware device with all software conversions
plughw:CARD=sofhdadsp,DEV=5
    sof-hda-dsp, 
    Hardware device with all software conversions
plughw:CARD=sofhdadsp,DEV=31
    sof-hda-dsp, 
    Hardware device with all software conversions
sysdefault:CARD=sofhdadsp
    sof-hda-dsp, 
    Default Audio Device
dmix:CARD=sofhdadsp,DEV=0
    sof-hda-dsp, 
    Direct sample mixing device
dmix:CARD=sofhdadsp,DEV=3
    sof-hda-dsp, 
    Direct sample mixing device
dmix:CARD=sofhdadsp,DEV=4
    sof-hda-dsp, 
    Direct sample mixing device
dmix:CARD=sofhdadsp,DEV=5
    sof-hda-dsp, 
    Direct sample mixing device
dmix:CARD=sofhdadsp,DEV=31
    sof-hda-dsp, 
    Direct sample mixing device

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: sofhdadsp [sof-hda-dsp], device 0: HDA Analog (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: sofhdadsp [sof-hda-dsp], device 3: HDMI1 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: sofhdadsp [sof-hda-dsp], device 4: HDMI2 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: sofhdadsp [sof-hda-dsp], device 5: HDMI3 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: sofhdadsp [sof-hda-dsp], device 31: HDA Analog Deep Buffer (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

These are the steps I have taken.

# installed signalflow
pip3 install signalflow
# ran simple code
from signalflow import *
graph = AudioGraph()

and got this error

/home/filipfranek/repos/synthesis/signalflow-tutorial/script.py ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) (venv) filipfranek@thinkpad-yoga-x1-gen8 ~/repos/synthesis/signalflow-tutorial $ signalflow test ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) ALSA lib dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory) Traceback (most recent call last): File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 161, in <module> main() File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 148, in main run_test(args.frequency, args.gain, args.output_backend_name, args.output_device_name) File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 42, in run_test graph = AudioGraph(config=config) ^^^^^^^^^^^^^^^^^^^^^^^^^ signalflow.AudioIOException: libsoundio error: Output device does not support float32 samples

I though the issue was:

signalflow.AudioIOException: libsoundio error: Output device does not support float32 samples

but the error log also mentioned it could not find the libasound_module_pcm_pipewire.so library:

Cannot open shared library libasound_module_pcm_pipewire.so (/usr/lib/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or directory)

I have got that library though:

find /usr/lib -name libasound_module_pcm_pipewire.so -type f
/usr/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pipewire.so

so to temporarily fix it, I just created a symlink:

sudo ln -s /usr/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pipewire.so /usr/lib/alsa-lib/libasound_module_pcm_pipewire.so

Perhaps Alsa has to be restarted afterward sudo alsa force-reload.

That hopefully fixed the initial error and I run signalflow test and got:

Output device: Default ALSA Output (currently PipeWire Media Server) (0Hz, buffer size 8192 samples, 1 channel)
Traceback (most recent call last):
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 161, in <module>
    main()
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 148, in main
    run_test(args.frequency, args.gain, args.output_backend_name, args.output_device_name)
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 42, in run_test
    graph = AudioGraph(config=config)
            ^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: AudioGraph: Audio output device has zero sample rate

which suggests that the audio output device being used by the signalflow program is not properly configured or recognized by the system, specifically regarding its sample rate.

I tried to reconfigure signalflow configure to setup output_backend_name and output_device_name, but the device does not seem to be listed in signalflow list-output-device-names.

$ signalflow list-output-backend-names
Output device: Dummy Output Device (48000Hz, buffer size 48128 samples, 1 channel)
Available output backend names:
 - jack
 - alsa
 - dummy

$ signalflow list-output-device-names
Output device: Default ALSA Output (currently PipeWire Media Server) (0Hz, buffer size 8192 samples, 1 channel)
Traceback (most recent call last):
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 161, in <module>
    main()
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 150, in main
    run_list_output_device_names(args.output_backend_name)
  File "/home/filipfranek/repos/synthesis/signalflow-tutorial/venv/bin/signalflow", line 64, in run_list_output_device_names
    graph = AudioGraph(config=config, start=False)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: AudioGraph: Audio output device has zero sample rate

Any idea how to debug this?

ideoforms commented 7 months ago

I've just looked into this a little bit, and I think there are potentially a few overlapping issues.

Firstly and most critically, the libsoundio library that SignalFlow uses for cross-platform I/O sadly does not yet support Pipewire. In fact, libsoundio has been somewhat dormant over the past couple of years as its author has gone on to develop the Zig language. I'm hoping that there may be some community contributions in future, but I might look at switching to an alternative. cubeb looks promising.

Secondly, support for non-float32 is not yet implemented, which might currently rule out this particular device even outside of pipewire. I've added an issue for this. I don't think it should be a particularly complex piece of work (converting between float32 and int16 is just a case of a multiply and round), but I don't think I have a suitable device here to test on. At some point and when budget allows, I'd like to pick up a Linux laptop or NUC for testing.

I'm not sure why libasound required a symlink; could be something to do with the way in which 64-bit vs 32-bit libraries are installed by your package manager?

ideoforms commented 4 months ago

Hey @filip-franek, I have finally got hold of a Linux build machine that I can use for development, and have just pushed a fix for the float32 sample rate issue. If you have a moment to test whether it works at some point, I'd really appreciate it!

You will need to clone the latest commit from the repo and then build from source as described here. The only caveat is that it still won't work via pipewire because of the libsoundio constraint mentioned previously, so you would need to run it via a pure Alsa/Pulseaudio backend.

filip-franek commented 4 months ago

Thanks @ideoforms . It fixed the error I had before, but it introduced a new one ;).

Have not tried to debug it yet.

Python 3.11.6 (main, Oct  8 2023, 05:06:43) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from signalflow import *
>>> graph = AudioGraph()
Output device: Default ALSA Output (currently PipeWire Media Server) (0Hz, buffer size 8192 samples, 1 channel)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: AudioGraph: Audio output device has zero sample rate

Tried to run it in Docker as well, but it brings up other issues I have to look into.

Dockerfile that can output audio to my soundcard

# Dockerfile
FROM debian:bullseye

# Install necessary packages
RUN apt-get update && apt-get install -y \
    alsa-utils \
    python3 \
    python3-pip\
    pulseaudio \
    pulseaudio-utils

WORKDIR /app
COPY . /app
RUN pip3 install signalflow

RUN usermod -aG audio root
docker build -t signalflow .

docker run -it --rm     -e PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native     -v ${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native     -v ~/.config/pulse/cookie:/root/.config/pulse/cookie     --group-add $(getent group audio | cut -d: -f3) --name signalflow signalflow bin/bash

root@f65773f6849a:/app# python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from signalflow import *
>>> graph = AudioGraph()
Output device: Dummy Output Device (48000Hz, buffer size 48128 samples, 1 channel)
>>> 
Exception in AudioGraph: Node audioout-soundio cannot render because output buffer size is insufficient (48128 samples requested, buffer size = 2048). Increase the buffer size.
ideoforms commented 4 months ago

Thanks for re-testing! I suspect the first set of issues must boil down to libsoundio's lack of pipewire support, which would mean replacing SignalFlow's audio hardware abstraction layer. 🫤

For the second tests via Docker, this may be resolvable by simply increasing the audio buffer size by specifying output_buffer_size = 48128 in your ~/.signalflow/config (info on configuring signalflow). Can you let me know if that helps?