alsa-project / alsa-lib

The Advanced Linux Sound Architecture (ALSA) - library
GNU Lesser General Public License v2.1
366 stars 177 forks source link

alsa-lib 1.2.5 breaks espeak #155

Closed MrBitBucket closed 3 years ago

MrBitBucket commented 3 years ago

In archlinux amd64 upgrading alsa-lib from 1.2.4 - 1.2.5 breaks the espeak application https://sourceforge.net/projects/espeak/.

I see extra errors in espeak output eg


Expression 'PaAlsaStreamComponent_GetAvailableFrames( self, &framesAvail, xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3989
Expression 'PaAlsaStreamComponent_RegisterChannels( &self->playback, &self->bufferProcessor, &playbackFrames, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4118
Expression 'PaAlsaStream_SetUpBuffers( stream, &framesGot, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4359```
zqqw commented 3 years ago

Building at this recent commit: https://github.com/alsa-project/alsa-lib/commit/81e7923fbfad45b2f353a4d6e3053af51f5f7d0b reverting this commit: https://github.com/alsa-project/alsa-lib/commit/5275d170e05639473e68e5feb349aec65bf26428 and partially reverting this commit (the last bit, the first part of it makes no difference): https://github.com/alsa-project/alsa-lib/commit/28cc099d9ea3962b033cb1cb9c3e07db828d9ff7 fixes espeak and it worked again. I don't know the details of why this happens, but hopefully isolating the exact cause will help to find a good solution. Although it initially worked with espeak like this, later when I tried to listen to audio in the browser having left an espeak process running in the terminal, there was no sound, and then espeak stopped working again after that, so this is not a fully working patch.

$ git diff
diff --git a/src/conf.c b/src/conf.c
index d863dec6..a936c28c 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1994,9 +1994,7 @@ int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
                SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
                goto _end;
        }
