From c266e7b88e034bfe54c093fdfa95babf0439610b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 27 Jul 2014 19:34:41 +0300 Subject: [PATCH] Monstro: optimize Rewrote handling of modulators so that we don't have to allocate extra buffers for every note - should improve performance and make cpu usage more consistent --- plugins/monstro/Monstro.cpp | 577 ++++++++++-------------------------- plugins/monstro/Monstro.h | 32 +- 2 files changed, 177 insertions(+), 432 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 21fe87cfc..dc1b9b8f9 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -67,11 +67,6 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_samplerate( _samplerate ), m_fpp( _frames ) { - m_env1_buf = new sample_t[_frames]; - m_env2_buf = new sample_t[_frames]; - m_lfo1_buf = new sample_t[_frames]; - m_lfo2_buf = new sample_t[_frames]; - m_osc1l_phase = 0.0f; m_osc1r_phase = 0.0f; m_osc2l_phase = 0.0f; @@ -84,15 +79,14 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_ph3l_last = 0.0f; m_ph3r_last = 0.0f; - m_env1_phase = 0.0f; - m_env2_phase = 0.0f; - - 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_env_phase[0] = 0.0f; + m_env_phase[1] = 0.0f; + m_lfo_phase[0] = 0.0f; + m_lfo_phase[1] = 0.0f; + m_lfo_next[0] = Oscillator::noiseSample( 0.0f ); + m_lfo_next[1] = Oscillator::noiseSample( 0.0f ); + m_osc1l_last = 0.0f; m_osc1r_last = 0.0f; @@ -118,11 +112,6 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, MonstroSynth::~MonstroSynth() { - delete[] m_env1_buf; - delete[] m_env2_buf; - delete[] m_lfo1_buf; - delete[] m_lfo2_buf; - } @@ -132,39 +121,78 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // macros for modulating with env/lfos #define modulatefreq( car, mod ) \ modtmp = 0.0f; \ - if( mod##_e1 != 0.0f ) modtmp += m_env1_buf[f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) modtmp += m_env2_buf[f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) modtmp += m_lfo1_buf[f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) modtmp += m_lfo2_buf[f] * mod##_l2; \ + if( mod##_e1 != 0.0f ) modtmp += m_env[0] * mod##_e1; \ + if( mod##_e2 != 0.0f ) modtmp += m_env[1] * mod##_e2; \ + if( mod##_l1 != 0.0f ) modtmp += m_lfo[0] * mod##_l1; \ + if( mod##_l2 != 0.0f ) modtmp += m_lfo[1] * mod##_l2; \ car = qBound( MIN_FREQ, car * powf( 2.0f, modtmp ), MAX_FREQ ); #define modulateabs( car, mod ) \ - if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) car += m_env2_buf[f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) car += m_lfo1_buf[f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; + if( mod##_e1 != 0.0f ) car += m_env[0] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env[1] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo[0] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo[1] * mod##_l2; #define modulatephs( car, mod ) \ - if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) car += m_env2_buf[f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) car += m_lfo1_buf[f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; + if( mod##_e1 != 0.0f ) car += m_env[0] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env[1] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo[0] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo[1] * mod##_l2; #define modulatevol( car, mod ) \ - if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ); \ - if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * m_env1_buf[f] ); \ - if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ); \ - if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * m_env2_buf[f] ); \ - if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * m_lfo1_buf[f] ); \ - if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * m_lfo2_buf[f] ); \ + if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * m_env[0] ); \ + if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * m_env[0] ); \ + if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * m_env[1] ); \ + if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * m_env[1] ); \ + if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * m_lfo[0] ); \ + if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * m_lfo[1] ); \ car = qBound( -MODCLIP, car, MODCLIP ); - // pre-render env's and lfo's - renderModulators( _frames ); + + + //////////////////// + // // + // MODULATORS // + // // + //////////////////// + + // LFO phase offsets + const float lfo1_po = m_parent->m_lfo1Phs.value() / 360.0f; + const float lfo2_po = m_parent->m_lfo2Phs.value() / 360.0f; + + // remove cruft from phase counters to prevent overflow, add phase offset + m_lfo_phase[0] = absFraction( m_lfo_phase[0] + lfo1_po ); + m_lfo_phase[1] = absFraction( m_lfo_phase[1] + lfo2_po ); + + // LFO rates and increment + m_lfo_rate[0] = ( m_parent->m_lfo1Rate.value() * 0.001f * m_samplerate ); + m_lfo_rate[1] = ( m_parent->m_lfo2Rate.value() * 0.001f * m_samplerate ); + m_lfo_inc[0] = 1.0f / m_lfo_rate[0]; + m_lfo_inc[1] = 1.0f / m_lfo_rate[1]; + + m_env_sus[0] = m_parent-> m_env1Sus.value(); + m_env_sus[1] = m_parent-> m_env2Sus.value(); + + m_lfovalue[0] = m_parent->m_lfo1Wave.value(); + m_lfovalue[1] = m_parent->m_lfo2Wave.value(); + m_lfoatt[0] = m_parent->m_lfo1_att; + m_lfoatt[1] = m_parent->m_lfo2_att; + + m_env_pre[0] = m_parent->m_env1_pre; + m_env_att[0] = m_parent->m_env1_att; + m_env_hold[0] = m_parent->m_env1_hold; + m_env_dec[0] = m_parent->m_env1_dec; + m_env_rel[0] = m_parent->m_env1_rel; + m_env_pre[1] = m_parent->m_env2_pre; + m_env_att[1] = m_parent->m_env2_att; + m_env_hold[1] = m_parent->m_env2_hold; + m_env_dec[1] = m_parent->m_env2_dec; + m_env_rel[1] = m_parent->m_env2_rel; + // get updated osc1 values // get pulse width - const float pw = ( m_parent->m_osc1Pw.value() / 100.0f ); + const float pw = ( m_parent->m_osc1Pw.value() * 0.01f ); const float o1pw_e1 = ( m_parent->m_pw1env1.value() ); const float o1pw_e2 = ( m_parent->m_pw1env2.value() ); const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() * 0.5f ); @@ -322,7 +350,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // begin for loop for( f_cnt_t f = 0; f < _frames; f++ ) { - + // update modulators + updateModulators( f ); /* // debug code if( f % 10 == 0 ) { @@ -618,408 +647,122 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) m_osc3l_phase = absFraction( o3l_p - o3lpo ); m_osc3r_phase = absFraction( o3r_p - o3rpo ); + m_lfo_phase[0] = absFraction( m_lfo_phase[0] - lfo1_po ); + m_lfo_phase[1] = absFraction( m_lfo_phase[1] - lfo2_po ); } -void MonstroSynth::renderModulators( fpp_t _frames ) +inline void MonstroSynth::updateModulators( int frame ) { - // LFO phase offsets - const float lfo1_po = m_parent->m_lfo1Phs.value() / 360.0f; - const float lfo2_po = m_parent->m_lfo2Phs.value() / 360.0f; - - // remove cruft from phase counters to prevent overflow - m_lfo1_phase = fraction( m_lfo1_phase ); - m_lfo2_phase = fraction( m_lfo2_phase ); - - // LFO rates - const float lfo1_r = m_parent->m_lfo1Rate.value() / 1000.0f * m_samplerate; - const float lfo2_r = m_parent->m_lfo2Rate.value() / 1000.0f * m_samplerate; - // frames played before - const f_cnt_t tfp = m_nph->totalFramesPlayed(); - - // LFOs - // LFO 1 - - switch( m_parent->m_lfo1Wave.value() ) + const f_cnt_t tfp = m_nph->totalFramesPlayed() + frame; + + for( int i = 0; i < 2; ++i ) { - case WAVE_SINE: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_TRI: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_SAW: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_RAMP: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_SQR: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_SQRSOFT: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_MOOG: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_SINABS: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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; - case WAVE_EXP: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo1_phase + lfo1_po; - 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_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 ); - 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 ); - if( t < m_parent->m_lfo1_att ) m_lfo1_buf[f] *= ( static_cast( t ) / m_parent->m_lfo1_att ); - } - m_lfo1_phase += static_cast( _frames ) / lfo1_r; - break; - } - - // LFO 2 - - switch( m_parent->m_lfo2Wave.value() ) - { - case WAVE_SINE: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_TRI: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_SAW: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_RAMP: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_SQR: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_SQRSOFT: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_MOOG: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_SINABS: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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; - case WAVE_EXP: - for( f_cnt_t f = 0; f < _frames; f++ ) - { - const f_cnt_t t = f + tfp; - const float ph = m_lfo2_phase + lfo2_po; - 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_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 ); - 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 ); - if( t < m_parent->m_lfo2_att ) m_lfo2_buf[f] *= ( static_cast( t ) / m_parent->m_lfo2_att ); - } - m_lfo2_phase += static_cast( _frames ) / lfo2_r; - break; - } - - ///////////////////////////////////////////// - // - // - // envelopes - // - // - ///////////////////////////////////////////// - - const float env1_sus = m_parent-> m_env1Sus.value(); - const float env2_sus = m_parent-> m_env2Sus.value(); - - for( f_cnt_t f = 0; f < _frames; f++ ) - { - // envelope 1 - - // adjust phase for release - if( m_env1_phase < 4.0f && m_nph->isReleased() && f >= m_nph->framesBeforeRelease() ) + switch( m_lfovalue[i] ) { - if( m_env1_phase < 1.0f ) m_env1_phase = 5.0f; - else if( m_env1_phase < 2.0f ) m_env1_phase = 5.0f - fraction( m_env1_phase ); - else if( m_env1_phase < 3.0f ) m_env1_phase = 4.0f; - else m_env1_phase = 4.0f + fraction( m_env1_phase ); + case WAVE_SINE: + m_lfo[i] = Oscillator::sinSample( m_lfo_phase[i] ); + break; + case WAVE_TRI: + m_lfo[i] = Oscillator::triangleSample( m_lfo_phase[i] ); + break; + case WAVE_SAW: + m_lfo[i] = Oscillator::sawSample( m_lfo_phase[i] ); + break; + case WAVE_RAMP: + m_lfo[i] = Oscillator::sawSample( m_lfo_phase[i] ) * -1.0f; + break; + case WAVE_SQR: + m_lfo[i] = Oscillator::squareSample( m_lfo_phase[i] ); + break; + case WAVE_SQRSOFT: + m_lfo[i] = oscillate( WAVE_SQRSOFT, m_lfo_phase[i], 0 ); + break; + case WAVE_MOOG: + m_lfo[i] = Oscillator::moogSawSample( m_lfo_phase[i] ); + break; + case WAVE_SINABS: + m_lfo[i] = oscillate( WAVE_SINABS, m_lfo_phase[i], 0 ); + break; + case WAVE_EXP: + m_lfo[i] = Oscillator::expSample( m_lfo_phase[i] ); + break; + case WAVE_RANDOM: + if( tfp % static_cast( m_lfo_rate[i] ) == 0 ) m_lfo_last[i] = Oscillator::noiseSample( 0.0f ); + m_lfo[i] = m_lfo_last[i]; + break; + case WAVE_RANDOM_SMOOTH: + const f_cnt_t tm = tfp % static_cast( m_lfo_rate[i] ); + if( tm == 0 ) + { + m_lfo_last[i] = m_lfo_next[i]; + m_lfo_next[i] = Oscillator::noiseSample( 0.0f ); + } + m_lfo[i] = cosinusInterpolate( m_lfo_last[i], m_lfo_next[i], static_cast( tm ) / m_lfo_rate[i] ); + break; + } + + // attack + if( tfp < m_lfoatt[i] ) m_lfo[i] *= ( static_cast( tfp ) / m_lfoatt[i] ); + + // increment phase + m_lfo_phase[i] += m_lfo_inc[i]; + + + ///////////////////////////////////////////// + // // + // // + // envelopes // + // // + // // + ///////////////////////////////////////////// + + if( m_env_phase[i] < 4.0f && m_nph->isReleased() && frame >= m_nph->framesBeforeRelease() ) + { + if( m_env_phase[i] < 1.0f ) m_env_phase[i] = 5.0f; + else if( m_env_phase[i] < 2.0f ) m_env_phase[i] = 5.0f - fraction( m_env_phase[i] ); + else if( m_env_phase[i] < 3.0f ) m_env_phase[i] = 4.0f; + else m_env_phase[i] = 4.0f + fraction( m_env_phase[i] ); } // process envelope - if( m_env1_phase < 1.0f ) // pre-delay phase + if( m_env_phase[i] < 1.0f ) // pre-delay phase { - m_env1_buf[f] = 0.0f; - m_env1_phase = qMin( 1.0f, m_env1_phase + m_parent->m_env1_pre ); + m_env[i] = 0.0f; + m_env_phase[i] = qMin( 1.0f, m_env_phase[i] + m_env_pre[i] ); } - else if( m_env1_phase < 2.0f ) // attack phase + else if( m_env_phase[i] < 2.0f ) // attack phase { - m_env1_buf[f] = calcSlope1( fraction( m_env1_phase ) ); - m_env1_phase = qMin( 2.0f, m_env1_phase + m_parent->m_env1_att ); + m_env[i] = calcSlope1( fraction( m_env_phase[i] ) ); + m_env_phase[i] = qMin( 2.0f, m_env_phase[i] + m_env_att[i] ); } - else if( m_env1_phase < 3.0f ) // hold phase + else if( m_env_phase[i] < 3.0f ) // hold phase { - m_env1_buf[f] = 1.0f; - m_env1_phase = qMin( 3.0f, m_env1_phase + m_parent->m_env1_hold ); + m_env[i] = 1.0f; + m_env_phase[i] = qMin( 3.0f, m_env_phase[i] + m_env_hold[i] ); } - else if( m_env1_phase < 4.0f ) // decay phase + else if( m_env_phase[i] < 4.0f ) // decay phase { - const sample_t s = calcSlope1( 1.0f - fraction( m_env1_phase ) ); - if( s <= env1_sus ) + const sample_t s = calcSlope1( 1.0f - fraction( m_env_phase[i] ) ); + if( s <= m_env_sus[i] ) { - m_env1_buf[f] = env1_sus; + m_env[i] = m_env_sus[i]; } else { - m_env1_buf[f] = s; - m_env1_phase = qMin( 4.0f - env1_sus, m_env1_phase + m_parent->m_env1_dec ); - if( m_env1_phase == 4.0f ) m_env1_phase = 5.0f; // jump over release if sustain is zero - fix for clicking + m_env[i] = s; + m_env_phase[i] = qMin( 4.0f - m_env_sus[i], m_env_phase[i] + m_env_dec[i] ); + if( m_env_phase[i] == 4.0f ) m_env_phase[i] = 5.0f; // jump over release if sustain is zero - fix for clicking } } - else if( m_env1_phase < 5.0f ) // release phase + else if( m_env_phase[i] < 5.0f ) // release phase { - m_env1_buf[f] = calcSlope1( 1.0f - fraction( m_env1_phase ) ); - m_env1_phase += m_parent->m_env1_rel; + m_env[i] = calcSlope1( 1.0f - fraction( m_env_phase[i] ) ); + m_env_phase[i] += m_env_rel[i]; } - else m_env1_buf[f] = 0.0f; - -// qDebug( "env1 %f", m_env1_buf[f] ); - - // envelope 2 - - - - // adjust phase for release - if( m_env2_phase < 4.0f && m_nph->isReleased() && f >= m_nph->framesBeforeRelease() ) - { - if( m_env2_phase < 1.0f ) m_env2_phase = 5.0f; - else if( m_env2_phase < 2.0f ) m_env2_phase = 5.0f - fraction( m_env2_phase ); - else if( m_env2_phase < 3.0f ) m_env2_phase = 4.0f; - else m_env2_phase = 4.0f + fraction( m_env2_phase ); - } - - // process envelope - if( m_env2_phase < 1.0f ) // pre-delay phase - { - m_env2_buf[f] = 0.0f; - m_env2_phase = qMin( 1.0f, m_env2_phase + m_parent->m_env2_pre ); - } - else if( m_env2_phase < 2.0f ) // attack phase - { - m_env2_buf[f] = calcSlope2( fraction( m_env2_phase ) ); - m_env2_phase = qMin( 2.0f, m_env2_phase + m_parent->m_env2_att ); - } - else if( m_env2_phase < 3.0f ) // hold phase - { - m_env2_buf[f] = 1.0f; - m_env2_phase = qMin( 3.0f, m_env2_phase + m_parent->m_env2_hold ); - } - else if( m_env2_phase < 4.0f ) // decay phase - { - const sample_t s = calcSlope2( 1.0f - fraction( m_env2_phase ) ); - if( s <= env2_sus ) - { - m_env2_buf[f] = env2_sus; - } - else - { - m_env2_buf[f] = s; - m_env2_phase = qMin( 4.0f - env2_sus, m_env2_phase + m_parent->m_env2_dec ); - if( m_env2_phase == 4.0f ) m_env2_phase = 5.0f; // jump over release if sustain is zero - fix for clicking - } - } - else if( m_env2_phase < 5.0f ) // release phase - { - m_env2_buf[f] = calcSlope2( 1.0f - fraction( m_env2_phase) ); - m_env2_phase += m_parent->m_env2_rel; - } - else m_env2_buf[f] = 0.0f; - + else m_env[i] = 0.0f; } - } @@ -2071,7 +1814,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_lfo2RateKnob -> setWhatsThis( tr( "Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. " ) ); m_lfo1PhsKnob -> setWhatsThis( tr( "PHS controls the phase offset of the LFO. " ) ); m_lfo2PhsKnob -> setWhatsThis( tr( "PHS controls the phase offset of the LFO. " ) ); - + m_env1PreKnob -> setWhatsThis( tr( "PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. " ) ); m_env2PreKnob -> setWhatsThis( tr( "PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. " ) ); m_env1AttKnob -> setWhatsThis( tr( "ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. " diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 4b2066c88..b0e2c1bcd 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -208,12 +208,10 @@ private: const sample_rate_t m_samplerate; fpp_t m_fpp; - sample_t * m_env1_buf; - sample_t * m_env2_buf; - sample_t * m_lfo1_buf; - sample_t * m_lfo2_buf; + sample_t m_env [2]; + sample_t m_lfo [2]; - void renderModulators( fpp_t _frames ); + inline void updateModulators( int frame ); // linear interpolation /* inline sample_t interpolate( sample_t s1, sample_t s2, float x ) @@ -307,17 +305,21 @@ private: float m_osc3l_phase; float m_osc3r_phase; - sample_t m_env1_phase; - sample_t m_env2_phase; - - float m_lfo1_phase; - float m_lfo2_phase; + sample_t m_env_phase [2]; + float m_lfo_phase [2]; + sample_t m_lfo_last [2]; + sample_t m_lfo_next [2]; + float m_lfo_inc [2]; + float m_lfo_rate [2]; + float m_env_sus [2]; - sample_t m_lfo1_last; - sample_t m_lfo2_last; - - sample_t m_lfo1_s; - sample_t m_lfo2_s; + int m_lfovalue[2]; + int m_lfoatt[2]; + float m_env_pre[2]; + float m_env_att[2]; + float m_env_hold[2]; + float m_env_dec[2]; + float m_env_rel[2]; sample_t m_osc1l_last; sample_t m_osc1r_last;