Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/engine/enginemaster.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           enginemaster.cpp  -  description
00003                              -------------------
00004     begin                : Sun Apr 28 2002
00005     copyright            : (C) 2002 by
00006     email                :
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 *                                                                         *
00011 *   This program is free software; you can redistribute it and/or modify  *
00012 *   it under the terms of the GNU General Public License as published by  *
00013 *   the Free Software Foundation; either version 2 of the License, or     *
00014 *   (at your option) any later version.                                   *
00015 *                                                                         *
00016 ***************************************************************************/
00017 
00018 #include <QDebug>
00019 #include <QList>
00020 #include <QPair>
00021 
00022 #include "controlpushbutton.h"
00023 #include "configobject.h"
00024 #include "controllogpotmeter.h"
00025 #include "controlpotmeter.h"
00026 #include "enginebuffer.h"
00027 #include "enginemaster.h"
00028 #include "engine/engineworkerscheduler.h"
00029 #include "enginebuffer.h"
00030 #include "enginechannel.h"
00031 #include "engineclipping.h"
00032 #include "enginevumeter.h"
00033 #include "enginexfader.h"
00034 #include "enginesidechain.h"
00035 #include "engine/syncworker.h"
00036 #include "sampleutil.h"
00037 
00038 #ifdef __LADSPA__
00039 #include "engineladspa.h"
00040 #endif
00041 
00042 
00043 EngineMaster::EngineMaster(ConfigObject<ConfigValue> * _config,
00044                            const char * group) {
00045 
00046     m_pWorkerScheduler = new EngineWorkerScheduler(this);
00047     m_pWorkerScheduler->start();
00048     m_pSyncWorker = new SyncWorker(m_pWorkerScheduler);
00049 
00050     // Master sample rate
00051     m_pMasterSampleRate = new ControlObject(ConfigKey(group, "samplerate"));
00052     m_pMasterSampleRate->set(44100.);
00053 
00054     // Latency control
00055     m_pMasterLatency = new ControlObject(ConfigKey(group, "latency"));
00056 
00057     // Master rate
00058     m_pMasterRate = new ControlPotmeter(ConfigKey(group, "rate"), -1.0, 1.0);
00059 
00060 #ifdef __LADSPA__
00061     // LADSPA
00062     ladspa = new EngineLADSPA();
00063 #endif
00064 
00065     // Crossfader
00066     crossfader = new ControlPotmeter(ConfigKey(group, "crossfader"),-1.,1.);
00067 
00068     // Balance
00069     m_pBalance = new ControlPotmeter(ConfigKey(group, "balance"), -1., 1.);
00070 
00071     // Master volume
00072     m_pMasterVolume = new ControlLogpotmeter(ConfigKey(group, "volume"), 5.);
00073 
00074     // Clipping
00075     clipping = new EngineClipping(group);
00076 
00077     // VU meter:
00078     vumeter = new EngineVuMeter(group);
00079 
00080     // Headphone volume
00081     m_pHeadVolume = new ControlLogpotmeter(ConfigKey(group, "headVolume"), 5.);
00082 
00083     // Headphone mix (left/right)
00084     head_mix = new ControlPotmeter(ConfigKey(group, "headMix"),-1.,1.);
00085     head_mix->set(-1.);
00086 
00087     // Headphone Clipping
00088     head_clipping = new EngineClipping("");
00089 
00090     // Allocate buffers
00091     m_pHead = SampleUtil::alloc(MAX_BUFFER_LEN);
00092     m_pMaster = SampleUtil::alloc(MAX_BUFFER_LEN);
00093     memset(m_pHead, 0, sizeof(CSAMPLE) * MAX_BUFFER_LEN);
00094     memset(m_pMaster, 0, sizeof(CSAMPLE) * MAX_BUFFER_LEN);
00095 
00096     //Starts a thread for recording and shoutcast
00097     sidechain = new EngineSideChain(_config);
00098     connect(sidechain, SIGNAL(isRecording(bool)),
00099             this, SIGNAL(isRecording(bool)));
00100     connect(sidechain, SIGNAL(bytesRecorded(int)),
00101             this, SIGNAL(bytesRecorded(int)));
00102 
00103     //X-Fader Setup
00104     xFaderCurve = new ControlPotmeter(
00105         ConfigKey("[Mixer Profile]", "xFaderCurve"), 0., 2.);
00106     xFaderCalibration = new ControlPotmeter(
00107         ConfigKey("[Mixer Profile]", "xFaderCalibration"), -2., 2.);
00108 }
00109 
00110 EngineMaster::~EngineMaster()
00111 {
00112     qDebug() << "in ~EngineMaster()";
00113     delete crossfader;
00114     delete m_pBalance;
00115     delete head_mix;
00116     delete m_pMasterVolume;
00117     delete m_pHeadVolume;
00118     delete clipping;
00119     delete vumeter;
00120     delete head_clipping;
00121     delete sidechain;
00122 
00123     delete xFaderCalibration;
00124     delete xFaderCurve;
00125 
00126     delete m_pMasterSampleRate;
00127     delete m_pMasterLatency;
00128     delete m_pMasterRate;
00129 
00130     SampleUtil::free(m_pHead);
00131     SampleUtil::free(m_pMaster);
00132 
00133     QMutableListIterator<ChannelInfo*> channel_it(m_channels);
00134     while (channel_it.hasNext()) {
00135         ChannelInfo* pChannelInfo = channel_it.next();
00136         channel_it.remove();
00137         SampleUtil::free(pChannelInfo->m_pBuffer);
00138         delete pChannelInfo->m_pChannel;
00139         delete pChannelInfo->m_pVolumeControl;
00140         delete pChannelInfo;
00141     }
00142 
00143     delete m_pWorkerScheduler;
00144     delete m_pSyncWorker;
00145 }
00146 
00147 const CSAMPLE* EngineMaster::getMasterBuffer() const
00148 {
00149     return m_pMaster;
00150 }
00151 
00152 const CSAMPLE* EngineMaster::getHeadphoneBuffer() const
00153 {
00154     return m_pHead;
00155 }
00156 
00157 void EngineMaster::mixChannels(unsigned int channelBitvector, unsigned int maxChannels,
00158                                CSAMPLE* pOutput, unsigned int iBufferSize,
00159                                GainCalculator* pGainCalculator) {
00160     // Common case: 2 decks, 4 samplers, 1 mic
00161     ChannelInfo* pChannel1 = NULL;
00162     ChannelInfo* pChannel2 = NULL;
00163     ChannelInfo* pChannel3 = NULL;
00164     ChannelInfo* pChannel4 = NULL;
00165     ChannelInfo* pChannel5 = NULL;
00166     ChannelInfo* pChannel6 = NULL;
00167     ChannelInfo* pChannel7 = NULL;
00168 
00169     unsigned int totalActive = 0;
00170     for (unsigned int i = 0; i < maxChannels; ++i) {
00171         if ((channelBitvector & (1 << i)) == 0) {
00172             continue;
00173         }
00174 
00175         ++totalActive;
00176 
00177         if (pChannel1 == NULL) {
00178             pChannel1 = m_channels[i];
00179         } else if (pChannel2 == NULL) {
00180             pChannel2 = m_channels[i];
00181         } else if (pChannel3 == NULL) {
00182             pChannel3 = m_channels[i];
00183         } else if (pChannel4 == NULL) {
00184             pChannel4 = m_channels[i];
00185         } else if (pChannel5 == NULL) {
00186             pChannel5 = m_channels[i];
00187         } else if (pChannel6 == NULL) {
00188             pChannel6 = m_channels[i];
00189         } else if (pChannel7 == NULL) {
00190             pChannel7 = m_channels[i];
00191         }
00192     }
00193 
00194     if (totalActive == 0) {
00195         SampleUtil::applyGain(pOutput, 0.0f, iBufferSize);
00196     } else if (totalActive == 1) {
00197         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00198         double gain1 = pGainCalculator->getGain(pChannel1);
00199         SampleUtil::copyWithGain(pOutput,
00200                                  pBuffer1, gain1,
00201                                  iBufferSize);
00202     } else if (totalActive == 2) {
00203         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00204         double gain1 = pGainCalculator->getGain(pChannel1);
00205         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00206         double gain2 = pGainCalculator->getGain(pChannel2);
00207         SampleUtil::copy2WithGain(pOutput,
00208                                   pBuffer1, gain1,
00209                                   pBuffer2, gain2,
00210                                   iBufferSize);
00211     } else if (totalActive == 3) {
00212         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00213         double gain1 = pGainCalculator->getGain(pChannel1);
00214         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00215         double gain2 = pGainCalculator->getGain(pChannel2);
00216         CSAMPLE* pBuffer3 = pChannel3->m_pBuffer;
00217         double gain3 = pGainCalculator->getGain(pChannel3);
00218 
00219         SampleUtil::copy3WithGain(pOutput,
00220                                   pBuffer1, gain1,
00221                                   pBuffer2, gain2,
00222                                   pBuffer3, gain3,
00223                                   iBufferSize);
00224     } else if (totalActive == 4) {
00225         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00226         double gain1 = pGainCalculator->getGain(pChannel1);
00227         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00228         double gain2 = pGainCalculator->getGain(pChannel2);
00229         CSAMPLE* pBuffer3 = pChannel3->m_pBuffer;
00230         double gain3 = pGainCalculator->getGain(pChannel3);
00231         CSAMPLE* pBuffer4 = pChannel4->m_pBuffer;
00232         double gain4 = pGainCalculator->getGain(pChannel4);
00233         SampleUtil::copy4WithGain(pOutput,
00234                                   pBuffer1, gain1,
00235                                   pBuffer2, gain2,
00236                                   pBuffer3, gain3,
00237                                   pBuffer4, gain4,
00238                                   iBufferSize);
00239     } else if (totalActive == 5) {
00240         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00241         double gain1 = pGainCalculator->getGain(pChannel1);
00242         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00243         double gain2 = pGainCalculator->getGain(pChannel2);
00244         CSAMPLE* pBuffer3 = pChannel3->m_pBuffer;
00245         double gain3 = pGainCalculator->getGain(pChannel3);
00246         CSAMPLE* pBuffer4 = pChannel4->m_pBuffer;
00247         double gain4 = pGainCalculator->getGain(pChannel4);
00248         CSAMPLE* pBuffer5 = pChannel5->m_pBuffer;
00249         double gain5 = pGainCalculator->getGain(pChannel5);
00250 
00251         SampleUtil::copy5WithGain(pOutput,
00252                                   pBuffer1, gain1,
00253                                   pBuffer2, gain2,
00254                                   pBuffer3, gain3,
00255                                   pBuffer4, gain4,
00256                                   pBuffer5, gain5,
00257                                   iBufferSize);
00258     } else if (totalActive == 6) {
00259         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00260         double gain1 = pGainCalculator->getGain(pChannel1);
00261         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00262         double gain2 = pGainCalculator->getGain(pChannel2);
00263         CSAMPLE* pBuffer3 = pChannel3->m_pBuffer;
00264         double gain3 = pGainCalculator->getGain(pChannel3);
00265         CSAMPLE* pBuffer4 = pChannel4->m_pBuffer;
00266         double gain4 = pGainCalculator->getGain(pChannel4);
00267         CSAMPLE* pBuffer5 = pChannel5->m_pBuffer;
00268         double gain5 = pGainCalculator->getGain(pChannel5);
00269         CSAMPLE* pBuffer6 = pChannel6->m_pBuffer;
00270         double gain6 = pGainCalculator->getGain(pChannel6);
00271         SampleUtil::copy6WithGain(pOutput,
00272                                   pBuffer1, gain1,
00273                                   pBuffer2, gain2,
00274                                   pBuffer3, gain3,
00275                                   pBuffer4, gain4,
00276                                   pBuffer5, gain5,
00277                                   pBuffer6, gain6,
00278                                   iBufferSize);
00279     } else if (totalActive == 7) {
00280         CSAMPLE* pBuffer1 = pChannel1->m_pBuffer;
00281         double gain1 = pGainCalculator->getGain(pChannel1);
00282         CSAMPLE* pBuffer2 = pChannel2->m_pBuffer;
00283         double gain2 = pGainCalculator->getGain(pChannel2);
00284         CSAMPLE* pBuffer3 = pChannel3->m_pBuffer;
00285         double gain3 = pGainCalculator->getGain(pChannel3);
00286         CSAMPLE* pBuffer4 = pChannel4->m_pBuffer;
00287         double gain4 = pGainCalculator->getGain(pChannel4);
00288         CSAMPLE* pBuffer5 = pChannel5->m_pBuffer;
00289         double gain5 = pGainCalculator->getGain(pChannel5);
00290         CSAMPLE* pBuffer6 = pChannel6->m_pBuffer;
00291         double gain6 = pGainCalculator->getGain(pChannel6);
00292         CSAMPLE* pBuffer7 = pChannel7->m_pBuffer;
00293         double gain7 = pGainCalculator->getGain(pChannel7);
00294         SampleUtil::copy7WithGain(pOutput,
00295                                   pBuffer1, gain1,
00296                                   pBuffer2, gain2,
00297                                   pBuffer3, gain3,
00298                                   pBuffer4, gain4,
00299                                   pBuffer5, gain5,
00300                                   pBuffer6, gain6,
00301                                   pBuffer7, gain7,
00302                                   iBufferSize);
00303     } else {
00304         // Set pOutput to all 0s
00305         SampleUtil::applyGain(pOutput, 0.0f, iBufferSize);
00306 
00307         for (unsigned int i = 0; i < maxChannels; ++i) {
00308             if (channelBitvector & (1 << i)) {
00309                 ChannelInfo* pChannelInfo = m_channels[i];
00310                 CSAMPLE* pBuffer = pChannelInfo->m_pBuffer;
00311                 double gain = pGainCalculator->getGain(pChannelInfo);
00312                 SampleUtil::addWithGain(pOutput, pBuffer, gain, iBufferSize);
00313             }
00314         }
00315     }
00316 }
00317 
00318 void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBufferSize)
00319 {
00320     CSAMPLE **pOutput = (CSAMPLE**)pOut;
00321     Q_UNUSED(pOutput);
00322 
00323     // Prepare each channel for output
00324 
00325     // Bitvector of enabled channels
00326     const unsigned int maxChannels = 32;
00327     unsigned int masterOutput = 0;
00328     unsigned int headphoneOutput = 0;
00329 
00330     // Compute headphone mix
00331     // Head phone left/right mix
00332     float cf_val = head_mix->get();
00333     float chead_gain = 0.5*(-cf_val+1.);
00334     float cmaster_gain = 0.5*(cf_val+1.);
00335     // qDebug() << "head val " << cf_val << ", head " << chead_gain
00336     //          << ", master " << cmaster_gain;
00337 
00338     QList<ChannelInfo*>::iterator it = m_channels.begin();
00339     for (unsigned int channel_number = 0;
00340          it != m_channels.end(); ++it, ++channel_number) {
00341         ChannelInfo* pChannelInfo = *it;
00342         EngineChannel* pChannel = pChannelInfo->m_pChannel;
00343 
00344         if (!pChannel->isActive()) {
00345             continue;
00346         }
00347 
00348         bool needsProcessing = false;
00349         if (pChannel->isMaster()) {
00350             masterOutput |= (1 << channel_number);
00351             needsProcessing = true;
00352         }
00353 
00354         // If the channel is enabled for previewing in headphones, copy it
00355         // over to the headphone buffer
00356         if (pChannel->isPFL()) {
00357             headphoneOutput |= (1 << channel_number);
00358             needsProcessing = true;
00359         }
00360 
00361         // Process the buffer if necessary
00362         if (needsProcessing) {
00363             pChannel->process(NULL, pChannelInfo->m_pBuffer, iBufferSize);
00364         }
00365     }
00366 
00367     // Mix all the enabled headphone channels together.
00368     m_headphoneGain.setGain(chead_gain);
00369     mixChannels(headphoneOutput, maxChannels, m_pHead, iBufferSize, &m_headphoneGain);
00370 
00371     // Calculate the crossfader gains for left and right side of the crossfader
00372     float c1_gain, c2_gain;
00373     EngineXfader::getXfadeGains(c1_gain, c2_gain,
00374                                 crossfader->get(), xFaderCurve->get(),
00375                                 xFaderCalibration->get());
00376 
00377     // Now set the gains for overall volume and the left, center, right gains.
00378     m_masterGain.setGains(m_pMasterVolume->get(), c1_gain, 1.0, c2_gain);
00379 
00380     // Perform the master mix
00381     mixChannels(masterOutput, maxChannels, m_pMaster, iBufferSize, &m_masterGain);
00382 
00383 #ifdef __LADSPA__
00384     // LADPSA master effects
00385     ladspa->process(m_pMaster, m_pMaster, iBufferSize);
00386 #endif
00387 
00388     // Clipping
00389     clipping->process(m_pMaster, m_pMaster, iBufferSize);
00390 
00391     // Balance values
00392     float balright = 1.;
00393     float balleft = 1.;
00394     float bal = m_pBalance->get();
00395     if (bal>0.)
00396         balleft -= bal;
00397     else if (bal<0.)
00398         balright += bal;
00399 
00400     // Perform balancing on main out
00401     SampleUtil::applyAlternatingGain(m_pMaster, balleft, balright, iBufferSize);
00402 
00403     // Update VU meter (it does not return anything). Needs to be here so that
00404     // master balance is reflected in the VU meter.
00405     if (vumeter != NULL)
00406         vumeter->process(m_pMaster, m_pMaster, iBufferSize);
00407 
00408     //Submit master samples to the side chain to do shoutcasting, recording,
00409     //etc.  (cpu intensive non-realtime tasks)
00410     sidechain->submitSamples(m_pMaster, iBufferSize);
00411 
00412     // Add master to headphone with appropriate gain
00413     SampleUtil::addWithGain(m_pHead, m_pMaster, cmaster_gain, iBufferSize);
00414 
00415     // Head volume and clipping
00416     SampleUtil::applyGain(m_pHead, m_pHeadVolume->get(), iBufferSize);
00417     head_clipping->process(m_pHead, m_pHead, iBufferSize);
00418 
00419     //Master/headphones interleaving is now done in
00420     //SoundManager::requestBuffer() - Albert Nov 18/07
00421 
00422     // Schedule a ControlObject sync
00423     m_pSyncWorker->schedule();
00424 
00425     // We're close to the end of the callback. Wake up the engine worker
00426     // scheduler so that it runs the workers.
00427     m_pWorkerScheduler->runWorkers();
00428 }
00429 
00430 void EngineMaster::addChannel(EngineChannel* pChannel) {
00431     ChannelInfo* pChannelInfo = new ChannelInfo();
00432     pChannelInfo->m_pChannel = pChannel;
00433     pChannelInfo->m_pVolumeControl = new ControlLogpotmeter(
00434         ConfigKey(pChannel->getGroup(), "volume"), 1.0);
00435     pChannelInfo->m_pBuffer = SampleUtil::alloc(MAX_BUFFER_LEN);
00436     SampleUtil::applyGain(pChannelInfo->m_pBuffer, 0, MAX_BUFFER_LEN);
00437     m_channels.push_back(pChannelInfo);
00438 
00439     EngineBuffer* pBuffer = pChannelInfo->m_pChannel->getEngineBuffer();
00440     if (pBuffer != NULL) {
00441         pBuffer->bindWorkers(m_pWorkerScheduler);
00442     }
00443 
00444     // TODO(XXX) WARNING HUGE HACK ALERT In the case of 2-decks, this code hooks
00445     // the two EngineBuffers together so they can beat-sync off of each other.
00446     // rryan 6/2010
00447     bool isDeck1 = pChannel->getGroup() == "[Channel1]";
00448     bool isDeck2 = pChannel->getGroup() == "[Channel2]";
00449     if (isDeck1 || isDeck2) {
00450         QString otherGroup = isDeck1 ? "[Channel2]" : "[Channel1]";
00451         for (QList<ChannelInfo*>::const_iterator i = m_channels.constBegin();
00452              i != m_channels.constEnd(); ++i) {
00453             const ChannelInfo* pChannelInfo = *i;
00454             if (pChannelInfo->m_pChannel->getGroup() == otherGroup) {
00455                 EngineBuffer *pBuffer1 = pChannel->getEngineBuffer();
00456                 EngineBuffer *pBuffer2 = pChannelInfo->m_pChannel->getEngineBuffer();
00457                 if (pBuffer1 != NULL && pBuffer2 != NULL) {
00458                     pBuffer1->setOtherEngineBuffer(pBuffer2);
00459                     pBuffer2->setOtherEngineBuffer(pBuffer1);
00460                 }
00461             }
00462         }
00463     }
00464 }
00465 
00466 const CSAMPLE* EngineMaster::getDeckBuffer(unsigned int i) const {
00467     return getChannelBuffer(QString("[Channel%1]").arg(i+1));
00468 }
00469 
00470 const CSAMPLE* EngineMaster::getChannelBuffer(QString group) const {
00471     for (QList<ChannelInfo*>::const_iterator i = m_channels.constBegin();
00472          i != m_channels.constEnd(); ++i) {
00473         const ChannelInfo* pChannelInfo = *i;
00474         if (pChannelInfo->m_pChannel->getGroup() == group) {
00475             return pChannelInfo->m_pBuffer;
00476         }
00477     }
00478     return NULL;
00479 }
00480 
00481 const CSAMPLE* EngineMaster::buffer(AudioOutput output) const {
00482     switch (output.getType()) {
00483     case AudioOutput::MASTER:
00484         return getMasterBuffer();
00485         break;
00486     case AudioOutput::HEADPHONES:
00487         return getHeadphoneBuffer();
00488         break;
00489     case AudioOutput::DECK:
00490         return getDeckBuffer(output.getIndex());
00491         break;
00492     default:
00493         return NULL;
00494     }
00495 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines