@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#define _ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#ifndef ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#define ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
@@ -138,6 +138,8 @@ private:
|
||||
f_cnt_t m_rFrames;
|
||||
sample_t * m_pahdEnv;
|
||||
sample_t * m_rEnv;
|
||||
f_cnt_t m_pahdBufSize;
|
||||
f_cnt_t m_rBufSize;
|
||||
|
||||
|
||||
FloatModel m_lfoPredelayModel;
|
||||
|
||||
@@ -231,6 +231,8 @@ private:
|
||||
QMutex m_notesMutex;
|
||||
|
||||
int m_runningMidiNotes[NumKeys];
|
||||
QMutex m_midiNotesMutex;
|
||||
|
||||
bool m_sustainPedalPressed;
|
||||
|
||||
bool m_silentBuffersProcessed;
|
||||
|
||||
@@ -308,6 +308,16 @@ public:
|
||||
{
|
||||
m_inputFramesMutex.unlock();
|
||||
}
|
||||
|
||||
void lockPlayHandleRemoval()
|
||||
{
|
||||
m_playHandleRemovalMutex.lock();
|
||||
}
|
||||
|
||||
void unlockPlayHandleRemoval()
|
||||
{
|
||||
m_playHandleRemovalMutex.unlock();
|
||||
}
|
||||
|
||||
// audio-buffer-mgm
|
||||
void bufferToPort( const sampleFrame * _buf,
|
||||
@@ -449,7 +459,8 @@ private:
|
||||
|
||||
QMutex m_globalMutex;
|
||||
QMutex m_inputFramesMutex;
|
||||
|
||||
|
||||
QMutex m_playHandleRemovalMutex;
|
||||
|
||||
fifo * m_fifo;
|
||||
fifoWriter * m_fifoWriter;
|
||||
|
||||
@@ -276,7 +276,8 @@ private:
|
||||
// release of note
|
||||
NotePlayHandleList m_subNotes; // used for chords and arpeggios
|
||||
volatile bool m_released; // indicates whether note is released
|
||||
bool m_hasParent;
|
||||
bool m_hasParent; // indicates whether note has parent
|
||||
NotePlayHandle * m_parent; // parent note
|
||||
bool m_hadChildren;
|
||||
bool m_muted; // indicates whether note is muted
|
||||
track* m_bbTrack; // related BB track
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#include "ThreadableJob.h"
|
||||
#include "lmms_basics.h"
|
||||
@@ -84,7 +85,18 @@ public:
|
||||
return !isFinished();
|
||||
}
|
||||
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_processingLock.lock();
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
m_processingLock.unlock();
|
||||
}
|
||||
bool tryLock()
|
||||
{
|
||||
return m_processingLock.tryLock();
|
||||
}
|
||||
virtual void play( sampleFrame* buffer ) = 0;
|
||||
virtual bool isFinished( void ) const = 0;
|
||||
|
||||
@@ -108,6 +120,7 @@ private:
|
||||
Type m_type;
|
||||
f_cnt_t m_offset;
|
||||
const QThread* m_affinity;
|
||||
QMutex m_processingLock;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
|
||||
virtual void movePosition( const MidiTime & _pos );
|
||||
virtual void changeLength( const MidiTime & _length );
|
||||
|
||||
@@ -508,6 +508,18 @@ public:
|
||||
m_height = _height;
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_processingLock.lock();
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
m_processingLock.unlock();
|
||||
}
|
||||
bool tryLock()
|
||||
{
|
||||
return m_processingLock.tryLock();
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void setName( const QString & _new_name )
|
||||
@@ -533,6 +545,7 @@ private:
|
||||
|
||||
tcoVector m_trackContentObjects;
|
||||
|
||||
QMutex m_processingLock;
|
||||
|
||||
friend class trackView;
|
||||
|
||||
|
||||
@@ -100,8 +100,12 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters(
|
||||
m_releaseModel( 0.1, 0.0, 2.0, 0.001, this, tr( "Release" ) ),
|
||||
m_amountModel( 0.0, -1.0, 1.0, 0.005, this, tr( "Modulation" ) ),
|
||||
m_valueForZeroAmount( _value_for_zero_amount ),
|
||||
m_pahdFrames( 0 ),
|
||||
m_rFrames( 0 ),
|
||||
m_pahdEnv( NULL ),
|
||||
m_rEnv( NULL ),
|
||||
m_pahdBufSize( 0 ),
|
||||
m_rBufSize( 0 ),
|
||||
m_lfoPredelayModel( 0.0, 0.0, 1.0, 0.001, this, tr( "LFO Predelay" ) ),
|
||||
m_lfoAttackModel( 0.0, 0.0, 1.0, 0.001, this, tr( "LFO Attack" ) ),
|
||||
m_lfoSpeedModel( 0.1, 0.001, 1.0, 0.0001,
|
||||
@@ -399,8 +403,6 @@ void EnvelopeAndLfoParameters::loadSettings( const QDomElement & _this )
|
||||
|
||||
void EnvelopeAndLfoParameters::updateSampleVars()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
|
||||
const float frames_per_env_seg = SECS_PER_ENV_SEGMENT *
|
||||
engine::mixer()->processingSampleRate();
|
||||
// TODO: Remove the expKnobVals, time should be linear
|
||||
@@ -436,15 +438,24 @@ void EnvelopeAndLfoParameters::updateSampleVars()
|
||||
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
//m_pahdFrames = 0;
|
||||
m_rFrames = 0;
|
||||
}
|
||||
|
||||
delete[] m_pahdEnv;
|
||||
delete[] m_rEnv;
|
||||
|
||||
m_pahdEnv = new sample_t[m_pahdFrames];
|
||||
m_rEnv = new sample_t[m_rFrames];
|
||||
// if the buffers are too small, make bigger ones - so we only alloc new memory when necessary
|
||||
if( m_pahdBufSize < m_pahdFrames )
|
||||
{
|
||||
sample_t * tmp = m_pahdEnv;
|
||||
m_pahdEnv = new sample_t[m_pahdFrames];
|
||||
delete tmp;
|
||||
m_pahdBufSize = m_pahdFrames;
|
||||
}
|
||||
if( m_rBufSize < m_rFrames )
|
||||
{
|
||||
sample_t * tmp = m_rEnv;
|
||||
m_rEnv = new sample_t[m_rFrames];
|
||||
delete tmp;
|
||||
m_rBufSize = m_rFrames;
|
||||
}
|
||||
|
||||
const float aa = m_amountAdd;
|
||||
for( f_cnt_t i = 0; i < predelay_frames; ++i )
|
||||
@@ -523,7 +534,6 @@ void EnvelopeAndLfoParameters::updateSampleVars()
|
||||
|
||||
emit dataChanged();
|
||||
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ InstrumentSoundShaping::InstrumentSoundShaping(
|
||||
m_filterModel.addItem( tr( "RC LowPass 24dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "RC BandPass 24dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "RC HighPass 24dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Vocal Formant Filter" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Vocal Formant Filter" ), new PixmapLoader( "filter_hp" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,9 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
|
||||
if( m_filterEnabledModel.value() )
|
||||
{
|
||||
float cutBuffer [frames];
|
||||
float resBuffer [frames];
|
||||
|
||||
int old_filter_cut = 0;
|
||||
int old_filter_res = 0;
|
||||
|
||||
@@ -155,27 +158,13 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
}
|
||||
n->m_filter->setFilterType( m_filterModel.value() );
|
||||
|
||||
#ifdef __GNUC__
|
||||
float cut_buf[frames];
|
||||
float res_buf[frames];
|
||||
#else
|
||||
float * cut_buf = NULL;
|
||||
float * res_buf = NULL;
|
||||
#endif
|
||||
|
||||
if( m_envLfoParameters[Cut]->isUsed() )
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
cut_buf = new float[frames];
|
||||
#endif
|
||||
m_envLfoParameters[Cut]->fillLevel( cut_buf, envTotalFrames, envReleaseBegin, frames );
|
||||
m_envLfoParameters[Cut]->fillLevel( cutBuffer, envTotalFrames, envReleaseBegin, frames );
|
||||
}
|
||||
if( m_envLfoParameters[Resonance]->isUsed() )
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
res_buf = new float[frames];
|
||||
#endif
|
||||
m_envLfoParameters[Resonance]->fillLevel( res_buf, envTotalFrames, envReleaseBegin, frames );
|
||||
m_envLfoParameters[Resonance]->fillLevel( resBuffer, envTotalFrames, envReleaseBegin, frames );
|
||||
}
|
||||
|
||||
const float fcv = m_filterCutModel.value();
|
||||
@@ -186,10 +175,10 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
{
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
const float new_cut_val = EnvelopeAndLfoParameters::expKnobVal( cut_buf[frame] ) *
|
||||
const float new_cut_val = EnvelopeAndLfoParameters::expKnobVal( cutBuffer[frame] ) *
|
||||
CUT_FREQ_MULTIPLIER + fcv;
|
||||
|
||||
const float new_res_val = frv + RES_MULTIPLIER * res_buf[frame];
|
||||
const float new_res_val = frv + RES_MULTIPLIER * resBuffer[frame];
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut ||
|
||||
static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
@@ -207,7 +196,7 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
{
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
float new_cut_val = EnvelopeAndLfoParameters::expKnobVal( cut_buf[frame] ) *
|
||||
float new_cut_val = EnvelopeAndLfoParameters::expKnobVal( cutBuffer[frame] ) *
|
||||
CUT_FREQ_MULTIPLIER + fcv;
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut )
|
||||
@@ -224,7 +213,7 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
{
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
float new_res_val = frv + RES_MULTIPLIER * res_buf[frame];
|
||||
float new_res_val = frv + RES_MULTIPLIER * resBuffer[frame];
|
||||
|
||||
if( static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
{
|
||||
@@ -246,32 +235,20 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
buffer[frame][1] = n->m_filter->update( buffer[frame][1], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
delete[] cut_buf;
|
||||
delete[] res_buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
if( m_envLfoParameters[Volume]->isUsed() )
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
float vol_buf[frames];
|
||||
#else
|
||||
float * vol_buf = new float[frames];
|
||||
#endif
|
||||
m_envLfoParameters[Volume]->fillLevel( vol_buf, envTotalFrames, envReleaseBegin, frames );
|
||||
float volBuffer [frames];
|
||||
m_envLfoParameters[Volume]->fillLevel( volBuffer, envTotalFrames, envReleaseBegin, frames );
|
||||
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
float vol_level = vol_buf[frame];
|
||||
float vol_level = volBuffer[frame];
|
||||
vol_level = vol_level * vol_level;
|
||||
buffer[frame][0] = vol_level * buffer[frame][0];
|
||||
buffer[frame][1] = vol_level * buffer[frame][1];
|
||||
}
|
||||
#ifndef __GNUC__
|
||||
delete[] vol_buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* else if( m_envLfoParameters[Volume]->isUsed() == false && m_envLfoParameters[PANNING]->isUsed() )
|
||||
|
||||
@@ -337,13 +337,10 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
|
||||
m_inputBufferFrames[ m_inputBufferWrite ] = 0;
|
||||
unlockInputFrames();
|
||||
|
||||
// now we have to make sure no other thread does anything bad
|
||||
// while we're acting...
|
||||
lock();
|
||||
|
||||
// remove all play-handles that have to be deleted and delete
|
||||
// them if they still exist...
|
||||
// maybe this algorithm could be optimized...
|
||||
lockPlayHandleRemoval();
|
||||
ConstPlayHandleList::Iterator it_rem = m_playHandlesToRemove.begin();
|
||||
while( it_rem != m_playHandlesToRemove.end() )
|
||||
{
|
||||
@@ -357,6 +354,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
|
||||
|
||||
it_rem = m_playHandlesToRemove.erase( it_rem );
|
||||
}
|
||||
unlockPlayHandleRemoval();
|
||||
|
||||
// now we have to make sure no other thread does anything bad
|
||||
// while we're acting...
|
||||
lock();
|
||||
|
||||
// rotate buffers
|
||||
m_writeBuffer = ( m_writeBuffer + 1 ) % m_poolDepth;
|
||||
@@ -381,6 +383,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
|
||||
m_playHandleMutex.unlock();
|
||||
|
||||
// STAGE 1: run and render all play handles
|
||||
lockPlayHandleRemoval();
|
||||
MixerWorkerThread::fillJobQueue<PlayHandleList>( m_playHandles );
|
||||
MixerWorkerThread::startAndWaitForJobs();
|
||||
|
||||
@@ -404,6 +407,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
|
||||
++it;
|
||||
}
|
||||
}
|
||||
unlockPlayHandleRemoval();
|
||||
|
||||
|
||||
// STAGE 2: process effects of all instrument- and sampletracks
|
||||
@@ -648,12 +652,12 @@ void Mixer::removeAudioPort( AudioPort * _port )
|
||||
|
||||
void Mixer::removePlayHandle( PlayHandle * _ph )
|
||||
{
|
||||
lock();
|
||||
// check thread affinity as we must not delete play-handles
|
||||
// which were created in a thread different than mixer thread
|
||||
if( _ph->affinityMatters() &&
|
||||
_ph->affinity() == QThread::currentThread() )
|
||||
{
|
||||
lockPlayHandleRemoval();
|
||||
PlayHandleList::Iterator it =
|
||||
qFind( m_playHandles.begin(),
|
||||
m_playHandles.end(), _ph );
|
||||
@@ -662,12 +666,12 @@ void Mixer::removePlayHandle( PlayHandle * _ph )
|
||||
m_playHandles.erase( it );
|
||||
delete _ph;
|
||||
}
|
||||
unlockPlayHandleRemoval();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playHandlesToRemove.push_back( _ph );
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -675,7 +679,7 @@ void Mixer::removePlayHandle( PlayHandle * _ph )
|
||||
|
||||
void Mixer::removePlayHandles( track * _track, bool removeIPHs )
|
||||
{
|
||||
lock();
|
||||
lockPlayHandleRemoval();
|
||||
PlayHandleList::Iterator it = m_playHandles.begin();
|
||||
while( it != m_playHandles.end() )
|
||||
{
|
||||
@@ -689,7 +693,7 @@ void Mixer::removePlayHandles( track * _track, bool removeIPHs )
|
||||
++it;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
unlockPlayHandleRemoval();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +62,10 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
m_framesBeforeRelease( 0 ),
|
||||
m_releaseFramesToDo( 0 ),
|
||||
m_releaseFramesDone( 0 ),
|
||||
m_subNotes(),
|
||||
m_released( false ),
|
||||
m_hasParent( parent != NULL ),
|
||||
m_parent( parent ),
|
||||
m_hadChildren( false ),
|
||||
m_muted( false ),
|
||||
m_bbTrack( NULL ),
|
||||
@@ -76,6 +78,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
m_midiChannel( midiEventChannel >= 0 ? midiEventChannel : instrumentTrack->midiPort()->realOutputChannel() ),
|
||||
m_origin( origin )
|
||||
{
|
||||
lock();
|
||||
if( hasParent() == false )
|
||||
{
|
||||
m_baseDetuning = new BaseDetuning( detuning() );
|
||||
@@ -94,23 +97,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
updateFrequency();
|
||||
|
||||
setFrames( _frames );
|
||||
|
||||
// inform attached components about new MIDI note (used for recording in Piano Roll)
|
||||
if( m_origin == OriginMidiInput )
|
||||
{
|
||||
m_instrumentTrack->midiNoteOn( *this );
|
||||
}
|
||||
|
||||
if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() )
|
||||
{
|
||||
const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity();
|
||||
|
||||
// send MidiNoteOn event
|
||||
m_instrumentTrack->processOutEvent(
|
||||
MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ),
|
||||
MidiTime::fromFrames( offset(), engine::framesPerTick() ),
|
||||
offset() );
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +105,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
|
||||
NotePlayHandle::~NotePlayHandle()
|
||||
{
|
||||
lock();
|
||||
noteOff( 0 );
|
||||
|
||||
if( hasParent() == false )
|
||||
@@ -125,6 +113,10 @@ NotePlayHandle::~NotePlayHandle()
|
||||
delete m_baseDetuning;
|
||||
m_instrumentTrack->m_processHandles.removeAll( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_parent->m_subNotes.removeOne( this );
|
||||
}
|
||||
|
||||
if( m_pluginData != NULL )
|
||||
{
|
||||
@@ -136,13 +128,14 @@ NotePlayHandle::~NotePlayHandle()
|
||||
m_instrumentTrack->m_notes[key()] = NULL;
|
||||
}
|
||||
|
||||
for( NotePlayHandleList::Iterator it = m_subNotes.begin(); it != m_subNotes.end(); ++it )
|
||||
foreach( NotePlayHandle * n, m_subNotes )
|
||||
{
|
||||
delete *it;
|
||||
delete n;
|
||||
}
|
||||
m_subNotes.clear();
|
||||
|
||||
delete m_filter;
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +188,28 @@ void NotePlayHandle::play( sampleFrame * _working_buffer )
|
||||
return;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
if( m_totalFramesPlayed == 0 )
|
||||
{
|
||||
// inform attached components about new MIDI note (used for recording in Piano Roll)
|
||||
if( m_origin == OriginMidiInput )
|
||||
{
|
||||
m_instrumentTrack->midiNoteOn( *this );
|
||||
}
|
||||
|
||||
if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() )
|
||||
{
|
||||
const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity();
|
||||
|
||||
// send MidiNoteOn event
|
||||
m_instrumentTrack->processOutEvent(
|
||||
MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ),
|
||||
MidiTime::fromFrames( offset(), engine::framesPerTick() ),
|
||||
offset() );
|
||||
}
|
||||
}
|
||||
|
||||
// number of frames that can be played this period
|
||||
f_cnt_t framesThisPeriod = m_totalFramesPlayed == 0
|
||||
? engine::mixer()->framesPerPeriod() - offset()
|
||||
@@ -279,22 +294,18 @@ void NotePlayHandle::play( sampleFrame * _working_buffer )
|
||||
}
|
||||
|
||||
// play sub-notes (e.g. chords)
|
||||
for( NotePlayHandleList::Iterator it = m_subNotes.begin(); it != m_subNotes.end(); )
|
||||
foreach( NotePlayHandle * n, m_subNotes )
|
||||
{
|
||||
( *it )->play( _working_buffer );
|
||||
if( ( *it )->isFinished() )
|
||||
n->play( _working_buffer );
|
||||
if( n->isFinished() )
|
||||
{
|
||||
delete *it;
|
||||
it = m_subNotes.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
|
||||
// update internal data
|
||||
m_totalFramesPlayed += framesThisPeriod;
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -346,11 +357,12 @@ void NotePlayHandle::noteOff( const f_cnt_t _s )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_released = true;
|
||||
|
||||
// first note-off all sub-notes
|
||||
for( NotePlayHandleList::Iterator it = m_subNotes.begin(); it != m_subNotes.end(); ++it )
|
||||
foreach( NotePlayHandle * n, m_subNotes )
|
||||
{
|
||||
( *it )->noteOff( _s );
|
||||
n->noteOff( _s );
|
||||
}
|
||||
|
||||
// then set some variables indicating release-state
|
||||
@@ -372,8 +384,6 @@ void NotePlayHandle::noteOff( const f_cnt_t _s )
|
||||
setLength( MidiTime( static_cast<f_cnt_t>( totalFramesPlayed() / engine::framesPerTick() ) ) );
|
||||
m_instrumentTrack->midiNoteOff( *this );
|
||||
}
|
||||
|
||||
m_released = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -160,9 +160,11 @@ void TrackContainer::addTrack( track * _track )
|
||||
{
|
||||
if( _track->type() != track::HiddenAutomationTrack )
|
||||
{
|
||||
_track->lock();
|
||||
m_tracksMutex.lockForWrite();
|
||||
m_tracks.push_back( _track );
|
||||
m_tracksMutex.unlock();
|
||||
_track->unlock();
|
||||
emit trackAdded( _track );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ void song::masterVolumeChanged()
|
||||
|
||||
void song::setTempo()
|
||||
{
|
||||
engine::mixer()->lockPlayHandleRemoval();
|
||||
const bpm_t tempo = (bpm_t) m_tempoModel.value();
|
||||
engine::mixer()->lock();
|
||||
PlayHandleList & playHandles = engine::mixer()->playHandles();
|
||||
for( PlayHandleList::Iterator it = playHandles.begin();
|
||||
it != playHandles.end(); ++it )
|
||||
@@ -147,10 +147,12 @@ void song::setTempo()
|
||||
NotePlayHandle * nph = dynamic_cast<NotePlayHandle *>( *it );
|
||||
if( nph && !nph->isReleased() )
|
||||
{
|
||||
nph->lock();
|
||||
nph->resize( tempo );
|
||||
nph->unlock();
|
||||
}
|
||||
}
|
||||
engine::mixer()->unlock();
|
||||
engine::mixer()->unlockPlayHandleRemoval();
|
||||
|
||||
engine::updateFramesPerTick();
|
||||
|
||||
@@ -670,10 +672,8 @@ void song::removeBar()
|
||||
|
||||
void song::addBBTrack()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
track * t = track::create( track::BBTrack, this );
|
||||
engine::getBBTrackContainer()->setCurrentBB( dynamic_cast<bbTrack *>( t )->index() );
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -681,9 +681,7 @@ void song::addBBTrack()
|
||||
|
||||
void song::addSampleTrack()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
(void) track::create( track::SampleTrack, this );
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -691,9 +689,7 @@ void song::addSampleTrack()
|
||||
|
||||
void song::addAutomationTrack()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
(void) track::create( track::AutomationTrack, this );
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1697,18 +1697,17 @@ void trackOperationsWidget::paintEvent( QPaintEvent * _pe )
|
||||
*/
|
||||
void trackOperationsWidget::cloneTrack()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
m_trackView->getTrack()->clone();
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Clear this track - clears all TCOs from the track */
|
||||
void trackOperationsWidget::clearTrack()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
m_trackView->getTrack()->deleteTCOs();
|
||||
engine::mixer()->unlock();
|
||||
track * t = m_trackView->getTrack();
|
||||
t->lock();
|
||||
t->deleteTCOs();
|
||||
t->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -1839,6 +1838,7 @@ track::track( TrackTypes _type, TrackContainer * _tc ) :
|
||||
*/
|
||||
track::~track()
|
||||
{
|
||||
lock();
|
||||
emit destroyedTrack();
|
||||
|
||||
while( !m_trackContentObjects.isEmpty() )
|
||||
@@ -1847,6 +1847,7 @@ track::~track()
|
||||
}
|
||||
|
||||
m_trackContainer->removeTrack( this );
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -2534,9 +2535,9 @@ void trackView::dropEvent( QDropEvent * _de )
|
||||
// value contains our XML-data so simply create a
|
||||
// DataFile which does the rest for us...
|
||||
DataFile dataFile( value.toUtf8() );
|
||||
engine::mixer()->lock();
|
||||
m_track->lock();
|
||||
m_track->restoreState( dataFile.content().firstChild().toElement() );
|
||||
engine::mixer()->unlock();
|
||||
m_track->unlock();
|
||||
_de->accept();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ InstrumentTrack::~InstrumentTrack()
|
||||
void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, NotePlayHandle* n )
|
||||
{
|
||||
// we must not play the sound if this InstrumentTrack is muted...
|
||||
if( isMuted() || ( n && n->isBbTrackMuted() ) )
|
||||
if( isMuted() || ( n && n->isBbTrackMuted() ) || ! m_instrument )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -275,9 +275,9 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti
|
||||
if( event.velocity() > 0 )
|
||||
{
|
||||
NotePlayHandle* nph;
|
||||
m_notesMutex.lock();
|
||||
if( m_notes[event.key()] == NULL )
|
||||
{
|
||||
m_notesMutex.lock();
|
||||
nph = new NotePlayHandle( this, offset,
|
||||
typeInfo<f_cnt_t>::max() / 2,
|
||||
note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ),
|
||||
@@ -287,24 +287,23 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti
|
||||
if( ! engine::mixer()->addPlayHandle( nph ) )
|
||||
{
|
||||
m_notes[event.key()] = NULL;
|
||||
delete nph;
|
||||
}
|
||||
m_notesMutex.unlock();
|
||||
}
|
||||
m_notesMutex.unlock();
|
||||
eventHandled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case MidiNoteOff:
|
||||
m_notesMutex.lock();
|
||||
if( m_notes[event.key()] != NULL )
|
||||
{
|
||||
m_notesMutex.lock();
|
||||
// do actual note off and remove internal reference to NotePlayHandle (which itself will
|
||||
// be deleted later automatically)
|
||||
m_notes[event.key()]->noteOff( offset );
|
||||
m_notes[event.key()] = NULL;
|
||||
m_notesMutex.unlock();
|
||||
}
|
||||
m_notesMutex.unlock();
|
||||
eventHandled = true;
|
||||
break;
|
||||
|
||||
@@ -392,6 +391,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t
|
||||
switch( event.type() )
|
||||
{
|
||||
case MidiNoteOn:
|
||||
m_midiNotesMutex.lock();
|
||||
m_piano.setKeyState( event.key(), true ); // event.key() = original key
|
||||
|
||||
if( key >= 0 && key < NumKeys )
|
||||
@@ -402,19 +402,20 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t
|
||||
}
|
||||
++m_runningMidiNotes[key];
|
||||
m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time, offset );
|
||||
|
||||
emit newNote();
|
||||
}
|
||||
m_midiNotesMutex.unlock();
|
||||
break;
|
||||
|
||||
case MidiNoteOff:
|
||||
m_midiNotesMutex.lock();
|
||||
m_piano.setKeyState( event.key(), false ); // event.key() = original key
|
||||
|
||||
if( key >= 0 && key < NumKeys && --m_runningMidiNotes[key] <= 0 )
|
||||
{
|
||||
m_runningMidiNotes[key] = qMax( 0, m_runningMidiNotes[key] );
|
||||
m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset );
|
||||
}
|
||||
m_midiNotesMutex.unlock();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -432,18 +433,20 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t
|
||||
void InstrumentTrack::silenceAllNotes( bool removeIPH )
|
||||
{
|
||||
m_notesMutex.lock();
|
||||
m_midiNotesMutex.lock();
|
||||
for( int i = 0; i < NumKeys; ++i )
|
||||
{
|
||||
m_notes[i] = NULL;
|
||||
m_runningMidiNotes[i] = 0;
|
||||
}
|
||||
m_notesMutex.unlock();
|
||||
m_midiNotesMutex.unlock();
|
||||
|
||||
engine::mixer()->lock();
|
||||
lock();
|
||||
// invalidate all NotePlayHandles linked to this track
|
||||
m_processHandles.clear();
|
||||
engine::mixer()->removePlayHandles( this, removeIPH );
|
||||
engine::mixer()->unlock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -532,13 +535,13 @@ void InstrumentTrack::setName( const QString & _new_name )
|
||||
|
||||
void InstrumentTrack::updateBaseNote()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
for( NotePlayHandleList::Iterator it = m_processHandles.begin();
|
||||
it != m_processHandles.end(); ++it )
|
||||
{
|
||||
( *it )->lock();
|
||||
( *it )->updateFrequency();
|
||||
( *it )->unlock();
|
||||
}
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -590,6 +593,10 @@ void InstrumentTrack::removeMidiPortNode( DataFile & _dataFile )
|
||||
bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames,
|
||||
const f_cnt_t _offset, int _tco_num )
|
||||
{
|
||||
if( ! tryLock() || ! m_instrument )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const float frames_per_tick = engine::framesPerTick();
|
||||
|
||||
tcoVector tcos;
|
||||
@@ -615,6 +622,7 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames,
|
||||
|
||||
if ( tcos.size() == 0 )
|
||||
{
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -678,6 +686,7 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames,
|
||||
++nit;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
return played_a_note;
|
||||
}
|
||||
|
||||
@@ -731,7 +740,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement
|
||||
{
|
||||
silenceAllNotes( true );
|
||||
|
||||
engine::mixer()->lock();
|
||||
lock();
|
||||
|
||||
m_volumeModel.loadSettings( thisElement, "vol" );
|
||||
m_panningModel.loadSettings( thisElement, "pan" );
|
||||
@@ -797,7 +806,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
engine::mixer()->unlock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -807,10 +816,10 @@ Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name )
|
||||
{
|
||||
silenceAllNotes( true );
|
||||
|
||||
engine::mixer()->lock();
|
||||
lock();
|
||||
delete m_instrument;
|
||||
m_instrument = Instrument::instantiate( _plugin_name, this );
|
||||
engine::mixer()->unlock();
|
||||
unlock();
|
||||
|
||||
setName( m_instrument->displayName() );
|
||||
emit instrumentChanged();
|
||||
|
||||
@@ -174,6 +174,7 @@ note * pattern::addNote( const note & _new_note, const bool _quant_pos )
|
||||
new_note->quantizePos( engine::pianoRoll()->quantization() );
|
||||
}
|
||||
|
||||
instrumentTrack()->lock();
|
||||
if( m_notes.size() == 0 || m_notes.back()->pos() <= new_note->pos() )
|
||||
{
|
||||
m_notes.push_back( new_note );
|
||||
@@ -196,6 +197,7 @@ note * pattern::addNote( const note & _new_note, const bool _quant_pos )
|
||||
|
||||
m_notes.insert( it, new_note );
|
||||
}
|
||||
instrumentTrack()->unlock();
|
||||
|
||||
checkType();
|
||||
changeLength( length() );
|
||||
@@ -212,7 +214,7 @@ note * pattern::addNote( const note & _new_note, const bool _quant_pos )
|
||||
|
||||
void pattern::removeNote( const note * _note_to_del )
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
instrumentTrack()->lock();
|
||||
NoteVector::Iterator it = m_notes.begin();
|
||||
while( it != m_notes.end() )
|
||||
{
|
||||
@@ -224,7 +226,7 @@ void pattern::removeNote( const note * _note_to_del )
|
||||
}
|
||||
++it;
|
||||
}
|
||||
engine::mixer()->unlock();
|
||||
instrumentTrack()->unlock();
|
||||
|
||||
checkType();
|
||||
changeLength( length() );
|
||||
@@ -274,14 +276,14 @@ void pattern::rearrangeAllNotes()
|
||||
|
||||
void pattern::clearNotes()
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
instrumentTrack()->lock();
|
||||
for( NoteVector::Iterator it = m_notes.begin(); it != m_notes.end();
|
||||
++it )
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_notes.clear();
|
||||
engine::mixer()->unlock();
|
||||
instrumentTrack()->unlock();
|
||||
|
||||
checkType();
|
||||
emit dataChanged();
|
||||
|
||||
Reference in New Issue
Block a user