From 45c4b7b824de19fbdc3bbbc3907dd6bb81151483 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 Sep 2009 17:53:59 -0700 Subject: [PATCH] Mixer sends work in the backend The backend code of mixer uses mixer sends to compute effects. --- include/FxMixer.h | 20 +++++- src/core/FxMixer.cpp | 147 +++++++++++++++++++++++++++++++------------ src/core/mixer.cpp | 27 ++------ 3 files changed, 128 insertions(+), 66 deletions(-) diff --git a/include/FxMixer.h b/include/FxMixer.h index 2a6bd84e0..12d4af42a 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -40,8 +40,10 @@ struct FxChannel ~FxChannel(); EffectChain m_fxChain; - bool m_used; + + // set to true if any effect in the channel is enabled and running bool m_stillRunning; + float m_peakLeft; float m_peakRight; sampleFrame * m_buffer; @@ -50,6 +52,11 @@ struct FxChannel QString m_name; QMutex m_lock; + // pointers to other channels that this one sends to + QVector m_sends; + + // pointers to other channels that send to this one + QVector m_receives; } ; @@ -86,11 +93,20 @@ public: return NULL; } + // make the output of channel fromChannel go to the input of channel toChannel + void createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); + + // delete the connection made by createChannelSend + void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); + + // does fromChannel send its output to the input of toChannel? + bool channelSendsTo(fx_ch_t fromChannel, fx_ch_t toChannel); + + private: FxChannel * m_fxChannels[NumFxChannels+1]; // +1 = master - friend class mixerWorkerThread; friend class FxMixerView; diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index c7cfff902..ce8351cad 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -33,7 +33,6 @@ FxChannel::FxChannel( Model * _parent ) : m_fxChain( NULL ), - m_used( false ), m_stillRunning( false ), m_peakLeft( 0.0f ), m_peakRight( 0.0f ), @@ -64,10 +63,19 @@ FxMixer::FxMixer() : JournallingObject(), Model( NULL ) { - for( int i = 0; i < NumFxChannels+1; ++i ) + // create master channel + m_fxChannels[0] = new FxChannel(this); + + // create the rest of the channels + for( int i = 1; i < NumFxChannels+1; ++i ) { + // create new channel m_fxChannels[i] = new FxChannel( this ); + + // send the channel into master + createChannelSend(i, 0); } + // reset name etc. clear(); } @@ -85,6 +93,64 @@ FxMixer::~FxMixer() +void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) +{ + // first make sure the send doesn't already exist + if( ! channelSendsTo(fromChannel, toChannel) ) + { + // add to from's sends + m_fxChannels[fromChannel]->m_sends.push_back(toChannel); + + // add to to's receives + m_fxChannels[toChannel]->m_receives.push_back(fromChannel); + } +} + + + +// delete the connection made by createChannelSend +void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) +{ + // delete the send + FxChannel * from = m_fxChannels[fromChannel]; + FxChannel * to = m_fxChannels[toChannel]; + + // find and delete the send entry + for(int i=0; im_sends.size(); ++i) { + if( from->m_sends[i] == toChannel ) + { + // delete this index + from->m_sends.remove(i); + break; + } + } + + // find and delete the receive entry + for(int i=0; im_receives.size(); ++i) + { + if( to->m_receives[i] == fromChannel ) + { + // delete this index + to->m_receives.remove(i); + break; + } + } +} + + + +// does fromChannel send its output to the input of toChannel? +bool FxMixer::channelSendsTo(fx_ch_t fromChannel, fx_ch_t toChannel) +{ + FxChannel * from = m_fxChannels[fromChannel]; + for(int i=0; im_sends.size(); ++i){ + if( from->m_sends[i] == toChannel ) + return true; + } + return false; +} + + void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) { @@ -93,7 +159,6 @@ void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) m_fxChannels[_ch]->m_lock.lock(); CPU::bufMix( m_fxChannels[_ch]->m_buffer, _buf, engine::getMixer()->framesPerPeriod() ); - m_fxChannels[_ch]->m_used = true; m_fxChannels[_ch]->m_lock.unlock(); } } @@ -103,32 +168,49 @@ void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) void FxMixer::processChannel( fx_ch_t _ch, sampleFrame * _buf ) { - if( m_fxChannels[_ch]->m_muteModel.value() == false && - ( m_fxChannels[_ch]->m_used || - m_fxChannels[_ch]->m_stillRunning || - _ch == 0 ) ) + const fpp_t fpp = engine::getMixer()->framesPerPeriod(); + FxChannel * thisCh = m_fxChannels[_ch]; + if( ! thisCh->m_muteModel.value() ) { + // do mixer sends. loop through the channels that send to this one + for( int i = 0; i < thisCh->m_receives.size(); ++i) + { + fx_ch_t senderIndex = thisCh->m_receives[i]; + FxChannel * sender = m_fxChannels[senderIndex]; + + // compute the sending channel + processChannel( senderIndex ); + + // mix it with this one + sampleFrame * ch_buf = sender->m_buffer; + const float v = sender->m_volumeModel.value(); + for( f_cnt_t f = 0; f < fpp; ++f ) + { + _buf[f][0] += ch_buf[f][0] * v; + _buf[f][1] += ch_buf[f][1] * v; + } + engine::getMixer()->clearAudioBuffer( ch_buf, + engine::getMixer()->framesPerPeriod() ); + } + + if( _buf == NULL ) { - _buf = m_fxChannels[_ch]->m_buffer; + _buf = thisCh->m_buffer; } - const fpp_t f = engine::getMixer()->framesPerPeriod(); - m_fxChannels[_ch]->m_fxChain.startRunning(); - m_fxChannels[_ch]->m_stillRunning = - m_fxChannels[_ch]->m_fxChain.processAudioBuffer( - _buf, f ); - m_fxChannels[_ch]->m_peakLeft = - engine::getMixer()->peakValueLeft( _buf, f ) * - m_fxChannels[_ch]->m_volumeModel.value(); - m_fxChannels[_ch]->m_peakRight = - engine::getMixer()->peakValueRight( _buf, f ) * - m_fxChannels[_ch]->m_volumeModel.value(); - m_fxChannels[_ch]->m_used = true; + const float v = thisCh->m_volumeModel.value(); + + thisCh->m_fxChain.startRunning(); + thisCh->m_stillRunning = thisCh-> + m_fxChain.processAudioBuffer( _buf, fpp); + thisCh->m_peakLeft = + engine::getMixer()->peakValueLeft( _buf, fpp ) * v; + thisCh->m_peakRight = + engine::getMixer()->peakValueRight( _buf, fpp ) * v; } else { - m_fxChannels[_ch]->m_peakLeft = - m_fxChannels[_ch]->m_peakRight = 0.0f; + thisCh->m_peakLeft = thisCh->m_peakRight = 0.0f; } } @@ -149,31 +231,14 @@ void FxMixer::masterMix( sampleFrame * _buf ) const int fpp = engine::getMixer()->framesPerPeriod(); memcpy( _buf, m_fxChannels[0]->m_buffer, sizeof( sampleFrame ) * fpp ); - for( int i = 1; i < NumFxChannels+1; ++i ) - { - if( m_fxChannels[i]->m_used ) - { - sampleFrame * ch_buf = m_fxChannels[i]->m_buffer; - const float v = m_fxChannels[i]->m_volumeModel.value(); - for( f_cnt_t f = 0; f < fpp; ++f ) - { - _buf[f][0] += ch_buf[f][0] * v; - _buf[f][1] += ch_buf[f][1] * v; - } - engine::getMixer()->clearAudioBuffer( ch_buf, - engine::getMixer()->framesPerPeriod() ); - m_fxChannels[i]->m_used = false; - } - } - processChannel( 0, _buf ); - if( m_fxChannels[0]->m_muteModel.value() ) + /*if( m_fxChannels[0]->m_muteModel.value() ) { engine::getMixer()->clearAudioBuffer( _buf, engine::getMixer()->framesPerPeriod() ); return; - } + }*/ const float v = m_fxChannels[0]->m_volumeModel.value(); for( f_cnt_t f = 0; f < engine::getMixer()->framesPerPeriod(); ++f ) diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index b82d6886f..35fdb62cd 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -143,16 +143,6 @@ public: private: virtual void run() { -#if 0 -#ifdef LMMS_BUILD_LINUX -#ifdef LMMS_HAVE_PTHREAD_H - cpu_set_t mask; - CPU_ZERO( &mask ); - CPU_SET( m_workerNum, &mask ); - pthread_setaffinity_np( pthread_self(), sizeof( mask ), &mask ); -#endif -#endif -#endif QMutex m; while( m_quit == false ) { @@ -618,15 +608,17 @@ sampleFrameA * mixer::renderNextBuffer() // STAGE 3: process effects in FX mixer - FILL_JOB_QUEUE_PARAM(QVector,__fx_channel_jobs, + /*FILL_JOB_QUEUE_PARAM(QVector,__fx_channel_jobs, MixerWorkerThread::EffectChannel,1); START_JOBS(); - WAIT_FOR_JOBS(); + WAIT_FOR_JOBS();*/ // STAGE 4: do master mix in FX mixer engine::fxMixer()->masterMix( m_writeBuf ); + WAIT_FOR_JOBS(); + unlock(); @@ -1137,17 +1129,6 @@ void mixer::fifoWriter::finish() void mixer::fifoWriter::run() { -#if 0 -#ifdef LMMS_BUILD_LINUX -#ifdef LMMS_HAVE_PTHREAD_H - cpu_set_t mask; - CPU_ZERO( &mask ); - CPU_SET( 0, &mask ); - pthread_setaffinity_np( pthread_self(), sizeof( mask ), &mask ); -#endif -#endif -#endif - const fpp_t frames = m_mixer->framesPerPeriod(); while( m_writing ) {