=== modified file 'mixxx/build/depends.py' --- mixxx/build/depends.py 2011-04-28 21:54:22 +0000 +++ mixxx/build/depends.py 2011-04-30 20:14:41 +0000 @@ -362,7 +362,7 @@ "engine/enginepregain.cpp", "engine/enginechannel.cpp", "engine/enginemaster.cpp", - "engine/enginedelay.cpp", + "engine/enginepfldelay.cpp", "engine/engineflanger.cpp", "engine/enginevumeter.cpp", "engine/enginevinylsoundemu.cpp", === modified file 'mixxx/src/controlvaluedelegate.cpp' --- mixxx/src/controlvaluedelegate.cpp 2011-04-04 15:19:33 +0000 +++ mixxx/src/controlvaluedelegate.cpp 2011-04-30 19:19:52 +0000 @@ -131,6 +131,7 @@ m_masterControlValues.append("balance"); m_masterControlValues.append("crossfader"); m_masterControlValues.append("volume"); + m_masterControlValues.append("pfl_delay"); } if (m_playlistControlValues.isEmpty()) { === modified file 'mixxx/src/dlgprefsound.cpp' --- mixxx/src/dlgprefsound.cpp 2011-04-17 04:16:00 +0000 +++ mixxx/src/dlgprefsound.cpp 2011-04-30 20:07:31 +0000 @@ -59,12 +59,17 @@ sampleRateComboBox->addItem(QString(tr("%1 Hz")).arg(srate), srate); } } + + m_pflDelay = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey("[Master]", "pfl_delay"))); + connect(sampleRateComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sampleRateChanged(int))); connect(sampleRateComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLatencies(int))); connect(latencyComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(latencyChanged(int))); + connect(pflDelaySlider, SIGNAL(valueChanged(int)), + this, SLOT(pflDelayChanged(int))); initializePaths(); loadSettings(); @@ -341,6 +346,16 @@ } /** + * Slot called when the headphone delay slider is changed to update the + * delay in the config. + */ +void DlgPrefSound::pflDelayChanged(int delay_fraction) +{ + float fraction = (float)delay_fraction / 1000.0; + m_pflDelay->slotSet(fraction); +} + +/** * Slot called whenever the selected sample rate is changed. Populates the * latency input box with MAX_LATENCY values, starting at 1ms, representing * a number of frames per buffer, which will always be a power of 2 (so the === modified file 'mixxx/src/dlgprefsound.h' --- mixxx/src/dlgprefsound.h 2011-04-08 06:04:27 +0000 +++ mixxx/src/dlgprefsound.h 2011-04-30 20:04:26 +0000 @@ -19,6 +19,7 @@ #include #include "ui_dlgprefsounddlg.h" #include "configobject.h" +#include "controlobjectthreadmain.h" #include "soundmanagerconfig.h" class SoundManager; @@ -61,6 +62,7 @@ SoundManager *m_pSoundManager; PlayerManager *m_pPlayerManager; ConfigObject *m_pConfig; + ControlObjectThreadMain* m_pflDelay; QList m_inputDevices; QList m_outputDevices; bool m_settingsModified; @@ -75,6 +77,7 @@ void updateAPIs(); void sampleRateChanged(int index); void latencyChanged(int index); + void pflDelayChanged(int delay_fraction); void updateLatencies(int sampleRateIndex); void refreshDevices(); void settingChanged(); === modified file 'mixxx/src/dlgprefsounddlg.ui' --- mixxx/src/dlgprefsounddlg.ui 2010-12-29 01:52:27 +0000 +++ mixxx/src/dlgprefsounddlg.ui 2011-04-30 19:46:19 +0000 @@ -55,6 +55,39 @@ + + + + + + false + + + Headphone Delay + + + + + + + + 0 + 0 + + + + 0 + + + 1000 + + + Qt::Horizontal + + + + + @@ -102,8 +135,8 @@ 0 0 - 496 - 271 + 480 + 209 @@ -150,8 +183,8 @@ 0 0 - 496 - 271 + 64 + 16 === modified file 'mixxx/src/engine/enginemaster.cpp' --- mixxx/src/engine/enginemaster.cpp 2011-04-13 02:58:05 +0000 +++ mixxx/src/engine/enginemaster.cpp 2011-04-30 20:12:00 +0000 @@ -32,6 +32,7 @@ #include "enginevumeter.h" #include "enginexfader.h" #include "enginesidechain.h" +#include "enginepfldelay.h" #include "sampleutil.h" #ifdef __LADSPA__ @@ -41,7 +42,6 @@ EngineMaster::EngineMaster(ConfigObject * _config, const char * group) { - m_pWorkerScheduler = new EngineWorkerScheduler(this); // Master sample rate @@ -83,6 +83,8 @@ // Headphone Clipping head_clipping = new EngineClipping(""); + + m_pHeadDelay = new EnginePflDelay(); // Allocate buffers m_pHead = SampleUtil::alloc(MAX_BUFFER_LEN); @@ -357,7 +359,7 @@ // Mix all the enabled headphone channels together. m_headphoneGain.setGain(chead_gain); mixChannels(headphoneOutput, maxChannels, m_pHead, iBufferSize, &m_headphoneGain); - + // Calculate the crossfader gains for left and right side of the crossfader float c1_gain, c2_gain; EngineXfader::getXfadeGains(c1_gain, c2_gain, @@ -405,6 +407,9 @@ // Head volume and clipping SampleUtil::applyGain(m_pHead, m_pHeadVolume->get(), iBufferSize); head_clipping->process(m_pHead, m_pHead, iBufferSize); + + //delay the headphone sound by the appropriate amount + m_pHeadDelay->process(m_pHead, m_pHead, iBufferSize); //Master/headphones interleaving is now done in //SoundManager::requestBuffer() - Albert Nov 18/07 === modified file 'mixxx/src/engine/enginemaster.h' --- mixxx/src/engine/enginemaster.h 2011-04-13 03:01:52 +0000 +++ mixxx/src/engine/enginemaster.h 2011-04-30 20:12:09 +0000 @@ -39,6 +39,7 @@ class ControlPushButton; class EngineVinylSoundEmu; class EngineSideChain; +class EnginePflDelay; class EngineMaster : public EngineObject, public AudioSource { Q_OBJECT @@ -134,6 +135,7 @@ ControlObject *m_pMasterVolume, *m_pHeadVolume; EngineClipping *clipping, *head_clipping; + EnginePflDelay *m_pHeadDelay; #ifdef __LADSPA__ EngineLADSPA *ladspa; #endif === renamed file 'mixxx/src/engine/enginedelay.cpp' => 'mixxx/src/engine/enginepfldelay.cpp' --- mixxx/src/engine/enginedelay.cpp 2009-01-24 04:39:32 +0000 +++ mixxx/src/engine/enginepfldelay.cpp 2011-04-30 20:11:24 +0000 @@ -1,5 +1,5 @@ /*************************************************************************** - enginedelay.cpp - description + enginepfldelay.cpp - description ------------------- copyright : (C) 2002 by Tue and Ken Haste Andersen email : @@ -14,25 +14,44 @@ * * ***************************************************************************/ -#include "enginedelay.h" +#include "enginepfldelay.h" #include "controlpotmeter.h" +#include "sampleutil.h" /*---------------------------------------------------------------- ----------------------------------------------------------------*/ -EngineDelay::EngineDelay(const char * group) +EnginePflDelay::EnginePflDelay() { m_pDelayBuffer = new CSAMPLE[kiMaxDelay]; + //make sure it's zeroed out + SampleUtil::applyGain(m_pDelayBuffer, 0.0f, kiMaxDelay); m_iDelayPos = 0; - new ControlPotmeter(ConfigKey(group, "delay"), 0, kiMaxDelay); + + m_pDelayPot = new ControlPotmeter(ConfigKey("[Master]", "pfl_delay"), 0, 1); + connect(m_pDelayPot, SIGNAL(valueChanged(double)), + this, SLOT(slotDelayChanged(double)), + Qt::DirectConnection); + + m_iDelay = 0; } -EngineDelay::~EngineDelay() +EnginePflDelay::~EnginePflDelay() { delete [] m_pDelayBuffer; } -void EngineDelay::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize) +void EnginePflDelay::slotDelayChanged(double new_delay) +{ + //if we actually pick a value of kiMaxDelay, it wraps around to zero + m_iDelay = (int)(new_delay * (kiMaxDelay-2)); + if (m_iDelay % 2) + m_iDelay++; + //zero out the buffer to prevent noise + SampleUtil::applyGain(m_pDelayBuffer, 0.0f, kiMaxDelay); +} + +void EnginePflDelay::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize) { int iDelaySourcePos = (m_iDelayPos+kiMaxDelay-m_iDelay)%kiMaxDelay; CSAMPLE * pOutput = (CSAMPLE *)pOut; @@ -46,8 +65,8 @@ m_pDelayBuffer[m_iDelayPos] = pIn[i]; m_iDelayPos = (m_iDelayPos+1)%kiMaxDelay; - // Take "old" sample from delay buffer and mix it with the source buffer: - pOutput[i] = 0.5*(m_pDelayBuffer[iDelaySourcePos] + pIn[i]); + // Take delayed sample from delay buffer and copy it to dest buffer: + pOutput[i] = m_pDelayBuffer[iDelaySourcePos]; iDelaySourcePos = (iDelaySourcePos+1)%kiMaxDelay; } } === renamed file 'mixxx/src/engine/enginedelay.h' => 'mixxx/src/engine/enginepfldelay.h' --- mixxx/src/engine/enginedelay.h 2009-01-24 04:39:32 +0000 +++ mixxx/src/engine/enginepfldelay.h 2011-04-30 20:11:47 +0000 @@ -1,5 +1,5 @@ /*************************************************************************** - enginedelay.h - description + enginepfldelay.h - description ------------------- copyright : (C) 2002 by Tue and Ken Haste Andersen email : @@ -14,23 +14,28 @@ * * ***************************************************************************/ -#ifndef ENGINEDELAY_H -#define ENGINEDELAY_H +#ifndef ENGINEPFLDELAY_H +#define ENGINEPFLDELAY_H #include "engineobject.h" class ControlPotmeter; -const int kiMaxDelay = 20000; +const int kiMaxDelay = MAX_BUFFER_LEN; -class EngineDelay : public EngineObject +class EnginePflDelay : public EngineObject { + Q_OBJECT public: - EngineDelay(const char *group); - ~EngineDelay(); + EnginePflDelay(); + ~EnginePflDelay(); void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize); + +public slots: + void slotDelayChanged(double); + private: - ControlPotmeter *m_pPotmeter; + ControlPotmeter *m_pDelayPot; CSAMPLE *m_pDelayBuffer; int m_iDelay, m_iDelayPos; };