- optimized envelope and LFO computations

- separated sample variables updates from paint events


git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@375 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Javier Serrano Polo
2006-08-27 21:43:20 +00:00
parent 3eb581b76c
commit 0648712e39

View File

@@ -489,6 +489,8 @@ envelopeAndLFOWidget::envelopeAndLFOWidget( float _value_for_zero_amount,
connect( eng()->getMixer(), SIGNAL( sampleRateChanged() ), this,
SLOT( updateSampleVars() ) );
m_lfoShapeData =
new sample_t[eng()->getMixer()->framesPerAudioBuffer()];
updateSampleVars();
}
@@ -511,6 +513,21 @@ envelopeAndLFOWidget::~envelopeAndLFOWidget()
void envelopeAndLFOWidget::updateLFOShapeData( void )
{
const fpab_t frames = eng()->getMixer()->framesPerAudioBuffer();
m_userWave.lock();
for( fpab_t offset = 0; offset < frames; ++offset )
{
m_lfoShapeData[offset] = lfoShapeSample( offset );
}
m_userWave.unlock();
m_bad_lfoShapeData = FALSE;
}
void envelopeAndLFOWidget::triggerLFO( engine * _engine )
{
vvector<envelopeAndLFOWidget *> & v = s_EaLWidgets[_engine];
@@ -519,6 +536,7 @@ void envelopeAndLFOWidget::triggerLFO( engine * _engine )
{
( *it )->m_lfoFrame +=
_engine->getMixer()->framesPerAudioBuffer();
( *it )->m_bad_lfoShapeData = TRUE;
}
}
@@ -532,51 +550,70 @@ void envelopeAndLFOWidget::resetLFO( engine * _engine )
it != v.end(); ++it )
{
( *it )->m_lfoFrame = 0;
( *it )->m_bad_lfoShapeData = TRUE;
}
}
inline float FASTCALL envelopeAndLFOWidget::lfoLevel( f_cnt_t _frame,
const f_cnt_t _frame_offset ) const
inline void FASTCALL envelopeAndLFOWidget::fillLFOLevel( float * _buf,
f_cnt_t _frame,
const fpab_t _frames )
{
if( m_lfoAmountIsZero == FALSE && _frame > m_lfoPredelayFrames )
if( m_lfoAmountIsZero || _frame <= m_lfoPredelayFrames )
{
#ifdef LMMS_DEBUG
assert( m_lfoShapeData != NULL );
#endif
_frame -= m_lfoPredelayFrames;
if( _frame > m_lfoAttackFrames )
for( fpab_t offset = 0; offset < _frames; ++offset )
{
return( m_lfoShapeData[( m_lfoFrame + _frame_offset ) %
m_lfoOscillationFrames] );
*_buf++ = 0.0f;
}
return( m_lfoShapeData[( m_lfoFrame + _frame_offset ) %
m_lfoOscillationFrames] *
_frame / m_lfoAttackFrames );
return;
}
_frame -= m_lfoPredelayFrames;
if( m_bad_lfoShapeData )
{
updateLFOShapeData();
}
fpab_t offset = 0;
for( ; offset < _frames && _frame < m_lfoAttackFrames; ++offset,
++_frame )
{
*_buf++ = m_lfoShapeData[offset] * _frame / m_lfoAttackFrames;
}
for( ; offset < _frames; ++offset )
{
*_buf++ = m_lfoShapeData[offset];
}
return( 0.0f );
}
float FASTCALL envelopeAndLFOWidget::level( f_cnt_t _frame,
void FASTCALL envelopeAndLFOWidget::fillLevel( float * _buf, f_cnt_t _frame,
const f_cnt_t _release_begin,
const f_cnt_t _frame_offset )
const fpab_t _frames )
{
const float lfo_level = lfoLevel( _frame, _frame_offset );
float env_level;
if( _frame < _release_begin && _frame < m_pahdFrames )
fillLFOLevel( _buf, _frame, _frames );
for( fpab_t offset = 0; offset < _frames; ++offset, ++_buf, ++_frame )
{
env_level = m_pahdEnv[_frame];
}
else if( _frame >= _release_begin )
{
if( ( _frame -= _release_begin ) < m_rFrames )
float env_level;
if( _frame < _release_begin )
{
env_level = m_rEnv[_frame] *
if( _frame < m_pahdFrames )
{
env_level = m_pahdEnv[_frame];
}
else
{
env_level = m_sustainLevel;
}
}
else if( ( _frame - _release_begin ) < m_rFrames )
{
env_level = m_rEnv[_frame - _release_begin] *
( ( _release_begin < m_pahdFrames ) ?
m_pahdEnv[_release_begin] : m_sustainLevel );
}
@@ -584,15 +621,12 @@ float FASTCALL envelopeAndLFOWidget::level( f_cnt_t _frame,
{
env_level = 0.0f;
}
// at this point, *_buf is LFO level
*_buf = m_controlEnvAmountCb->isChecked() ?
env_level * ( 0.5f + *_buf ) :
env_level + *_buf;
}
else
{
env_level = m_sustainLevel;
}
return( m_controlEnvAmountCb->isChecked() ?
env_level * ( 0.5f + lfo_level )
:
env_level + lfo_level );
}
@@ -649,7 +683,6 @@ void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
m_busyMutex.unlock();
updateSampleVars();
update();
}
@@ -730,8 +763,6 @@ void envelopeAndLFOWidget::dropEvent( QDropEvent * _de )
void envelopeAndLFOWidget::paintEvent( QPaintEvent * )
{
updateSampleVars();
#ifdef QT4
QPainter p( this );
p.setRenderHint( QPainter::Antialiasing );
@@ -1023,49 +1054,42 @@ void envelopeAndLFOWidget::updateSampleVars( void )
m_lfoAmountIsZero = FALSE;
}
if( m_lfoAmountIsZero == FALSE )
{
delete[] m_lfoShapeData;
m_lfoShapeData = new sample_t[m_lfoOscillationFrames];
for( f_cnt_t frame = 0; frame < m_lfoOscillationFrames;
++frame )
{
const float phase = frame / static_cast<float>(
m_lfoOscillationFrames );
// in gcc, optimization level 3 may place
// branches out of loop and generates one loop
// for each branch...
switch( m_lfoShape )
{
case TRIANGLE:
m_lfoShapeData[frame] =
oscillator::triangleSample( phase );
break;
case SQUARE:
m_lfoShapeData[frame] =
oscillator::squareSample( phase );
break;
case SAW:
m_lfoShapeData[frame] =
oscillator::sawSample( phase );
break;
case USER:
m_lfoShapeData[frame] =
m_userWave.userWaveSample( phase );
break;
case SIN:
default:
m_lfoShapeData[frame] =
oscillator::sinSample( phase );
break;
}
m_lfoShapeData[frame] *= m_lfoAmount;
}
}
m_bad_lfoShapeData = TRUE;
m_busyMutex.unlock();
update();
}
inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpab_t _frame_offset )
{
f_cnt_t frame = ( m_lfoFrame + _frame_offset ) % m_lfoOscillationFrames;
const float phase = frame / static_cast<float>(
m_lfoOscillationFrames );
sample_t shape_sample;
switch( m_lfoShape )
{
case TRIANGLE:
shape_sample = oscillator::triangleSample( phase );
break;
case SQUARE:
shape_sample = oscillator::squareSample( phase );
break;
case SAW:
shape_sample = oscillator::sawSample( phase );
break;
case USER:
shape_sample = m_userWave.userWaveSample( phase );
break;
case SIN:
default:
shape_sample = oscillator::sinSample( phase );
break;
}
return( shape_sample * m_lfoAmount );
}
@@ -1082,7 +1106,7 @@ void envelopeAndLFOWidget::x100Toggled( bool )
void envelopeAndLFOWidget::updateAfterKnobChange( float )
{
update();
updateSampleVars();
}
@@ -1091,7 +1115,7 @@ void envelopeAndLFOWidget::updateAfterKnobChange( float )
void envelopeAndLFOWidget::lfoWaveCh( int _val )
{
m_lfoShape = static_cast<lfoShapes>( _val );
update();
updateSampleVars();
}
@@ -1112,7 +1136,7 @@ void envelopeAndLFOWidget::lfoUserWaveCh( bool _on )
}
eng()->getSongEditor()->setModified();
update();
updateSampleVars();
}