1 #pragma once 2 3 #include <QObject> 4 #include <QVarLengthArray> 5 6 #include "preferences/usersettings.h" 7 #include "control/controlobject.h" 8 #include "control/controlpushbutton.h" 9 #include "engine/engineobject.h" 10 #include "engine/channels/enginechannel.h" 11 #include "engine/channelhandle.h" 12 #include "soundio/soundmanager.h" 13 #include "soundio/soundmanagerutil.h" 14 #include "recording/recordingmanager.h" 15 16 class EngineWorkerScheduler; 17 class EngineBuffer; 18 class EngineChannel; 19 class EngineDeck; 20 class EngineFlanger; 21 class EngineVuMeter; 22 class ControlPotmeter; 23 class ControlPushButton; 24 class EngineSideChain; 25 class EffectsManager; 26 class EngineEffectsManager; 27 class SyncWorker; 28 class GuiTick; 29 class EngineSync; 30 class EngineTalkoverDucking; 31 class EngineDelay; 32 33 // The number of channels to pre-allocate in various structures in the 34 // engine. Prevents memory allocation in EngineMaster::addChannel. 35 static const int kPreallocatedChannels = 64; 36 37 class EngineMaster : public QObject, public AudioSource { 38 Q_OBJECT 39 public: 40 EngineMaster(UserSettingsPointer pConfig, 41 const QString& group, 42 EffectsManager* pEffectsManager, 43 ChannelHandleFactoryPointer pChannelHandleFactory, 44 bool bEnableSidechain); 45 virtual ~EngineMaster(); 46 47 // Get access to the sample buffers. None of these are thread safe. Only to 48 // be called by SoundManager. 49 const CSAMPLE* buffer(const AudioOutput& output) const; 50 registerChannelGroup(const QString & group)51 ChannelHandleAndGroup registerChannelGroup(const QString& group) { 52 return ChannelHandleAndGroup( 53 m_pChannelHandleFactory->getOrCreateHandle(group), group); 54 } 55 56 // Register the sound I/O that does not correspond to any EngineChannel object 57 void registerNonEngineChannelSoundIO(SoundManager* pSoundManager); 58 59 // WARNING: These methods are called by the main thread. They should only 60 // touch the volatile bool connected indicators (see below). However, when 61 // these methods are called the callback is guaranteed to be inactive 62 // (SoundManager closes all devices before calling these). This may change 63 // in the future. 64 virtual void onOutputConnected(const AudioOutput& output); 65 virtual void onOutputDisconnected(const AudioOutput& output); 66 void onInputConnected(const AudioInput& input); 67 void onInputDisconnected(const AudioInput& input); 68 69 void process(const int iBufferSize); 70 71 // Add an EngineChannel to the mixing engine. This is not thread safe -- 72 // only call it before the engine has started mixing. 73 void addChannel(EngineChannel* pChannel); 74 EngineChannel* getChannel(const QString& group); gainForOrientation(EngineChannel::ChannelOrientation orientation,CSAMPLE_GAIN leftGain,CSAMPLE_GAIN centerGain,CSAMPLE_GAIN rightGain)75 static inline CSAMPLE_GAIN gainForOrientation(EngineChannel::ChannelOrientation orientation, 76 CSAMPLE_GAIN leftGain, 77 CSAMPLE_GAIN centerGain, 78 CSAMPLE_GAIN rightGain) { 79 switch (orientation) { 80 case EngineChannel::LEFT: 81 return leftGain; 82 case EngineChannel::RIGHT: 83 return rightGain; 84 case EngineChannel::CENTER: 85 default: 86 return centerGain; 87 } 88 } 89 90 // Provide access to the master sync so enginebuffers can know what their rate controller is. getEngineSync()91 EngineSync* getEngineSync() const{ 92 return m_pMasterSync; 93 } 94 95 // These are really only exposed for tests to use. 96 const CSAMPLE* getMasterBuffer() const; 97 const CSAMPLE* getBoothBuffer() const; 98 const CSAMPLE* getHeadphoneBuffer() const; 99 const CSAMPLE* getOutputBusBuffer(unsigned int i) const; 100 const CSAMPLE* getDeckBuffer(unsigned int i) const; 101 const CSAMPLE* getChannelBuffer(const QString& name) const; 102 const CSAMPLE* getSidechainBuffer() const; 103 getSideChain()104 EngineSideChain* getSideChain() const { 105 return m_pEngineSideChain; 106 } 107 108 CSAMPLE_GAIN getMasterGain(int channelIndex) const; 109 110 struct ChannelInfo { ChannelInfoChannelInfo111 ChannelInfo(int index) 112 : m_pChannel(NULL), 113 m_pBuffer(NULL), 114 m_pVolumeControl(NULL), 115 m_pMuteControl(NULL), 116 m_index(index) { 117 } 118 ChannelHandle m_handle; 119 EngineChannel* m_pChannel; 120 CSAMPLE* m_pBuffer; 121 ControlObject* m_pVolumeControl; 122 ControlPushButton* m_pMuteControl; 123 GroupFeatureState m_features; 124 int m_index; 125 }; 126 127 struct GainCache { 128 CSAMPLE_GAIN m_gain; 129 bool m_fadeout; 130 }; 131 132 class GainCalculator { 133 public: 134 virtual ~GainCalculator() = default; 135 virtual CSAMPLE_GAIN getGain(ChannelInfo* pChannelInfo) const = 0; 136 }; 137 class PflGainCalculator : public GainCalculator { 138 public: getGain(ChannelInfo * pChannelInfo)139 inline CSAMPLE_GAIN getGain(ChannelInfo* pChannelInfo) const override { 140 Q_UNUSED(pChannelInfo); 141 return m_dGain; 142 } setGain(CSAMPLE_GAIN dGain)143 inline void setGain(CSAMPLE_GAIN dGain) { 144 m_dGain = dGain; 145 } 146 147 private: 148 CSAMPLE_GAIN m_dGain; 149 }; 150 class TalkoverGainCalculator : public GainCalculator { 151 public: getGain(ChannelInfo * pChannelInfo)152 inline CSAMPLE_GAIN getGain(ChannelInfo* pChannelInfo) const override { 153 return static_cast<CSAMPLE_GAIN>(pChannelInfo->m_pVolumeControl->get()); 154 } 155 }; 156 class OrientationVolumeGainCalculator : public GainCalculator { 157 public: OrientationVolumeGainCalculator()158 OrientationVolumeGainCalculator() 159 : m_dLeftGain(1.0), 160 m_dCenterGain(1.0), 161 m_dRightGain(1.0), 162 m_dTalkoverDuckingGain(1.0) { 163 } 164 getGain(ChannelInfo * pChannelInfo)165 inline CSAMPLE_GAIN getGain(ChannelInfo* pChannelInfo) const { 166 const CSAMPLE_GAIN channelVolume = static_cast<CSAMPLE_GAIN>( 167 pChannelInfo->m_pVolumeControl->get()); 168 const CSAMPLE_GAIN orientationGain = EngineMaster::gainForOrientation( 169 pChannelInfo->m_pChannel->getOrientation(), 170 m_dLeftGain, 171 m_dCenterGain, 172 m_dRightGain); 173 return channelVolume * orientationGain * m_dTalkoverDuckingGain; 174 } 175 setGains(CSAMPLE_GAIN leftGain,CSAMPLE_GAIN centerGain,CSAMPLE_GAIN rightGain,CSAMPLE_GAIN talkoverDuckingGain)176 inline void setGains(CSAMPLE_GAIN leftGain, 177 CSAMPLE_GAIN centerGain, 178 CSAMPLE_GAIN rightGain, 179 CSAMPLE_GAIN talkoverDuckingGain) { 180 m_dLeftGain = leftGain; 181 m_dCenterGain = centerGain; 182 m_dRightGain = rightGain; 183 m_dTalkoverDuckingGain = talkoverDuckingGain; 184 } 185 186 private: 187 CSAMPLE_GAIN m_dLeftGain; 188 CSAMPLE_GAIN m_dCenterGain; 189 CSAMPLE_GAIN m_dRightGain; 190 CSAMPLE_GAIN m_dTalkoverDuckingGain; 191 }; 192 193 enum class MicMonitorMode { 194 // These are out of order with how they are listed in DlgPrefSound for backwards 195 // compatibility with Mixxx 2.0 user settings. In Mixxx 2.0, before the 196 // booth output was added, this was a binary option without 197 // the MASTER_AND_BOOTH mode. 198 MASTER = 0, 199 DIRECT_MONITOR, 200 MASTER_AND_BOOTH 201 }; 202 203 template<typename T, unsigned int CAPACITY> 204 class FastVector { 205 public: FastVector()206 inline FastVector() : m_size(0), m_data((T*)((void *)m_buffer)) {}; ~FastVector()207 inline ~FastVector() { 208 if (QTypeInfo<T>::isComplex) { 209 for (int i = 0; i < m_size; ++i) { 210 m_data[i].~T(); 211 } 212 } 213 } append(const T & t)214 inline void append(const T& t) { 215 if (QTypeInfo<T>::isComplex) { 216 new (&m_data[m_size++]) T(t); 217 } else { 218 m_data[m_size++] = t; 219 } 220 }; 221 inline const T& operator[](unsigned int i) const { 222 return m_data[i]; 223 } 224 inline T& operator[](unsigned int i) { 225 return m_data[i]; 226 } at(unsigned int i)227 inline const T& at(unsigned int i) const { 228 return m_data[i]; 229 } replace(unsigned int i,const T & t)230 inline void replace(unsigned int i, const T& t) { 231 T copy(t); 232 m_data[i] = copy; 233 } size()234 inline int size () const { 235 return m_size; 236 } 237 private: 238 int m_size; 239 T* const m_data; 240 // Using a long double buffer guarantees the alignment for any type 241 // but avoids the constructor call T(); 242 long double m_buffer[(CAPACITY * sizeof(T) + sizeof(long double) - 1) / 243 sizeof(long double)]; 244 }; 245 246 protected: 247 // The master buffer is protected so it can be accessed by test subclasses. 248 CSAMPLE* m_pMaster; 249 250 // ControlObjects for switching off unnecessary processing 251 // These are protected so tests can set them 252 ControlObject* m_pMasterEnabled; 253 ControlObject* m_pHeadphoneEnabled; 254 ControlObject* m_pBoothEnabled; 255 256 private: 257 // Processes active channels. The master sync channel (if any) is processed 258 // first and all others are processed after. Populates m_activeChannels, 259 // m_activeBusChannels, m_activeHeadphoneChannels, and 260 // m_activeTalkoverChannels with each channel that is active for the 261 // respective output. 262 void processChannels(int iBufferSize); 263 264 ChannelHandleFactoryPointer m_pChannelHandleFactory; 265 void applyMasterEffects(); 266 void processHeadphones(const CSAMPLE_GAIN masterMixGainInHeadphones); 267 bool sidechainMixRequired() const; 268 269 EngineEffectsManager* m_pEngineEffectsManager; 270 271 // List of channels added to the engine. 272 QVarLengthArray<ChannelInfo*, kPreallocatedChannels> m_channels; 273 274 // The previous gain of each channel for each mixing output (master, 275 // headphone, talkover). 276 QVarLengthArray<GainCache, kPreallocatedChannels> m_channelMasterGainCache; 277 QVarLengthArray<GainCache, kPreallocatedChannels> m_channelHeadphoneGainCache; 278 QVarLengthArray<GainCache, kPreallocatedChannels> m_channelTalkoverGainCache; 279 280 // Pre-allocated buffers for performing channel mixing in the callback. 281 QVarLengthArray<ChannelInfo*, kPreallocatedChannels> m_activeChannels; 282 QVarLengthArray<ChannelInfo*, kPreallocatedChannels> m_activeBusChannels[3]; 283 QVarLengthArray<ChannelInfo*, kPreallocatedChannels> m_activeHeadphoneChannels; 284 QVarLengthArray<ChannelInfo*, kPreallocatedChannels> m_activeTalkoverChannels; 285 286 unsigned int m_iSampleRate; 287 unsigned int m_iBufferSize; 288 289 // Mixing buffers for each output. 290 CSAMPLE* m_pOutputBusBuffers[3]; 291 CSAMPLE* m_pBooth; 292 CSAMPLE* m_pHead; 293 CSAMPLE* m_pTalkover; 294 CSAMPLE* m_pTalkoverHeadphones; 295 CSAMPLE* m_pSidechainMix; 296 297 EngineWorkerScheduler* m_pWorkerScheduler; 298 EngineSync* m_pMasterSync; 299 300 ControlObject* m_pMasterGain; 301 ControlObject* m_pBoothGain; 302 ControlObject* m_pHeadGain; 303 ControlObject* m_pMasterSampleRate; 304 ControlObject* m_pMasterLatency; 305 ControlObject* m_pMasterAudioBufferSize; 306 ControlObject* m_pAudioLatencyOverloadCount; 307 ControlObject* m_pNumMicsConfigured; 308 ControlPotmeter* m_pAudioLatencyUsage; 309 ControlPotmeter* m_pAudioLatencyOverload; 310 EngineTalkoverDucking* m_pTalkoverDucking; 311 EngineDelay* m_pMasterDelay; 312 EngineDelay* m_pHeadDelay; 313 EngineDelay* m_pBoothDelay; 314 EngineDelay* m_pLatencyCompensationDelay; 315 316 EngineVuMeter* m_pVumeter; 317 EngineSideChain* m_pEngineSideChain; 318 319 ControlPotmeter* m_pCrossfader; 320 ControlPotmeter* m_pHeadMix; 321 ControlPotmeter* m_pBalance; 322 ControlPushButton* m_pXFaderMode; 323 ControlPotmeter* m_pXFaderCurve; 324 ControlPotmeter* m_pXFaderCalibration; 325 ControlPushButton* m_pXFaderReverse; 326 ControlPushButton* m_pHeadSplitEnabled; 327 ControlObject* m_pKeylockEngine; 328 329 PflGainCalculator m_headphoneGain; 330 TalkoverGainCalculator m_talkoverGain; 331 OrientationVolumeGainCalculator m_masterGain; 332 CSAMPLE_GAIN m_masterGainOld; 333 CSAMPLE_GAIN m_boothGainOld; 334 CSAMPLE_GAIN m_headphoneMasterGainOld; 335 CSAMPLE_GAIN m_headphoneGainOld; 336 CSAMPLE_GAIN m_balleftOld; 337 CSAMPLE_GAIN m_balrightOld; 338 const ChannelHandleAndGroup m_masterHandle; 339 const ChannelHandleAndGroup m_headphoneHandle; 340 const ChannelHandleAndGroup m_masterOutputHandle; 341 const ChannelHandleAndGroup m_busTalkoverHandle; 342 const ChannelHandleAndGroup m_busCrossfaderLeftHandle; 343 const ChannelHandleAndGroup m_busCrossfaderCenterHandle; 344 const ChannelHandleAndGroup m_busCrossfaderRightHandle; 345 346 // Mix two Mono channels. This is useful for outdoor gigs 347 ControlObject* m_pMasterMonoMixdown; 348 ControlObject* m_pMicMonitorMode; 349 350 volatile bool m_bBusOutputConnected[3]; 351 bool m_bExternalRecordBroadcastInputConnected; 352 }; 353