swh / ladspa

The SWH Plugins package for the LADSPA plugin system
http://plugin.org.uk/
GNU General Public License v2.0
228 stars 52 forks source link

Reverse Delay - SIGFPE with 0 delay time #86

Open zonkmachine opened 4 months ago

zonkmachine commented 4 months ago

Got a crash in LMMS with the Reverse Delay (revdelay_1605.so) idelay_samples can be 0 and this is not good with modulus (%) operation.

https://github.com/swh/ladspa/blob/02bda232041380c2846414945798cbbfecb2f3f2/revdelay_1605.xml#L118

Thread 28 "lmms::AudioEngi" received signal SIGFPE, Arithmetic exception.
[Switching to Thread 0x7fffaf7fe640 (LWP 7507)]
0x00007fffe80f9ed6 in runRevdelay (instance=0x555558d15840, sample_count=<optimized out>) at /home/lmms/plugins/LadspaEffect/swh/ladspa/revdelay_1605.xml:118
118           if ((write_phase % idelay_samples) < xfade_samp) {
(gdb) bt full
#0  0x00007fffe80f9ed6 in runRevdelay (instance=0x555558d15840, sample_count=<optimized out>) at /home/lmms/plugins/LadspaEffect/swh/ladspa/revdelay_1605.xml:118
        idelay_samples = 0
        read = <optimized out>
        insamp = 0
        next_delay_samples = <optimized out>
        delay_samples_slope = -87.2048416
        plugin_data = 0x555558d15840
...

Downstream issue https://github.com/LMMS/lmms/issues/5936

zonkmachine commented 4 months ago

A quick fix. I haven't test it more than see that it doesn't crash. It looks like the same issue is there in the LV2 version.

diff --git a/revdelay_1605.xml b/revdelay_1605.xml
index 085e95c..03cce30 100644
--- a/revdelay_1605.xml
+++ b/revdelay_1605.xml
@@ -12,6 +12,7 @@
       #include <stdio.h>

       #define MIN(a,b) ((a) < (b) ? (a) : (b))
+      #define MAX(a,b) ((a) > (b) ? (a) : (b))
       #define CALC_DELAY(delaytime) \
         (f_clamp (delaytime * sample_rate, 1.f, (float)(buffer_size + 1)))

@@ -112,7 +113,7 @@
           write_phase = (write_phase + 1) % delay2;

           read_phase = delay2 - write_phase;
-          idelay_samples = (long)delay_samples;
+          idelay_samples = MAX(1,(long)delay_samples);
           read = wet * buffer[read_phase]   + (dry * insamp);

           if ((write_phase % idelay_samples) < xfade_samp) {
swh commented 4 months ago

Great, thanks, I've applied it to HEAD.

I'm not in a position to test it unfortunately, so I've not made a new release.