|
|
|
|
@@ -211,9 +211,11 @@ FxMixer::~FxMixer()
|
|
|
|
|
{
|
|
|
|
|
deleteChannelSend( m_fxRoutes.first() );
|
|
|
|
|
}
|
|
|
|
|
for( int i = 0; i < m_fxChannels.size(); ++i )
|
|
|
|
|
while( m_fxChannels.size() )
|
|
|
|
|
{
|
|
|
|
|
delete m_fxChannels[i];
|
|
|
|
|
FxChannel * f = m_fxChannels[m_fxChannels.size() - 1];
|
|
|
|
|
m_fxChannels.pop_back();
|
|
|
|
|
delete f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -288,8 +290,6 @@ void FxMixer::deleteChannel( int index )
|
|
|
|
|
// channel deletion is performed between mixer rounds
|
|
|
|
|
Engine::mixer()->requestChangeInModel();
|
|
|
|
|
|
|
|
|
|
FxChannel * ch = m_fxChannels[index];
|
|
|
|
|
|
|
|
|
|
// go through every instrument and adjust for the channel index change
|
|
|
|
|
TrackContainer::TrackList tracks;
|
|
|
|
|
tracks += Engine::getSong()->tracks();
|
|
|
|
|
@@ -315,6 +315,8 @@ void FxMixer::deleteChannel( int index )
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FxChannel * ch = m_fxChannels[index];
|
|
|
|
|
|
|
|
|
|
// delete all of this channel's sends and receives
|
|
|
|
|
while( ! ch->m_sends.isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
@@ -326,8 +328,8 @@ void FxMixer::deleteChannel( int index )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// actually delete the channel
|
|
|
|
|
delete m_fxChannels[index];
|
|
|
|
|
m_fxChannels.remove(index);
|
|
|
|
|
delete ch;
|
|
|
|
|
|
|
|
|
|
for( int i = index; i < m_fxChannels.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
@@ -434,7 +436,7 @@ FxRoute * FxMixer::createRoute( FxChannel * from, FxChannel * to, float amount )
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
m_sendsMutex.lock();
|
|
|
|
|
Engine::mixer()->requestChangeInModel();
|
|
|
|
|
FxRoute * route = new FxRoute( from, to, amount );
|
|
|
|
|
|
|
|
|
|
// add us to from's sends
|
|
|
|
|
@@ -445,7 +447,7 @@ FxRoute * FxMixer::createRoute( FxChannel * from, FxChannel * to, float amount )
|
|
|
|
|
|
|
|
|
|
// add us to fxmixer's list
|
|
|
|
|
Engine::fxMixer()->m_fxRoutes.append( route );
|
|
|
|
|
m_sendsMutex.unlock();
|
|
|
|
|
Engine::mixer()->doneChangeInModel();
|
|
|
|
|
|
|
|
|
|
return route;
|
|
|
|
|
}
|
|
|
|
|
@@ -472,7 +474,7 @@ void FxMixer::deleteChannelSend( fx_ch_t fromChannel, fx_ch_t toChannel )
|
|
|
|
|
|
|
|
|
|
void FxMixer::deleteChannelSend( FxRoute * route )
|
|
|
|
|
{
|
|
|
|
|
m_sendsMutex.lock();
|
|
|
|
|
Engine::mixer()->requestChangeInModel();
|
|
|
|
|
// remove us from from's sends
|
|
|
|
|
route->sender()->m_sends.remove( route->sender()->m_sends.indexOf( route ) );
|
|
|
|
|
// remove us from to's receives
|
|
|
|
|
@@ -480,7 +482,7 @@ void FxMixer::deleteChannelSend( FxRoute * route )
|
|
|
|
|
// remove us from fxmixer's list
|
|
|
|
|
Engine::fxMixer()->m_fxRoutes.remove( Engine::fxMixer()->m_fxRoutes.indexOf( route ) );
|
|
|
|
|
delete route;
|
|
|
|
|
m_sendsMutex.unlock();
|
|
|
|
|
Engine::mixer()->doneChangeInModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -571,33 +573,46 @@ void FxMixer::masterMix( sampleFrame * _buf )
|
|
|
|
|
{
|
|
|
|
|
const int fpp = Engine::mixer()->framesPerPeriod();
|
|
|
|
|
|
|
|
|
|
if( m_sendsMutex.tryLock() )
|
|
|
|
|
// add the channels that have no dependencies (no incoming senders, ie.
|
|
|
|
|
// no receives) to the jobqueue. The channels that have receives get
|
|
|
|
|
// added when their senders get processed, which is detected by
|
|
|
|
|
// dependency counting.
|
|
|
|
|
// also instantly add all muted channels as they don't need to care
|
|
|
|
|
// about their senders, and can just increment the deps of their
|
|
|
|
|
// recipients right away.
|
|
|
|
|
MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic );
|
|
|
|
|
for( FxChannel * ch : m_fxChannels )
|
|
|
|
|
{
|
|
|
|
|
// add the channels that have no dependencies (no incoming senders, ie. no receives)
|
|
|
|
|
// to the jobqueue. The channels that have receives get added when their senders get processed, which
|
|
|
|
|
// is detected by dependency counting.
|
|
|
|
|
// also instantly add all muted channels as they don't need to care about their senders, and can just increment the deps of
|
|
|
|
|
// their recipients right away.
|
|
|
|
|
MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic );
|
|
|
|
|
ch->m_muted = ch->m_muteModel.value();
|
|
|
|
|
if( ch->m_muted ) // instantly "process" muted channels
|
|
|
|
|
{
|
|
|
|
|
ch->processed();
|
|
|
|
|
ch->done();
|
|
|
|
|
}
|
|
|
|
|
else if( ch->m_receives.size() == 0 )
|
|
|
|
|
{
|
|
|
|
|
ch->m_queued = true;
|
|
|
|
|
MixerWorkerThread::addJob( ch );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
for( FxChannel * ch : m_fxChannels )
|
|
|
|
|
{
|
|
|
|
|
ch->m_muted = ch->m_muteModel.value();
|
|
|
|
|
if( ch->m_muted ) // instantly "process" muted channels
|
|
|
|
|
int s = ch->state();
|
|
|
|
|
if( s == ThreadableJob::Queued
|
|
|
|
|
|| s == ThreadableJob::InProgress )
|
|
|
|
|
{
|
|
|
|
|
ch->processed();
|
|
|
|
|
ch->done();
|
|
|
|
|
}
|
|
|
|
|
else if( ch->m_receives.size() == 0 )
|
|
|
|
|
{
|
|
|
|
|
ch->m_queued = true;
|
|
|
|
|
MixerWorkerThread::addJob( ch );
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
|
|
|
|
if( !found )
|
|
|
|
|
{
|
|
|
|
|
MixerWorkerThread::startAndWaitForJobs();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
m_sendsMutex.unlock();
|
|
|
|
|
MixerWorkerThread::startAndWaitForJobs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handle sample-exact data in master volume fader
|
|
|
|
|
|