rncbc / synthv1

synthv1 - an old-school polyphonic synthesizer
https://synthv1.sourceforge.io
GNU General Public License v2.0
40 stars 10 forks source link

synthv1_wave::sample() overflow when working with DAW #15

Closed AnClark closed 3 years ago

AnClark commented 3 years ago

Here I have a new bug when working with REAPER on Windows. Seems that synthv1_wave::sample() generated an overflown value, then passed to synthv1_wave::interp().

Backtrace from GDB:

--Type <RET> for more, q to quit, c to continue without paging--

Thread 28 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 10788.0x2284]
synthv1_wave::interp (this=0xad3b2e0, i=4294967295, itab=8, alpha=-4.2949673e+09) at ../src/synthv1_wave.h:144
144                     const float x0 = frames[i];
(gdb) bt
#0  synthv1_wave::interp (this=0xad3b2e0, i=4294967295, itab=8, alpha=-4.2949673e+09) at ../src/synthv1_wave.h:144
#1  0x00007ffd7092f03c in synthv1_wave::sample (this=0xad3b2e0, phase=..., freq=-0.623733521)
    at ../src/synthv1_wave.h:135
#2  0x00007ffd704cd060 in synthv1_oscillator::sample (this=0xadfd2d8, freq=-0.623733521) at ../src/synthv1_wave.h:295
#3  0x00007ffd70206525 in synthv1_impl::process (this=0xad3b2e0, ins=0xa58ea60, outs=0xa58ea50, nframes=384)
    at ../src/synthv1.cpp:2464
#4  0x00007ffd707b0a1a in synthv1::process (this=0x31e7280, ins=0xa58ea60, outs=0xa58ea50, nframes=384)
    at ../src/synthv1.cpp:2833
#5  0x00007ffd701567b7 in synthv1_lv2::run (this=0x31e7280, nframes=384) at ../src/synthv1_lv2.cpp:362
#6  0x00007ffd700299ed in synthv1_lv2_run (instance=0x31e7280, nframes=384) at ../src/synthv1_lv2.cpp:828
#7  0x000000014005afde in ?? ()
#8  0x00000001403a2943 in ?? ()
#9  0x00000001403cca72 in ?? ()
#10 0x000000014076a101 in ?? ()
#11 0x000000014077211f in ?? ()
#12 0x0000000140761a9d in ?? ()
#13 0x00000001408c5d28 in ?? ()
#14 0x00000001408e5397 in ?? ()
#15 0x00000001408e546f in ?? ()
#16 0x00007ffdc96b7034 in KERNEL32!BaseThreadInitThunk () from C:\WINDOWS\System32\kernel32.dll
#17 0x00007ffdca702651 in ntdll!RtlUserThreadStart () from C:\WINDOWS\SYSTEM32\ntdll.dll
#18 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
rncbc commented 3 years ago

yeah, having i=4294967295 sounds like it having a negative value, which shouldn't ever happen :(...

does it occur all the time or just with some special DCO settings?

AnClark commented 3 years ago

Occurs all the time. Here are my two instances' settings:

image image

AnClark commented 3 years ago

A temporary workaround:

diff --git a/src/synthv1_wave.h b/src/synthv1_wave.h
index 9657f86..c93d030 100644
--- a/src/synthv1_wave.h
+++ b/src/synthv1_wave.h
@@ -120,6 +120,9 @@ public:
        const uint32_t i = uint32_t(index);
        const float alpha = index - float(i);

+       if(i >= __UINT32_MAX__)
+           return 0;
+
        phase.phase += freq / m_srate;
        if (phase.phase >= 1.0f) {
            phase.phase -= 1.0f;
rncbc commented 3 years ago

can you set a conditional breakpoint on that very condition (i >= __UINT32_MAX__) and then print the state of some variable eg. index, alpha, phase.phase, freq, m_nsize and m_srate ?

there's something very wrong and weird going on there, probably induced by the windows compiler, stdlib or the processor architecture, that at least never happens on GNU/Linux x86 (g++)...

AnClark commented 3 years ago

My GDB will freeze when setting conditional breakpoints. So I use MessageBoxA() instead.

image image image image image

rncbc commented 3 years ago

how come m_srate (sample-rate) is zero??

there you have the culprit ! could it be that reaper/windows is instantiating (via synthv1_lv2_instantiate()) with a foul sample rate value, which seems to be zero?

please try to set a BP on synthv1_lv2_instantiate() and verify for yourself what sample_rate value is being passed to the synthv1_lv2 constructor, somewhere here https://github.com/rncbc/synthv1/blob/10fdb2b6d12db8a62e5208e6ce9b004b1b574da6/src/synthv1_lv2.cpp#L807

AnClark commented 3 years ago

image

Sample rate seems OK. It's my fault that I'd forgotten to use %f for printing m_srate.

Here's the real output: image

rncbc commented 3 years ago

ok. thanks, then please we must investigate why oh why is 'freq' negative...

can you trace the values of pv->dco1_freq1, m_ctl1.pitchbend, modwheel1, lfo1 and possibly pv->dco1_glide1.tick(), just before this line in synthv1_impl::process() is executed: https://github.com/rncbc/synthv1/blob/10fdb2b6d12db8a62e5208e6ce9b004b1b574da6/src/synthv1.cpp#L2464-L2466

AnClark commented 3 years ago

image image image image image

rncbc commented 3 years ago

what happens when you set DCO Glide to Off ?

AnClark commented 3 years ago

what happens when you set DCO Glide to Off ?

It seems that there's no explicit problem when playing sounds (aka. Glide effect can be switched off well). I've two instances (with 4 synthesizers). Only one synthesizer has Glide turned off.

rncbc commented 3 years ago

what happens when you set DCO Glide to Off ?

It seems that there's no explicit problem when playing sounds (aka. Glide effect can be switched off well). I've two instances (with 4 synthesizers). Only one synthesizer has Glide turned off.

i mean WITHOUT you workaround (https://github.com/AnClark/synthv1/commit/176dbd548b0a7779c76c7b210cf8fc4ff706d02e)!...

on another update, can you please merge/update from develop branch (https://github.com/rncbc/synthv1/commit/0ae7c0d), and check whether it behaves then?

note that the issue seems to occur only on very first note is playing after instantiation and Glide is on (> 0).

AnClark commented 3 years ago

i mean WITHOUT you workaround (AnClark@176dbd5)!...

Don't worry. All of the bugs above occurs without that workaround. I'll merge your upstream, bypass my workaround, and retry.


UPDATE: Seems that your improvement below has solved this issue. Great! (I've also bypassed my workaround.)

index 6eec17e..b9a4126 100644
--- a/src/synthv1.cpp
+++ b/src/synthv1.cpp
@@ -596,7 +596,7 @@ struct synthv1_glide
        {
                m_frames = frames;

-               if (m_frames > 0) {
+               if (m_frames > 0 && m_last > 0.0f) {
                        m_freq = m_last - freq;
                        m_step = m_freq / float(m_frames);
                } else {