-       err = get_char(&input);
-       fd = input.current;
-       if (err != LOCAL_UNEXPECTED_EOF) {
+       if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
                SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
                err = -EINVAL;
                goto _end;
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 24c9941d..407af156 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -552,7 +552,8 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
        err = snd_pcm_status(plugin->gen.slave, status);
        if (err < 0)
                return err;
-       snd_pcm_plugin_sync_hw_ptr(pcm, status->hw_ptr, status->avail);
+       status->appl_ptr = *pcm->appl.ptr;
+       status->hw_ptr = *pcm->hw.ptr;
        /*
         * For capture stream, the situation is more complicated, because
         * snd_pcm_plugin_avail_update() commits the data to the slave pcm.
perexg commented 3 years ago

Code URL: https://github.com/PortAudio/portaudio/blob/master/src/hostapi/alsa/pa_linux_alsa.c#L3644

perexg commented 3 years ago

I cannot reproduce here with mpg123 -o portaudio a.mp3 (portaudio-19 library). Do you have any special version of the portaudio library ? It would be nice to see the error which alsa-lib returns also it may be useful to dump the PCM parameters via snd_pcm_dump().

zqqw commented 3 years ago
$ mpg123 -o portaudio a.mp3
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
        version 1.28.0; written and copyright by Michael Hipp and others
        free software (LGPL) without any warranty but with best wishes
[src/libout123/module.c:open_module_here():133] error: Failed to open module portaudio.
[src/libout123/libout123.c:out123_open():484] error: Found no driver out of [portaudio] working with device <default>.
main: [src/mpg123.c:check_fatal_output():331] error: out123 error 3: failure loading driver module

Bug occurs with standard Artix packages (Arch based, mostly identical except for systemd removal where required), OP has found the same on Arch.
$ pacman -Ss portaudio
world/portaudio 1:19.7.0-1
    A free, cross-platform, open source, audio I/O library.
lib32/lib32-portaudio 1:19.7.0-1
    A free, cross-platform, open source, audio I/O library (32 bit)
extra/portaudio 1:19.7.0-1
    A free, cross-platform, open source, audio I/O library.
community/python-pyaudio 0.2.11-6
    Python bindings for PortAudio
multilib/lib32-portaudio 1:19.7.0-1
    A free, cross-platform, open source, audio I/O library (32 bit)

Also the same using the portaudio-git AUR package:
portaudio-git-1:19.7.0.rRC2.23.gd859f7d-1

$ git diff
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 24c9941d..04491be8 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -552,6 +552,7 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
        err = snd_pcm_status(plugin->gen.slave, status);
        if (err < 0)
                return err;
+       snd_pcm_dump(pcm, NULL);
        snd_pcm_plugin_sync_hw_ptr(pcm, status->hw_ptr, status->avail);
        /*
         * For capture stream, the situation is more complicated, because

Result : segfault, not sure how to use this or where the output handle parameter should come from, if you could show some diff of what you mean I can try it.
perexg commented 3 years ago

Example dump code:

1) https://github.com/alsa-project/alsa-utils/blob/master/aplay/aplay.c#L539 2) https://github.com/alsa-project/alsa-utils/blob/master/aplay/aplay.c#L1467 3) https://github.com/alsa-project/alsa-utils/blob/master/aplay/aplay.c#L921

Please, modify and analyze the portaudio library not the alsa-lib code for the first stage. We need to know the exact error from the application POV.

zqqw commented 3 years ago

This is with portaudio (latest git version) built with --enable-debug-output configured, haven't had time to look at the dump bit yet. The first faulty commit apparently involves alsa-lib reading alsa.conf so perhaps portaudio has little influence on that?

$ espeak
hello
before paHostApiInitializers[0].
ALSA version (build): 1.2.5
ALSA version (runtime): 1.2.5
BuildDeviceList: Found device [0]: HDA Intel: 92HD71B7X Analog (hw:0,0)
BuildDeviceList: Ignoring ALSA plugin device [hw] of type [hw]
BuildDeviceList: Ignoring ALSA plugin device [plughw] of type [plug]
BuildDeviceList: Ignoring ALSA plugin device [plug] of type [plug]
BuildDeviceList: Ignoring ALSA plugin device [shm] of type [shm]
BuildDeviceList: Ignoring ALSA plugin device [tee] of type [file]
BuildDeviceList: Ignoring ALSA plugin device [file] of type [file]
BuildDeviceList: Ignoring ALSA plugin device [null] of type [null]
BuildDeviceList: Ignoring ALSA plugin device [cards] of type [unknown]
BuildDeviceList: Found plugin [default] of type [unknown]
BuildDeviceList: Found plugin [sysdefault] of type [unknown]
BuildDeviceList: Found plugin [front] of type [unknown]
BuildDeviceList: Found plugin [rear] of type [unknown]
BuildDeviceList: Found plugin [center_lfe] of type [unknown]
BuildDeviceList: Found plugin [side] of type [unknown]
BuildDeviceList: Found plugin [surround21] of type [unknown]
BuildDeviceList: Found plugin [surround40] of type [unknown]
BuildDeviceList: Found plugin [surround41] of type [unknown]
BuildDeviceList: Found plugin [surround50] of type [unknown]
BuildDeviceList: Found plugin [surround51] of type [unknown]
BuildDeviceList: Found plugin [surround71] of type [unknown]
BuildDeviceList: Found plugin [iec958] of type [unknown]
BuildDeviceList: Found plugin [spdif] of type [unknown]
BuildDeviceList: Found plugin [hdmi] of type [unknown]
BuildDeviceList: Found plugin [dmix] of type [unknown]
BuildDeviceList: Ignoring ALSA plugin device [dsnoop] of type [unknown]
BuildDeviceList: Found plugin [modem] of type [unknown]
BuildDeviceList: Found plugin [phoneline] of type [unknown]
BuildDeviceList: Filling device info for 19 devices
FillInDevInfo: Filling device info for: HDA Intel: 92HD71B7X Analog (hw:0,0)
GropeDevice: collecting info ..
GropeDevice: collecting info ..
Default input device: HDA Intel: 92HD71B7X Analog (hw:0,0)
Default output device: HDA Intel: 92HD71B7X Analog (hw:0,0)
FillInDevInfo: Adding device HDA Intel: 92HD71B7X Analog (hw:0,0): 0
FillInDevInfo: Filling device info for: sysdefault
GropeDevice: collecting info ..
GropeDevice: Limiting number of plugin channels to 128
GropeDevice: collecting info ..
GropeDevice: Limiting number of plugin channels to 128
FillInDevInfo: Adding device sysdefault: 1
FillInDevInfo: Filling device info for: front
GropeDevice: collecting info ..
FillInDevInfo: Adding device front: 2
FillInDevInfo: Filling device info for: rear
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
OpenPcm: Opened device 'rear' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: rear, all channels == 0
FillInDevInfo: Filling device info for: center_lfe
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
OpenPcm: Opened device 'center_lfe' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: center_lfe, all channels == 0
FillInDevInfo: Filling device info for: side
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
OpenPcm: Opened device 'side' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: side, all channels == 0
FillInDevInfo: Filling device info for: surround21
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
OpenPcm: Opened device 'surround21' ptr[(nil)] - result: [-22:Invalid argument]
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
OpenPcm: Opened device 'surround21' ptr[(nil)] - result: [-22:Invalid argument]
FillInDevInfo: Skipped device: surround21, all channels == 0
FillInDevInfo: Filling device info for: surround40
GropeDevice: collecting info ..
FillInDevInfo: Adding device surround40: 3
FillInDevInfo: Filling device info for: surround41
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
OpenPcm: Opened device 'surround41' ptr[(nil)] - result: [-22:Invalid argument]
FillInDevInfo: Skipped device: surround41, all channels == 0
FillInDevInfo: Filling device info for: surround50
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
OpenPcm: Opened device 'surround50' ptr[(nil)] - result: [-22:Invalid argument]
FillInDevInfo: Skipped device: surround50, all channels == 0
FillInDevInfo: Filling device info for: surround51
GropeDevice: collecting info ..
FillInDevInfo: Adding device surround51: 4
FillInDevInfo: Filling device info for: surround71
GropeDevice: collecting info ..
FillInDevInfo: Adding device surround71: 5
FillInDevInfo: Filling device info for: iec958
OpenPcm: Opened device 'iec958' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: iec958, all channels == 0
FillInDevInfo: Filling device info for: spdif
OpenPcm: Opened device 'spdif' ptr[(nil)] - result: [-2:No such file or directory]
OpenPcm: Opened device 'spdif' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: spdif, all channels == 0
FillInDevInfo: Filling device info for: hdmi
OpenPcm: Opened device 'hdmi' ptr[(nil)] - result: [-2:No such file or directory]
OpenPcm: Opened device 'hdmi' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: hdmi, all channels == 0
FillInDevInfo: Filling device info for: modem
OpenPcm: Opened device 'modem' ptr[(nil)] - result: [-2:No such file or directory]
OpenPcm: Opened device 'modem' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: modem, all channels == 0
FillInDevInfo: Filling device info for: phoneline
OpenPcm: Opened device 'phoneline' ptr[(nil)] - result: [-2:No such file or directory]
OpenPcm: Opened device 'phoneline' ptr[(nil)] - result: [-2:No such file or directory]
FillInDevInfo: Skipped device: phoneline, all channels == 0
FillInDevInfo: Filling device info for: default
GropeDevice: collecting info ..
GropeDevice: Limiting number of plugin channels to 128
GropeDevice: collecting info ..
GropeDevice: Limiting number of plugin channels to 128
Default input device: default
Default output device: default
FillInDevInfo: Adding device default: 6
FillInDevInfo: Filling device info for: dmix
GropeDevice: collecting info ..
FillInDevInfo: Adding device dmix: 7
BuildDeviceList: Building device list took 0.214580 seconds
after paHostApiInitializers[0].
before paHostApiInitializers[1].
PaOSS BuildDeviceList: Total number of devices found: 0
after paHostApiInitializers[1].
before paHostApiInitializers[2].
connect(2) call to /dev/shm/jack-1000/default/jack_0 failed (err=No such file or directory)
attempt to connect to server failed
PaJack_Initialize: Couldn't connect to JACK, status: 17
after paHostApiInitializers[2].
AlsaOpen: Opening device default
PaAlsaStreamComponent_Initialize: Host Chans P 1
AlsaOpen: Opening device default
PaAlsaStreamComponent_InitialConfigure: device MMAP SND_PCM_ACCESS_MMAP_INTERLEAVED: YES
PaAlsaStreamComponent_InitialConfigure: device MMAP SND_PCM_ACCESS_MMAP_NONINTERLEAVED: YES
PaAlsaStreamComponent_InitialConfigure: device can MMAP: YES
PaAlsaStreamComponent_DetermineFramesPerBuffer: user-buffer (frames)           = 0
PaAlsaStreamComponent_DetermineFramesPerBuffer: user-buffer (sec)              = 0.000000
PaAlsaStreamComponent_DetermineFramesPerBuffer: suggested latency (sec)        = 0.021333
PaAlsaStreamComponent_DetermineFramesPerBuffer: suggested host buffer (frames) = 470
PaAlsaStreamComponent_DetermineFramesPerBuffer: suggested host buffer (sec)    = 0.021315
PaAlsaStreamComponent_DetermineFramesPerBuffer: periods min = 3, max = 16, req = 4 
PaAlsaStreamComponent_DetermineFramesPerBuffer: suggested host buffer period   = 117 
PaAlsaStreamComponent_DetermineFramesPerBuffer: The determined period size (117) is less than minimum (470)
PaAlsaStreamComponent_DetermineFramesPerBuffer: device period minimum          = 470
PaAlsaStreamComponent_DetermineFramesPerBuffer: device period maximum          = 471
PaAlsaStreamComponent_DetermineFramesPerBuffer: host buffer period             = 470
PaAlsaStreamComponent_DetermineFramesPerBuffer: host buffer period latency     = 0.021315
PaAlsaStreamComponent_DetermineFramesPerBuffer: The configured period size is non-integer.
PaAlsaStream_Configure: Playback period size: 470, latency: 0.042676
OpenStream: Stream: framesPerBuffer = 0, maxFramesPerHostBuffer = 471, latency i=0.000000, o=0.042676
PaUnixThread_New: Waited for 0.000166225 seconds for stream to start
Expression 'framesAvail' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3644
Host error description: Resource deadlock avoided
Expression 'PaAlsaStreamComponent_GetAvailableFrames( self, &framesAvail, xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4004
Expression 'PaAlsaStreamComponent_RegisterChannels( &self->playback, &self->bufferProcessor, &playbackFrames, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4133
Expression 'PaAlsaStream_SetUpBuffers( stream, &framesGot, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4374
CallbackThreadFunc: Thread 1396446784 is canceled due to error -9999
 OnExit: Stopping ALSA handles
AlsaStop: Dropped frames
OnExit: Stoppage
CallbackThreadFunc: Thread 1396446784 exiting
 PaUnixThread_Terminate: Canceling thread 1396446784
PaUnixThread_Terminate: Joining thread 1396446784
Callback thread returned: -9999
perexg commented 3 years ago

What's ALSA error returned in Expression 'framesAvail' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3644 ? Also, dump the PCM status / info (ALSA side). Also, it may be nice to compare 1.2.4 vs 1.2.5 debug portaudio debug output.

zqqw commented 3 years ago

Not quite sure where "handle" should be taken from here, it segfaults like this:

$ git diff src/hostapi/alsa/pa_linux_alsa.c
diff --git a/src/hostapi/alsa/pa_linux_alsa.c b/src/hostapi/alsa/pa_linux_alsa.c
index cf01f47..ca2ec85 100644
--- a/src/hostapi/alsa/pa_linux_alsa.c
+++ b/src/hostapi/alsa/pa_linux_alsa.c
@@ -3631,8 +3631,14 @@ error:
 static PaError PaAlsaStreamComponent_GetAvailableFrames( PaAlsaStreamComponent *self, unsigned long *numFrames, int *xrunOccurred )
 {
     PaError result = paNoError;
+    static snd_output_t *log;
+    snd_ctl_t *handle;
+    int err;
     snd_pcm_sframes_t framesAvail = alsa_snd_pcm_avail_update( self->pcm );
     *xrunOccurred = 0;
+    err = snd_output_stdio_attach(&log, stderr, 0);
+    assert(err >= 0);
+

     if( -EPIPE == framesAvail )
     {
@@ -3641,6 +3647,8 @@ static PaError PaAlsaStreamComponent_GetAvailableFrames( PaAlsaStreamComponent *
     }
     else
     {
+        snd_pcm_dump(handle, log);
+        snd_output_close(log);
         ENSURE_( framesAvail, paUnanticipatedHostError );
     }

$ espeak
hello
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
connect(2) call to /dev/shm/jack-1000/default/jack_0 failed (err=No such file or directory)
attempt to connect to server failed
Segmentation fault
perexg commented 3 years ago

Try something like this:

@@ -3641,6 +3647,8 @@ static PaError PaAlsaStreamComponent_GetAvailableFrames( PaAlsaStreamComponent *
     }
     else
     {
+        snd_output_t *log;
+        fprintf(stderr, "******* framesAvail = %li\n", (long)framesAvail);
+        snd_output_stdio_attach(&log, stderr, 0);
+        snd_pcm_dump(self->pcm, log);
+        snd_output_close(log);
         ENSURE_( framesAvail, paUnanticipatedHostError );
     }
zqqw commented 3 years ago

files1.tar.gz Thank you, that worked. I attach the dump output with the latest alsa-lib git and the working 1.2.4 alsa lib release build, also the output of the latest portaudio git built with internal debugging enabled when using the working 1.2.4 alsa lib to compare with the output posted earlier.

perexg commented 3 years ago

Thanks. I see the problem now.

perexg commented 3 years ago

Could you test the above patch?

zqqw commented 3 years ago

All good - espeak speaks again!

$ espeak
hello        
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:877:(find_matching_chmap) Found no matching channel map
connect(2) call to /dev/shm/jack-1000/default/jack_0 failed (err=No such file or directory)
attempt to connect to server failed
hi
how are you
It works again, thanks!
perexg commented 3 years ago

Thank you for your cooperation. It's appreciated.