changed busy flag into busy mutex, improves thread safety
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@352 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -89,7 +89,7 @@ public:
|
||||
|
||||
float FASTCALL level( f_cnt_t _frame,
|
||||
const f_cnt_t _release_begin,
|
||||
const f_cnt_t _frame_offset ) const;
|
||||
const f_cnt_t _frame_offset );
|
||||
|
||||
inline bool used( void ) const
|
||||
{
|
||||
@@ -105,6 +105,15 @@ public:
|
||||
return( "el" );
|
||||
}
|
||||
|
||||
void lock( void )
|
||||
{
|
||||
m_busyMutex.lock();
|
||||
}
|
||||
void unlock( void )
|
||||
{
|
||||
m_busyMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void updateSampleVars( void );
|
||||
@@ -183,7 +192,7 @@ private:
|
||||
USER
|
||||
} m_lfoShape;
|
||||
|
||||
volatile bool m_busy;
|
||||
QMutex m_busyMutex;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -124,8 +124,7 @@ envelopeAndLFOWidget::envelopeAndLFOWidget( float _value_for_zero_amount,
|
||||
m_lfoAmountIsZero( FALSE ),
|
||||
m_lfoShapeData( NULL ),
|
||||
m_userWave( eng() ),
|
||||
m_lfoShape( SIN ),
|
||||
m_busy( FALSE )
|
||||
m_lfoShape( SIN )
|
||||
{
|
||||
if( s_envGraph == NULL )
|
||||
{
|
||||
@@ -564,12 +563,8 @@ inline float FASTCALL envelopeAndLFOWidget::lfoLevel( f_cnt_t _frame,
|
||||
|
||||
float FASTCALL envelopeAndLFOWidget::level( f_cnt_t _frame,
|
||||
const f_cnt_t _release_begin,
|
||||
const f_cnt_t _frame_offset ) const
|
||||
const f_cnt_t _frame_offset )
|
||||
{
|
||||
if( m_busy )
|
||||
{
|
||||
return( 0.0f );
|
||||
}
|
||||
const float lfo_level = lfoLevel( _frame, _frame_offset );
|
||||
float env_level;
|
||||
if( _frame < _release_begin && _frame < m_pahdFrames )
|
||||
@@ -629,7 +624,7 @@ void envelopeAndLFOWidget::saveSettings( QDomDocument & _doc,
|
||||
|
||||
void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_busy = TRUE;
|
||||
m_busyMutex.lock();
|
||||
|
||||
m_predelayKnob->loadSettings( _this, "pdel" );
|
||||
m_attackKnob->loadSettings( _this, "att" );
|
||||
@@ -650,7 +645,7 @@ void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
|
||||
"lfosyncmode" ).toInt() );
|
||||
m_userWave.setAudioFile( _this.attribute( "userwavefile" ) );
|
||||
|
||||
m_busy = FALSE;
|
||||
m_busyMutex.unlock();
|
||||
|
||||
updateSampleVars();
|
||||
update();
|
||||
@@ -910,176 +905,166 @@ void envelopeAndLFOWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
{
|
||||
if( !m_busy )
|
||||
{
|
||||
m_busy = TRUE;
|
||||
m_busyMutex.lock();
|
||||
|
||||
const float frames_per_env_seg = SECS_PER_ENV_SEGMENT *
|
||||
const float frames_per_env_seg = SECS_PER_ENV_SEGMENT *
|
||||
eng()->getMixer()->sampleRate();
|
||||
const f_cnt_t predelay_frames = static_cast<f_cnt_t>(
|
||||
const f_cnt_t predelay_frames = static_cast<f_cnt_t>(
|
||||
frames_per_env_seg *
|
||||
expKnobVal( m_predelayKnob->value() ) );
|
||||
|
||||
const f_cnt_t attack_frames = static_cast<f_cnt_t>(
|
||||
frames_per_env_seg *
|
||||
const f_cnt_t attack_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_attackKnob->value() ) );
|
||||
|
||||
const f_cnt_t hold_frames = static_cast<f_cnt_t>(
|
||||
frames_per_env_seg *
|
||||
const f_cnt_t hold_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_holdKnob->value() ) );
|
||||
|
||||
const f_cnt_t decay_frames = static_cast<f_cnt_t>(
|
||||
frames_per_env_seg *
|
||||
const f_cnt_t decay_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_decayKnob->value() *
|
||||
m_sustainKnob->value() ) );
|
||||
|
||||
m_sustainLevel = 1.0f - m_sustainKnob->value();
|
||||
m_amount = m_amountKnob->value();
|
||||
if( m_amount >= 0 )
|
||||
{
|
||||
m_amountAdd = ( 1.0f - m_amount ) *
|
||||
m_valueForZeroAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_amountAdd = m_valueForZeroAmount;
|
||||
}
|
||||
m_sustainLevel = 1.0f - m_sustainKnob->value();
|
||||
m_amount = m_amountKnob->value();
|
||||
if( m_amount >= 0 )
|
||||
{
|
||||
m_amountAdd = ( 1.0f - m_amount ) * m_valueForZeroAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_amountAdd = m_valueForZeroAmount;
|
||||
}
|
||||
|
||||
m_pahdFrames = predelay_frames + attack_frames + hold_frames +
|
||||
m_pahdFrames = predelay_frames + attack_frames + hold_frames +
|
||||
decay_frames;
|
||||
m_rFrames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
m_rFrames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_releaseKnob->value() ) );
|
||||
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
//m_pahdFrames = 0;
|
||||
m_rFrames = 0;
|
||||
}
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
//m_pahdFrames = 0;
|
||||
m_rFrames = 0;
|
||||
}
|
||||
|
||||
sample_t * new_pahd_env = new sample_t[m_pahdFrames];
|
||||
sample_t * new_r_env = new sample_t[m_rFrames];
|
||||
sample_t * new_pahd_env = new sample_t[m_pahdFrames];
|
||||
sample_t * new_r_env = new sample_t[m_rFrames];
|
||||
|
||||
for( f_cnt_t i = 0; i < predelay_frames; ++i )
|
||||
{
|
||||
new_pahd_env[i] = m_amountAdd;
|
||||
}
|
||||
for( f_cnt_t i = 0; i < predelay_frames; ++i )
|
||||
{
|
||||
new_pahd_env[i] = m_amountAdd;
|
||||
}
|
||||
|
||||
f_cnt_t add = predelay_frames;
|
||||
f_cnt_t add = predelay_frames;
|
||||
|
||||
for( f_cnt_t i = 0; i < attack_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = ( (float)i / attack_frames ) *
|
||||
for( f_cnt_t i = 0; i < attack_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = ( (float)i / attack_frames ) *
|
||||
m_amount + m_amountAdd;
|
||||
}
|
||||
}
|
||||
|
||||
add += attack_frames;
|
||||
for( f_cnt_t i = 0; i < hold_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = m_amount + m_amountAdd;
|
||||
}
|
||||
add += attack_frames;
|
||||
for( f_cnt_t i = 0; i < hold_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = m_amount + m_amountAdd;
|
||||
}
|
||||
|
||||
add += hold_frames;
|
||||
for( f_cnt_t i = 0; i < decay_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = ( m_sustainLevel + ( 1.0f -
|
||||
add += hold_frames;
|
||||
for( f_cnt_t i = 0; i < decay_frames; ++i )
|
||||
{
|
||||
new_pahd_env[add+i] = ( m_sustainLevel + ( 1.0f -
|
||||
(float)i / decay_frames ) *
|
||||
( 1.0f - m_sustainLevel ) ) *
|
||||
m_amount + m_amountAdd;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_pahdEnv;
|
||||
delete[] m_rEnv;
|
||||
delete[] m_pahdEnv;
|
||||
delete[] m_rEnv;
|
||||
|
||||
m_pahdEnv = new_pahd_env;
|
||||
m_rEnv = new_r_env;
|
||||
m_pahdEnv = new_pahd_env;
|
||||
m_rEnv = new_r_env;
|
||||
|
||||
for( f_cnt_t i = 0; i < m_rFrames; ++i )
|
||||
{
|
||||
new_r_env[i] = ( (float)( m_rFrames - i ) / m_rFrames
|
||||
for( f_cnt_t i = 0; i < m_rFrames; ++i )
|
||||
{
|
||||
new_r_env[i] = ( (float)( m_rFrames - i ) / m_rFrames
|
||||
// * m_sustainLevel
|
||||
) * m_amount;
|
||||
}
|
||||
}
|
||||
|
||||
// save this calculation in real-time-part
|
||||
m_sustainLevel = m_sustainLevel * m_amount + m_amountAdd;
|
||||
|
||||
// save this calculation in real-time-part
|
||||
m_sustainLevel = m_sustainLevel * m_amount + m_amountAdd;
|
||||
|
||||
const float frames_per_lfo_oscillation =
|
||||
SECS_PER_LFO_OSCILLATION *
|
||||
|
||||
const float frames_per_lfo_oscillation = SECS_PER_LFO_OSCILLATION *
|
||||
eng()->getMixer()->sampleRate();
|
||||
m_lfoPredelayFrames = static_cast<f_cnt_t>(
|
||||
frames_per_lfo_oscillation *
|
||||
m_lfoPredelayFrames = static_cast<f_cnt_t>( frames_per_lfo_oscillation *
|
||||
expKnobVal( m_lfoPredelayKnob->value() ) );
|
||||
m_lfoAttackFrames = static_cast<f_cnt_t>(
|
||||
frames_per_lfo_oscillation *
|
||||
m_lfoAttackFrames = static_cast<f_cnt_t>( frames_per_lfo_oscillation *
|
||||
expKnobVal( m_lfoAttackKnob->value() ) );
|
||||
m_lfoOscillationFrames = static_cast<f_cnt_t>(
|
||||
m_lfoOscillationFrames = static_cast<f_cnt_t>(
|
||||
frames_per_lfo_oscillation *
|
||||
m_lfoSpeedKnob->value() );
|
||||
if( m_x100Cb->isChecked() )
|
||||
{
|
||||
m_lfoOscillationFrames /= 100;
|
||||
}
|
||||
m_lfoAmount = m_lfoAmountKnob->value() * 0.5f;
|
||||
|
||||
m_used = TRUE;
|
||||
if( static_cast<int>( floorf( m_lfoAmount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
m_lfoAmountIsZero = TRUE;
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) ==
|
||||
0 )
|
||||
{
|
||||
m_used = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
// hope, compiler optimizes well and places
|
||||
// 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_busy = FALSE;
|
||||
if( m_x100Cb->isChecked() )
|
||||
{
|
||||
m_lfoOscillationFrames /= 100;
|
||||
}
|
||||
m_lfoAmount = m_lfoAmountKnob->value() * 0.5f;
|
||||
|
||||
m_used = TRUE;
|
||||
if( static_cast<int>( floorf( m_lfoAmount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
m_lfoAmountIsZero = TRUE;
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
m_used = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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_busyMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -238,7 +238,12 @@ float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n,
|
||||
release_begin += eng()->getMixer()->framesPerAudioBuffer();
|
||||
}
|
||||
|
||||
return( m_envLFOWidgets[VOLUME]->level( _frame, release_begin, 0 ) );
|
||||
m_envLFOWidgets[VOLUME]->lock();
|
||||
float volume_level =
|
||||
m_envLFOWidgets[VOLUME]->level( _frame, release_begin, 0 );
|
||||
m_envLFOWidgets[VOLUME]->unlock();
|
||||
|
||||
return( volume_level );
|
||||
}
|
||||
|
||||
|
||||
@@ -277,6 +282,10 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
eng()->getMixer()->sampleRate() );
|
||||
}
|
||||
|
||||
m_envLFOWidgets[VOLUME]->lock();
|
||||
m_envLFOWidgets[CUT]->lock();
|
||||
m_envLFOWidgets[RES]->lock();
|
||||
|
||||
if( m_filterGroupBox->isActive() )
|
||||
{
|
||||
int old_filter_cut = 0;
|
||||
@@ -457,6 +466,10 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
m_envLFOWidgets[RES]->unlock();
|
||||
m_envLFOWidgets[CUT]->unlock();
|
||||
m_envLFOWidgets[VOLUME]->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user