From c2f2b7e0d762961a19050bcbd636edad34f67c19 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Wed, 3 Jan 2024 17:01:28 +0100 Subject: [PATCH] Handle divisions by 0 in Lb302 and Monstro (#7021) * Handle divisions by 0 in Lb302 Handle potential division by 0 which in turn lead to floating point exceptions in Lb302. The division can occur in the `process` method if it is called with the member `vco_inc` still initialized to 0. This seems to happen then the Lb302 processes with no notes actually being played. The offending call is `BandLimitedWave::pdToLen(vco_inc)` which is now prevented when the increment is 0. In the latter case a sample of 0 is produced. This works because in all other cases the Lb302 instance should process a note which in turn sets the increments to something different from 0. * Fix FPEs in Monstro Fix some floating point exceptions in `MonstroSynth::renderOutput` that occurred due to calling `BandLimitedWave::pdToLen` with a value of 0. This happened when one of the phase deltas was set to 0, i.e. `pd_l` or `pd_r`. These cases are now checked and produce silence in the corresponding components if the phase delta is set to 0. * Fix uninitialized variables Initialize the local variables `len_l` and `len_r` to 0. This fixes compiler warnings a la "error: 'len_r' may be used uninitialized in this function" which are treated as errors on the build server. * Adjust whitespace of touched code --- plugins/Lb302/Lb302.cpp | 11 +++--- plugins/Monstro/Monstro.cpp | 72 ++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/plugins/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp index ee49442d5d4..44583cbc513 100644 --- a/plugins/Lb302/Lb302.cpp +++ b/plugins/Lb302/Lb302.cpp @@ -585,20 +585,23 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) vco_k = 0.5 * Oscillator::noiseSample( vco_c ); break; + // The next cases all use the BandLimitedWave class which uses the oscillator increment `vco_inc` to compute samples. + // If that oscillator increment is 0 we return a 0 sample because calling BandLimitedWave::pdToLen(0) leads to a + // division by 0 which in turn leads to floating point exceptions. case VcoShape::BLSawtooth: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLSaw ) * 0.5f; + vco_k = vco_inc == 0. ? 0. : BandLimitedWave::oscillate(vco_c + 0.5f, BandLimitedWave::pdToLen(vco_inc), BandLimitedWave::Waveform::BLSaw) * 0.5f; break; case VcoShape::BLSquare: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLSquare ) * 0.5f; + vco_k = vco_inc == 0. ? 0. : BandLimitedWave::oscillate(vco_c + 0.5f, BandLimitedWave::pdToLen(vco_inc), BandLimitedWave::Waveform::BLSquare) * 0.5f; break; case VcoShape::BLTriangle: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLTriangle ) * 0.5f; + vco_k = vco_inc == 0. ? 0. : BandLimitedWave::oscillate(vco_c + 0.5f, BandLimitedWave::pdToLen(vco_inc), BandLimitedWave::Waveform::BLTriangle) * 0.5f; break; case VcoShape::BLMoog: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLMoog ); + vco_k = vco_inc == 0. ? 0. : BandLimitedWave::oscillate(vco_c + 0.5f, BandLimitedWave::pdToLen(vco_inc), BandLimitedWave::Waveform::BLMoog); break; } diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index 2201e4ed90b..9563f756d3c 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -320,8 +320,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float rightph; float pd_l; float pd_r; - float len_l; - float len_r; + float len_l(0.); + float len_r(0.); // osc1 vars float o1l_f; @@ -503,12 +503,27 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( pd_r > 0.5 ) pd_r = 1.0 - pd_r; // multi-wave DC Oscillator - len_l = BandLimitedWave::pdToLen( pd_l ); - len_r = BandLimitedWave::pdToLen( pd_r ); - if( m_counter2l > 0 ) { len_l /= m_counter2l; m_counter2l--; } - if( m_counter2r > 0 ) { len_r /= m_counter2r; m_counter2r--; } - sample_t O2L = oscillate( o2w, leftph, len_l ); - sample_t O2R = oscillate( o2w, rightph, len_r ); + sample_t O2L = 0.; + if (pd_l != 0.) + { + len_l = BandLimitedWave::pdToLen(pd_l); + if (m_counter2l > 0) + { + len_l /= m_counter2l; m_counter2l--; + } + O2L = oscillate(o2w, leftph, len_l); + } + + sample_t O2R = 0.; + if (len_r != 0.) + { + len_r = BandLimitedWave::pdToLen(pd_r); + if (m_counter2r > 0) + { + len_r /= m_counter2r; m_counter2r--; + } + O2R = oscillate(o2w, rightph, len_r); + } // modulate volume O2L *= o2lv; @@ -568,17 +583,40 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( pd_r > 0.5 ) pd_r = 1.0 - pd_r; // multi-wave DC Oscillator - len_l = BandLimitedWave::pdToLen( pd_l ); - len_r = BandLimitedWave::pdToLen( pd_r ); - if( m_counter3l > 0 ) { len_l /= m_counter3l; m_counter3l--; } - if( m_counter3r > 0 ) { len_r /= m_counter3r; m_counter3r--; } - // sub-osc 1 - sample_t O3AL = oscillate( o3w1, leftph, len_l ); - sample_t O3AR = oscillate( o3w1, rightph, len_r ); + sample_t O3AL = 0.; + sample_t O3AR = 0.; // multi-wave DC Oscillator, sub-osc 2 - sample_t O3BL = oscillate( o3w2, leftph, len_l ); - sample_t O3BR = oscillate( o3w2, rightph, len_r ); + sample_t O3BL = 0.; + sample_t O3BR = 0.; + + if (pd_l != 0.) + { + len_l = BandLimitedWave::pdToLen(pd_l); + if (m_counter3l > 0) + { + len_l /= m_counter3l; m_counter3l--; + } + // sub-osc 1 + O3AL = oscillate(o3w1, leftph, len_l); + + // multi-wave DC Oscillator, sub-osc 2 + O3BL = oscillate(o3w2, leftph, len_l); + } + + if (pd_r != 0.) + { + len_r = BandLimitedWave::pdToLen(pd_r); + if (m_counter3r > 0) + { + len_r /= m_counter3r; m_counter3r--; + } + // sub-osc 1 + O3AR = oscillate(o3w1, rightph, len_r); + + // multi-wave DC Oscillator, sub-osc 2 + O3BR = oscillate(o3w2, rightph, len_r); + } // calc and modulate sub sub = o3sub;