Skip to content

Commit

Permalink
Handle divisions by 0 in Lb302 and Monstro (#7021)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
michaelgregorius committed Jan 3, 2024
1 parent 8eba258 commit c2f2b7e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 21 deletions.
11 changes: 7 additions & 4 deletions plugins/Lb302/Lb302.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
72 changes: 55 additions & 17 deletions plugins/Monstro/Monstro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit c2f2b7e

Please sign in to comment.