diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 7ca7477d4..d9c80a3c3 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -89,22 +89,20 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_lfo1_phase = 0.0f; m_lfo2_phase = 0.0f; + + m_lfo1_s = Oscillator::noiseSample( 0.0f ); + m_lfo2_s = Oscillator::noiseSample( 0.0f ); m_osc1l_last = 0.0f; m_osc1r_last = 0.0f; - - m_osc2l_last = 0.0f; - m_osc2r_last = 0.0f; - - m_osc3l_last = 0.0f; - m_osc3r_last = 0.0f; - + m_l_last = 0.0f; m_r_last = 0.0f; -// constants for amp delta capping - m_adcap1 = ADCAP1 / m_samplerate; - m_adcap2 = ADCAP2 / m_samplerate; + m_invert2l = false; + m_invert2r = false; + m_invert3l = false; + m_invert3r = false; } @@ -256,9 +254,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const bool o1ssr = m_parent->m_osc1SSR.value(); const bool o1ssf = m_parent->m_osc1SSF.value(); - const bool o2sync = m_parent->m_osc2Sync.value(); - const bool o3sync = m_parent->m_osc3Sync.value(); - + const bool o2sync = m_parent->m_osc2SyncH.value(); + const bool o3sync = m_parent->m_osc3SyncH.value(); + const bool o2syncr = m_parent->m_osc2SyncR.value(); + const bool o3syncr = m_parent->m_osc3SyncR.value(); /////////////////////////// // // @@ -274,20 +273,20 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o1l_p; float o1r_p; float o1_pw; - + // osc2 vars float o2l_f; float o2r_f; float o2l_p; float o2r_p; - + // osc3 vars float o3l_f; float o3r_f; float o3l_p; float o3r_p; float sub; - + // phase delta calculation vars float pd_l; float pd_r; @@ -330,7 +329,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // bounds check for phase if( o1l_p < 0 ) o1l_p -= floorf( o1l_p ); if( o1r_p < 0 ) o1r_p -= floorf( o1r_p ); - + // pulse wave osc sample_t O1L = ( fraction( o1l_p ) < o1_pw ) ? 1.0f : -1.0f; sample_t O1R = ( fraction( o1r_p ) < o1_pw ) ? 1.0f : -1.0f; @@ -339,40 +338,64 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // sync on rise if( o1ssr ) { + // hard sync if( o2sync ) { if( O1L > m_osc1l_last ) m_osc2l_phase = 0.0f; if( O1R > m_osc1r_last ) m_osc2r_phase = 0.0f; - } + } if( o3sync ) { if( O1L > m_osc1l_last ) m_osc3l_phase = 0.0f; if( O1R > m_osc1r_last ) m_osc3r_phase = 0.0f; } + // reverse sync + if( o2syncr ) + { + if( O1L > m_osc1l_last ) m_invert2l = !m_invert2l; + if( O1R > m_osc1r_last ) m_invert2r = !m_invert2r; + } + if( o3syncr ) + { + if( O1L > m_osc1l_last ) m_invert3l = !m_invert3l; + if( O1R > m_osc1r_last ) m_invert3r = !m_invert3r; + } } // sync on fall if( o1ssf ) { + // hard sync if( o2sync ) { if( O1L < m_osc1l_last ) m_osc2l_phase = 0.0f; if( O1R < m_osc1r_last ) m_osc2r_phase = 0.0f; - } + } if( o3sync ) { if( O1L < m_osc1l_last ) m_osc3l_phase = 0.0f; if( O1R < m_osc1r_last ) m_osc3r_phase = 0.0f; } + // reverse sync + if( o2syncr ) + { + if( O1L < m_osc1l_last ) m_invert2l = !m_invert2l; + if( O1R < m_osc1r_last ) m_invert2r = !m_invert2r; + } + if( o3syncr ) + { + if( O1L < m_osc1l_last ) m_invert3l = !m_invert3l; + if( O1R < m_osc1r_last ) m_invert3r = !m_invert3r; + } } // update last before signal is touched - // also do a very simplistic amp delta cap - it's a pulse wave signal so we won't care about it too much... + // also do a very simple amp delta cap const sample_t tmpl = m_osc1l_last; const sample_t tmpr = m_osc1r_last; m_osc1l_last = O1L; m_osc1r_last = O1R; - + if( tmpl != O1L ) O1L = 0.0f; if( tmpr != O1R ) O1R = 0.0f; @@ -413,29 +436,27 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( pd_l > 0.5 ) pd_l = 1.0 - pd_l; pd_r = qAbs( o2r_p - m_ph2r_last ); if( pd_r > 0.5 ) pd_r = 1.0 - pd_r; - + // multi-wave DC Oscillator sample_t O2L = oscillate( o2w, o2l_p, BandLimitedWave::pdToLen( pd_l ) ); sample_t O2R = oscillate( o2w, o2r_p, BandLimitedWave::pdToLen( pd_r ) ); - // do amplitude delta cap - O2L = qBound( m_osc2l_last - m_adcap1, O2L, m_osc2l_last + m_adcap1 ); - O2R = qBound( m_osc2r_last - m_adcap1, O2R, m_osc2r_last + m_adcap1 ); - m_osc2l_last = O2L; - m_osc2r_last = O2R; - // modulate volume O2L *= o2lv; O2R *= o2rv; modulatevol( O2L, o2v ) modulatevol( O2R, o2v ) + // reverse sync - invert waveforms when needed + if( m_invert2l ) O2L *= -1.0; + if( m_invert2r ) O2R *= -1.0; + // update osc2 phases m_ph2l_last = m_osc2l_phase; m_ph2r_last = m_osc2r_phase; m_osc2l_phase = fraction( m_osc2l_phase + 1.0f / ( static_cast( m_samplerate ) / o2l_f ) ); m_osc2r_phase = fraction( m_osc2r_phase + 1.0f / ( static_cast( m_samplerate ) / o2r_f ) ); - + ///////////////////////////// // // @@ -451,8 +472,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // o2 modulation? if( omod == MOD_FM ) { - o3l_f = qBound( MIN_FREQ, o3l_f * powf( 2.0f, O2L * 2 ), MAX_FREQ ); - o3r_f = qBound( MIN_FREQ, o3r_f * powf( 2.0f, O2R * 2 ), MAX_FREQ ); + o3l_f = qBound( MIN_FREQ, o3l_f * powf( 2.0f, O2L ), MAX_FREQ ); + o3r_f = qBound( MIN_FREQ, o3r_f * powf( 2.0f, O2R ), MAX_FREQ ); } // calc and modulate phase @@ -476,7 +497,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( pd_l > 0.5 ) pd_l = 1.0 - pd_l; pd_r = qAbs( o3r_p - m_ph3r_last ); if( pd_r > 0.5 ) pd_r = 1.0 - pd_r; - + // multi-wave DC Oscillator, sub-osc 1 sample_t O3AL = oscillate( o3w1, o3l_p, BandLimitedWave::pdToLen( pd_l ) ); sample_t O3AR = oscillate( o3w1, o3r_p, BandLimitedWave::pdToLen( pd_r ) ); @@ -492,12 +513,6 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) sample_t O3L = linearInterpolate( O3AL, O3BL, sub ); sample_t O3R = linearInterpolate( O3AR, O3BR, sub ); - // do amp delta capping, before volume is touched - O3L = qBound( m_osc3l_last - m_adcap1, O3L, m_osc3l_last + m_adcap1 ); - O3R = qBound( m_osc3r_last - m_adcap1, O3R, m_osc3r_last + m_adcap1 ); - m_osc3l_last = O3L; - m_osc3r_last = O3R; - // modulate volume O3L *= o3lv; O3R *= o3rv; @@ -510,22 +525,23 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) O3R = qBound( -MODCLIP, O3R * qMax( 0.0f, 1.0f + O2R ), MODCLIP ); } + // reverse sync - invert waveforms when needed + if( m_invert3l ) O3L *= -1.0; + if( m_invert3r ) O3R *= -1.0; + // update osc3 phases m_ph3l_last = m_osc3l_phase; - m_ph3r_last = m_osc3r_phase; + m_ph3r_last = m_osc3r_phase; m_osc3l_phase = fraction( m_osc3l_phase + 1.0f / ( static_cast( m_samplerate ) / o3l_f ) ); m_osc3r_phase = fraction( m_osc3r_phase + 1.0f / ( static_cast( m_samplerate ) / o3r_f ) ); - // amp delta caps + // integrator - very simple filter sample_t L = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); sample_t R = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); - L = qBound( m_l_last - m_adcap2, L, m_l_last + m_adcap2 ); - R = qBound( m_r_last - m_adcap2, R, m_r_last + m_adcap2 ); + _buf[f][0] = linearInterpolate( L, m_l_last, INTEGRATOR ); + _buf[f][1] = linearInterpolate( R, m_r_last, INTEGRATOR ); - _buf[f][0] = L; - _buf[f][1] = R; - m_l_last = L; m_r_last = R; } @@ -550,9 +566,6 @@ void MonstroSynth::renderModulators( fpp_t _frames ) const f_cnt_t tfp = m_nph->totalFramesPlayed(); // LFOs - sample_t lfo1_s; - sample_t lfo2_s; - // LFO 1 switch( m_parent->m_lfo1Wave.value() ) @@ -562,9 +575,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::sinSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::sinSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -573,9 +586,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::triangleSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::triangleSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -584,9 +597,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::sawSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::sawSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -595,9 +608,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::sawSample( ph ) * -1.0f; - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::sawSample( ph ) * -1.0f; + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -606,9 +619,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::squareSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::squareSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -617,9 +630,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = oscillate( WAVE_SQRSOFT, ph, lfo1_r ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = oscillate( WAVE_SQRSOFT, ph, lfo1_r ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -628,9 +641,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::moogSawSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::moogSawSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -639,9 +652,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = oscillate( WAVE_SINABS, ph, lfo1_r ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = oscillate( WAVE_SINABS, ph, lfo1_r ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; @@ -650,23 +663,38 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo1_phase + lfo1_po; - lfo1_s = Oscillator::expSample( ph ); - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; + m_lfo1_s = Oscillator::expSample( ph ); + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; m_lfo1_phase += 1.0f / lfo1_r; } break; - case WAVE_NOISE: - default: + case WAVE_RANDOM: for( f_cnt_t f = 0; f < _frames; f++ ) { const f_cnt_t t = f + tfp; if( t % static_cast( lfo1_r ) == 0 ) m_lfo1_last = Oscillator::noiseSample( 0.0f ); - lfo1_s = m_lfo1_last; - if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); - m_lfo1_buf[f] = lfo1_s; - m_lfo1_phase += 1.0f / lfo1_r; + m_lfo1_s = m_lfo1_last; + if( t < m_parent->m_lfo1_att ) m_lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = m_lfo1_s; } + m_lfo1_phase += static_cast( _frames ) / lfo1_r; + break; + case WAVE_RANDOM_SMOOTH: + default: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + tfp; + const f_cnt_t tm = t % static_cast( lfo1_r ); + const float p = static_cast( tm ) / lfo1_r; + if( tm == 0 ) + { + m_lfo1_last = m_lfo1_s; + m_lfo1_s = Oscillator::noiseSample( 0.0f ); + } + m_lfo1_buf[f] = cosinusInterpolate( m_lfo1_last, m_lfo1_s, p ); + } + m_lfo1_phase += static_cast( _frames ) / lfo1_r; break; } @@ -679,9 +707,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::sinSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::sinSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -690,9 +718,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::triangleSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::triangleSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -701,9 +729,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::sawSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::sawSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -712,9 +740,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::sawSample( ph ) * -1.0f; - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::sawSample( ph ) * -1.0f; + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -723,9 +751,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::squareSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::squareSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -734,9 +762,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = oscillate( WAVE_SQRSOFT, ph, lfo2_r ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = oscillate( WAVE_SQRSOFT, ph, lfo2_r ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -745,9 +773,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::moogSawSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::moogSawSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -756,9 +784,9 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = oscillate( WAVE_SINABS, ph, lfo2_r ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = oscillate( WAVE_SINABS, ph, lfo2_r ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; @@ -767,23 +795,38 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { const f_cnt_t t = f + tfp; const float ph = m_lfo2_phase + lfo2_po; - lfo2_s = Oscillator::expSample( ph ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; + m_lfo2_s = Oscillator::expSample( ph ); + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; m_lfo2_phase += 1.0f / lfo2_r; } break; - case WAVE_NOISE: - default: + case WAVE_RANDOM: for( f_cnt_t f = 0; f < _frames; f++ ) { const f_cnt_t t = f + tfp; if( t % static_cast( lfo2_r ) == 0 ) m_lfo2_last = Oscillator::noiseSample( 0.0f ); - lfo2_s = m_lfo2_last; - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); - m_lfo2_buf[f] = lfo2_s; - m_lfo2_phase += 1.0f / lfo2_r; + m_lfo2_s = m_lfo2_last; + if( t < m_parent->m_lfo2_att ) m_lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = m_lfo2_s; } + m_lfo2_phase += static_cast( _frames ) / lfo2_r; + break; + case WAVE_RANDOM_SMOOTH: + default: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + tfp; + const f_cnt_t tm = t % static_cast( lfo2_r ); + const float p = static_cast( tm ) / lfo2_r; + if( tm == 0 ) + { + m_lfo2_last = m_lfo2_s; + m_lfo2_s = Oscillator::noiseSample( 0.0f ); + } + m_lfo2_buf[f] = cosinusInterpolate( m_lfo2_last, m_lfo2_s, p ); + } + m_lfo2_phase += static_cast( _frames ) / lfo2_r; break; } @@ -929,7 +972,8 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc2Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune right" ) ), m_osc2Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 2 Stereo phase offset" ) ), m_osc2Wave( this, tr( "Osc 2 Waveform" ) ), - m_osc2Sync( false, this, tr( "Osc 2 Sync" ) ), + m_osc2SyncH( false, this, tr( "Osc 2 Sync Hard" ) ), + m_osc2SyncR( false, this, tr( "Osc 2 Sync Reverse" ) ), m_osc3Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 3 Volume" ) ), m_osc3Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Panning" ) ), @@ -938,7 +982,8 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc3Sub( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Sub-oscillator mix" ) ), m_osc3Wave1( this, tr( "Osc 3 Waveform 1" ) ), m_osc3Wave2( this, tr( "Osc 3 Waveform 2" ) ), - m_osc3Sync( false, this, tr( "Osc 3 Sync" ) ), + m_osc3SyncH( false, this, tr( "Osc 3 Sync Hard" ) ), + m_osc3SyncR( false, this, tr( "Osc 3 Sync Reverse" ) ), m_lfo1Wave( this, tr( "LFO 1 Waveform" ) ), m_lfo1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 1 Attack" ) ), @@ -1027,9 +1072,9 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : { // make sure the wavetables exist: -// generate bandlimited wavetables +// generate bandlimited wavetables BandLimitedWave::generateWaves(); - + // setup waveboxes setwavemodel( m_osc2Wave ) setwavemodel( m_osc3Wave1 ) @@ -1150,7 +1195,8 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_osc2Ftr.saveSettings( _doc, _this, "o2ftr" ); m_osc2Spo.saveSettings( _doc, _this, "o2spo" ); m_osc2Wave.saveSettings( _doc, _this, "o2wav" ); - m_osc2Sync.saveSettings( _doc, _this, "o2syn" ); + m_osc2SyncH.saveSettings( _doc, _this, "o2syn" ); + m_osc2SyncR.saveSettings( _doc, _this, "o2synr" ); m_osc3Vol.saveSettings( _doc, _this, "o3vol" ); m_osc3Pan.saveSettings( _doc, _this, "o3pan" ); @@ -1159,7 +1205,8 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_osc3Sub.saveSettings( _doc, _this, "o3sub" ); m_osc3Wave1.saveSettings( _doc, _this, "o3wav1" ); m_osc3Wave2.saveSettings( _doc, _this, "o3wav2" ); - m_osc3Sync.saveSettings( _doc, _this, "o3syn" ); + m_osc3SyncH.saveSettings( _doc, _this, "o3syn" ); + m_osc3SyncR.saveSettings( _doc, _this, "o3synr" ); m_lfo1Wave.saveSettings( _doc, _this, "l1wav" ); m_lfo1Att.saveSettings( _doc, _this, "l1att" ); @@ -1265,7 +1312,8 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_osc2Ftr.loadSettings( _this, "o2ftr" ); m_osc2Spo.loadSettings( _this, "o2spo" ); m_osc2Wave.loadSettings( _this, "o2wav" ); - m_osc2Sync.loadSettings( _this, "o2syn" ); + m_osc2SyncH.loadSettings( _this, "o2syn" ); + m_osc2SyncR.loadSettings( _this, "o2synr" ); m_osc3Vol.loadSettings( _this, "o3vol" ); m_osc3Pan.loadSettings( _this, "o3pan" ); @@ -1274,7 +1322,8 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_osc3Sub.loadSettings( _this, "o3sub" ); m_osc3Wave1.loadSettings( _this, "o3wav1" ); m_osc3Wave2.loadSettings( _this, "o3wav2" ); - m_osc3Sync.loadSettings( _this, "o3syn" ); + m_osc3SyncH.loadSettings( _this, "o3syn" ); + m_osc3SyncR.loadSettings( _this, "o3synr" ); m_lfo1Wave.loadSettings( _this, "l1wav" ); m_lfo1Att.loadSettings( _this, "l1att" ); @@ -1550,7 +1599,8 @@ void MonstroView::modelChanged() m_osc2FtrKnob-> setModel( &m-> m_osc2Ftr ); m_osc2SpoKnob-> setModel( &m-> m_osc2Spo ); m_osc2WaveBox-> setModel( &m-> m_osc2Wave ); - m_osc2SyncButton-> setModel( &m-> m_osc2Sync ); + m_osc2SyncHButton-> setModel( &m-> m_osc2SyncH ); + m_osc2SyncRButton-> setModel( &m-> m_osc2SyncR ); m_osc3VolKnob-> setModel( &m-> m_osc3Vol ); m_osc3PanKnob-> setModel( &m-> m_osc3Pan ); @@ -1559,7 +1609,8 @@ void MonstroView::modelChanged() m_osc3SubKnob-> setModel( &m-> m_osc3Sub ); m_osc3Wave1Box-> setModel( &m-> m_osc3Wave1 ); m_osc3Wave2Box-> setModel( &m-> m_osc3Wave2 ); - m_osc3SyncButton-> setModel( &m-> m_osc3Sync ); + m_osc3SyncHButton-> setModel( &m-> m_osc3SyncH ); + m_osc3SyncRButton-> setModel( &m-> m_osc3SyncR ); m_lfo1WaveBox-> setModel( &m-> m_lfo1Wave ); m_lfo1AttKnob-> setModel( &m-> m_lfo1Att ); @@ -1691,7 +1742,8 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, 22 ); m_osc2WaveBox->setFont( pointSize<8>( m_osc2WaveBox->font() ) ); - maketinyled( m_osc2SyncButton, 204, O2ROW - 3, "Sync oscillator 2" ) + maketinyled( m_osc2SyncHButton, 212, O2ROW - 3, "Hard sync oscillator 2" ) + maketinyled( m_osc2SyncRButton, 191, O2ROW - 3, "Reverse sync oscillator 2" ) makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, "Volume", "%", "osc3Knob" ) makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, "Panning", "", "osc3Knob" ) @@ -1707,8 +1759,9 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, 22 ); m_osc3Wave2Box->setFont( pointSize<8>( m_osc3Wave2Box->font() ) ); - maketinyled( m_osc3SyncButton, 204, O3ROW - 3, "Sync oscillator 3" ) - + maketinyled( m_osc3SyncHButton, 212, O3ROW - 3, "Hard sync oscillator 3" ) + maketinyled( m_osc3SyncRButton, 191, O3ROW - 3, "Reverse sync oscillator 3" ) + m_lfo1WaveBox = new comboBox( view ); m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 ); m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 4e8a3ea96..59bf5dea7 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -93,7 +93,8 @@ name .addItem( tr( "Soft square wave" ), static_cast( new PluginPixmapLoader( "sqrsoft" ) ) ); \ name .addItem( tr( "Abs. sine wave" ), static_cast( new PluginPixmapLoader( "sinabs" ) ) ); \ name .addItem( tr( "Exponential wave" ), static_cast( new PluginPixmapLoader( "exp" ) ) ); \ - name .addItem( tr( "Random" ), static_cast( new PluginPixmapLoader( "rand" ) ) ); + name .addItem( tr( "Random" ), static_cast( new PluginPixmapLoader( "rand" ) ) ); \ + name .addItem( tr( "Random smooth" ), static_cast( new PluginPixmapLoader( "rand" ) ) ); // UI constants const int O1ROW = 22; @@ -158,6 +159,11 @@ const int WAVE_MOOG_D = 14; const int NUM_WAVES = 15; +// lfo-specific enumerators +const int WAVE_RANDOM = 9; +const int WAVE_RANDOM_SMOOTH = 10; +const int NUM_LFO_WAVES = 11; + // modulation enumerators const int MOD_MIX = 0; const int MOD_AM = 1; @@ -170,10 +176,7 @@ const float MODCLIP = 2.0; const float MIN_FREQ = 18.0f; const float MAX_FREQ = 48000.0f; -// constants for amp delta capping - these will be divided by samplerate by the synth -const float ADCAP1 = 44100 / 2; -const float ADCAP2 = 44100 / 2.25; - +const float INTEGRATOR = 3.0f / 7.0f; class MonstroInstrument; class MonstroView; @@ -302,16 +305,13 @@ private: sample_t m_lfo1_last; sample_t m_lfo2_last; + + sample_t m_lfo1_s; + sample_t m_lfo2_s; sample_t m_osc1l_last; sample_t m_osc1r_last; - sample_t m_osc2l_last; - sample_t m_osc2r_last; - - sample_t m_osc3l_last; - sample_t m_osc3r_last; - sample_t m_l_last; sample_t m_r_last; @@ -321,8 +321,10 @@ private: float m_ph3l_last; float m_ph3r_last; - float m_adcap1; - float m_adcap2; + bool m_invert2l; + bool m_invert3l; + bool m_invert2r; + bool m_invert3r; }; class MonstroInstrument : public Instrument @@ -434,7 +436,8 @@ private: FloatModel m_osc2Ftr; FloatModel m_osc2Spo; ComboBoxModel m_osc2Wave; - BoolModel m_osc2Sync; + BoolModel m_osc2SyncH; + BoolModel m_osc2SyncR; FloatModel m_osc3Vol; FloatModel m_osc3Pan; @@ -443,7 +446,8 @@ private: FloatModel m_osc3Sub; ComboBoxModel m_osc3Wave1; ComboBoxModel m_osc3Wave2; - BoolModel m_osc3Sync; + BoolModel m_osc3SyncH; + BoolModel m_osc3SyncR; ComboBoxModel m_lfo1Wave; TempoSyncKnobModel m_lfo1Att; @@ -582,7 +586,8 @@ private: knob * m_osc2FtrKnob; knob * m_osc2SpoKnob; comboBox * m_osc2WaveBox; - pixmapButton * m_osc2SyncButton; + pixmapButton * m_osc2SyncHButton; + pixmapButton * m_osc2SyncRButton; knob * m_osc3VolKnob; knob * m_osc3PanKnob; @@ -591,7 +596,8 @@ private: knob * m_osc3SubKnob; comboBox * m_osc3Wave1Box; comboBox * m_osc3Wave2Box; - pixmapButton * m_osc3SyncButton; + pixmapButton * m_osc3SyncHButton; + pixmapButton * m_osc3SyncRButton; comboBox * m_lfo1WaveBox; TempoSyncKnob * m_lfo1AttKnob; diff --git a/plugins/monstro/artwork_op.png b/plugins/monstro/artwork_op.png index 2f7b69ca0..b68bba649 100644 Binary files a/plugins/monstro/artwork_op.png and b/plugins/monstro/artwork_op.png differ