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.
(cherry picked from commit 5f6c42f19c)
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* mixer.cpp - audio-device-independent mixer for LMMS
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "mixer.h"
|
||||
@@ -664,7 +663,7 @@ const surroundSampleFrame * mixer::renderNextBuffer()
|
||||
emit nextAudioBuffer();
|
||||
|
||||
// and trigger LFOs
|
||||
EnvelopeAndLfoParameters::triggerLfo();
|
||||
EnvelopeAndLfoParameters::instances()->trigger();
|
||||
Controller::triggerFrameCounter();
|
||||
|
||||
const float new_cpu_load = timer.elapsed() / 10000.0f *
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -300,7 +300,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user