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