EnvelopeAndLfoParameters: moved global instances management into helper class

It's a bad style to manage global instances of an object in the object
itself. Therefore introduced a nested helper class which manages all
instances of EnvelopeAndLfoParameters globally. It is now responsible
for global reset/triggers of LFOs. In contrast to previous state, this
is now done thread-safe. Fixes crashes for example while importing
MIDI files.
This commit is contained in:
Tobias Doerffel
2010-05-21 13:27:04 +02:00
parent fe7d5e3d5a
commit 5f6c42f19c
4 changed files with 100 additions and 48 deletions

View File

@@ -1,7 +1,7 @@
/*
* EnvelopeAndLfoParameters.h - class EnvelopeAndLfoParameters
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -22,7 +22,6 @@
*
*/
#ifndef _ENVELOPE_AND_LFO_PARAMETERS_H
#define _ENVELOPE_AND_LFO_PARAMETERS_H
@@ -35,11 +34,39 @@
#include "lmms_basics.h"
class EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject
{
Q_OBJECT
public:
class LfoInstances
{
public:
LfoInstances()
{
}
~LfoInstances()
{
}
inline bool isEmpty() const
{
return m_lfos.isEmpty();
}
void trigger();
void reset();
void add( EnvelopeAndLfoParameters * lfo );
void remove( EnvelopeAndLfoParameters * lfo );
private:
QMutex m_lfoListMutex;
typedef QList<EnvelopeAndLfoParameters *> LfoList;
LfoList m_lfos;
} ;
EnvelopeAndLfoParameters( float _value_for_zero_amount,
Model * _parent );
virtual ~EnvelopeAndLfoParameters();
@@ -49,8 +76,10 @@ public:
return ( ( _val < 0 ) ? -_val : _val ) * _val;
}
static void triggerLfo();
static void resetLfo();
static LfoInstances * instances()
{
return s_lfoInstances;
}
void fillLevel( float * _buf, f_cnt_t _frame,
const f_cnt_t _release_begin,
@@ -89,8 +118,7 @@ protected:
private:
static QVector<EnvelopeAndLfoParameters *> s_EaLParametersInstances;
static LfoInstances * s_lfoInstances;
bool m_used;

View File

@@ -1,8 +1,8 @@
/*
* EnvelopeAndLfoParameters.cpp - class EnvelopeAndLfoParameters
*
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
@@ -38,7 +38,53 @@ extern const float SECS_PER_ENV_SEGMENT = 5.0f;
extern const float SECS_PER_LFO_OSCILLATION = 20.0f;
QVector<EnvelopeAndLfoParameters *> EnvelopeAndLfoParameters::s_EaLParametersInstances;
EnvelopeAndLfoParameters::LfoInstances * EnvelopeAndLfoParameters::s_lfoInstances = NULL;
void EnvelopeAndLfoParameters::LfoInstances::trigger()
{
QMutexLocker m( &m_lfoListMutex );
for( LfoList::Iterator it = m_lfos.begin();
it != m_lfos.end(); ++it )
{
( *it )->m_lfoFrame +=
engine::getMixer()->framesPerPeriod();
( *it )->m_bad_lfoShapeData = true;
}
}
void EnvelopeAndLfoParameters::LfoInstances::reset()
{
QMutexLocker m( &m_lfoListMutex );
for( LfoList::Iterator it = m_lfos.begin();
it != m_lfos.end(); ++it )
{
( *it )->m_lfoFrame = 0;
( *it )->m_bad_lfoShapeData = true;
}
}
void EnvelopeAndLfoParameters::LfoInstances::add( EnvelopeAndLfoParameters * lfo )
{
QMutexLocker m( &m_lfoListMutex );
m_lfos.append( lfo );
}
void EnvelopeAndLfoParameters::LfoInstances::remove( EnvelopeAndLfoParameters * lfo )
{
QMutexLocker m( &m_lfoListMutex );
m_lfos.removeAll( lfo );
}
@@ -70,7 +116,12 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters(
m_lfoAmountIsZero( false ),
m_lfoShapeData( NULL )
{
s_EaLParametersInstances.push_back( this );
if( s_lfoInstances == NULL )
{
s_lfoInstances = new LfoInstances();
}
instances()->add( this );
connect( &m_predelayModel, SIGNAL( dataChanged() ),
this, SLOT( updateSampleVars() ) );
@@ -133,10 +184,12 @@ EnvelopeAndLfoParameters::~EnvelopeAndLfoParameters()
delete[] m_rEnv;
delete[] m_lfoShapeData;
QVector<EnvelopeAndLfoParameters *> & v = s_EaLParametersInstances;
if( qFind( v.begin(), v.end(), this ) != v.end() )
instances()->remove( this );
if( instances()->isEmpty() )
{
v.erase( qFind( v.begin(), v.end(), this ) );
delete instances();
s_lfoInstances = NULL;
}
}
@@ -187,35 +240,6 @@ void EnvelopeAndLfoParameters::updateLfoShapeData()
void EnvelopeAndLfoParameters::triggerLfo()
{
QVector<EnvelopeAndLfoParameters *> & v = s_EaLParametersInstances;
for( QVector<EnvelopeAndLfoParameters *>::iterator it = v.begin();
it != v.end(); ++it )
{
( *it )->m_lfoFrame +=
engine::getMixer()->framesPerPeriod();
( *it )->m_bad_lfoShapeData = true;
}
}
void EnvelopeAndLfoParameters::resetLfo()
{
QVector<EnvelopeAndLfoParameters *> & v = s_EaLParametersInstances;
for( QVector<EnvelopeAndLfoParameters *>::iterator it = v.begin();
it != v.end(); ++it )
{
( *it )->m_lfoFrame = 0;
( *it )->m_bad_lfoShapeData = true;
}
}
inline void EnvelopeAndLfoParameters::fillLfoLevel( float * _buf,
f_cnt_t _frame,
const fpp_t _frames )

View File

@@ -1,7 +1,7 @@
/*
* Mixer.cpp - Mixer for audio processing and rendering
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -379,7 +379,7 @@ sampleFrameA * Mixer::renderNextBuffer()
emit nextAudioBuffer();
// and trigger LFOs
EnvelopeAndLfoParameters::triggerLfo();
EnvelopeAndLfoParameters::instances()->trigger();
Controller::triggerFrameCounter();
const float new_cpu_load = timer.elapsed() / 10000.0f *

View File

@@ -1,7 +1,7 @@
/*
* song.cpp - root of the model-tree
* song.cpp - root of the model tree
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -301,7 +301,7 @@ void song::processNextBuffer()
// at song-start we have to reset the LFOs
if( m_playPos[Mode_PlaySong] == 0 )
{
EnvelopeAndLfoParameters::resetLfo();
EnvelopeAndLfoParameters::instances()->reset();
}
break;