Merge lp:~mattmik/mixxx/features_passthrough into lp:~mixxxdevelopers/mixxx/trunk
- features_passthrough
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~mattmik/mixxx/features_passthrough |
Merge into: | lp:~mixxxdevelopers/mixxx/trunk |
Diff against target: |
609 lines (+239/-101) 12 files modified
mixxx/build/depends.py (+0/-1) mixxx/res/skins/Deere1280x800-WXGA/skin.xml (+1/-1) mixxx/src/basetrackplayer.cpp (+9/-5) mixxx/src/basetrackplayer.h (+4/-0) mixxx/src/engine/enginedeck.cpp (+133/-8) mixxx/src/engine/enginedeck.h (+34/-2) mixxx/src/engine/enginemaster.cpp (+2/-0) mixxx/src/engine/enginepassthrough.h (+0/-51) mixxx/src/engine/enginepregain.cpp (+18/-22) mixxx/src/engine/enginepregain.h (+2/-1) mixxx/src/mixxx.cpp (+17/-4) mixxx/src/soundmanager.cpp (+19/-6) |
To merge this branch: | bzr merge lp:~mattmik/mixxx/features_passthrough |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
RJ Skerry-Ryan | Approve | ||
Review via email: mp+109726@code.launchpad.net |
Commit message
Description of the change
Passthrough has been implemented through the EngineDeck class. This required some modifications to additional classes.
Passthrough for a certain deck is enabled using a ControlPushButton linked to the ConfigKey "passthrough_
Please ignore all modifications to the EnginePassthrough class, as passthrough using this class is deprecated.
If there are any questions, please contact me!
- 3255. By Daniel Schürmann
-
merged with lp:mixxx/1.10
- 3256. By RJ Skerry-Ryan
-
Add patch from Max Linke for Bug #1002330 to fix some more star-rating issues.
- 3257. By RJ Skerry-Ryan
-
Merging bkgood's lp:~mixxxdevelopers/mixxx/fixes_midi_burnout branch to lp:mixxx.
- 3258. By RJ Skerry-Ryan
-
On Linux, use a 5ms polling interval instead of 1ms. Workaround for Bug #990992 until we have a better fix.
- 3259. By jus
-
ic_template_
keyboard_ mapping_ sheet.svg re-drawn and arranged more clearly. Makes future maintainance easier if keyboard shortcuts change. - 3260. By Daniel Schürmann
-
set default recording folder to QDesktopService
s::MusicLocatio n - 3261. By RJ Skerry-Ryan
-
Add Max Linke's patch to add a 'Hidden Tracks' view to Mixxx and change default terminology from 'remove' to 'hide'. Fixes Bug #949828
- 3262. By RJ Skerry-Ryan
-
Remove redundant rollback since ScopedTransaction auto-rollbacks when it leaves scope w/o being committed.
- 3263. By RJ Skerry-Ryan
-
For some reason bzr patch did not add hiddentablemode
l.cpp from Max's patch. - 3264. By RJ Skerry-Ryan
-
Not my day today .. add hiddentablemodel.h
- 3265. By RJ Skerry-Ryan
-
Add mutil's patch to close the preference dialog when quitting Mixxx. Fixes Bug #1007958
- 3266. By RJ Skerry-Ryan
-
Add Max Linke's patch to fix external drag and drop. Fixes Bug #1014842
- 3267. By RJ Skerry-Ryan
-
Add patch from daschuer and mutil that warns the user if the skin does not match their screen resolution. Fixes Bug #1011002
- 3268. By RJ Skerry-Ryan
-
Add Numark OMNI control preset from Baxter.
- 3269. By RJ Skerry-Ryan
-
Re-enable bitrate column and allow bitrate: search queries. Fixes Bug #1008872
- 3270. By RJ Skerry-Ryan
-
When a CO does not exist, make it a toggle ControlPushButton by default instead of a ControlObject. Fixes Bug #1009547
- 3271. By RJ Skerry-Ryan
-
Add missing warning icon.
- 3272. By jus
-
Add new preferences icon for controllers & update icon template accordingly, fixes lp:992813
- 3273. By RJ Skerry-Ryan
-
Add Max Linke's patch to clean up cues, analyses, crates and playlists on purge of tracks from the library. Fixes Bug #949828
- 3274. By RJ Skerry-Ryan
-
Add patch from daschuer to improve schema upgrade error messages. Fixes Bug #963408
- 3275. By RJ Skerry-Ryan
-
Version bump to 1.11.0 beta1
- 3276. By RJ Skerry-Ryan
-
Add 1.11.0~
beta1-0ubuntu1 to Debian changelog. - 3277. By RJ Skerry-Ryan
-
Add Numark N4 preset from dj.stuartbrand.
- 3278. By RJ Skerry-Ryan
-
Merging lp:~hile/mixxx/forumlinks into lp:mixxx/1.11
- 3279. By RJ Skerry-Ryan
-
Add support for displaying wiki links from presets in the controller preferences dialog.
- 3280. By RJ Skerry-Ryan
-
Minor preset cleanups.
- 3281. By RJ Skerry-Ryan
-
Potentially fix PPA upload by supporting an explicit ubuntu_ppa SConscript command and allowing ubuntu_dist to be a comma separated list of distros to upload for. This allows us to have one original source tarball for all the individual Ubuntu versions we support.
- 3282. By RJ Skerry-Ryan
-
Merging from lp:mixxx
- 3283. By RJ Skerry-Ryan
-
Hack the mixxx_version when we're doing a PPA upload by appending -bzrXXXX.
- 3284. By RJ Skerry-Ryan
-
Merging from lp:mixxx/1.11
- 3285. By RJ Skerry-Ryan
-
Merging from lp:mixxx/1.11
- 3286. By Daniel Schürmann
-
Merging from lp:mixxx/1.11
- 3287. By RJ Skerry-Ryan
-
Merging from lp:mixxx/1.11
- 3288. By Daniel Schürmann
-
merged with lp:mixxx/1.11
- 3289. By Daniel Schürmann
-
merged with lp:mixxx/1.11
- 3290. By RJ Skerry-Ryan
-
Merging from lp:mixxx/1.11
- 3291. By Daniel Schürmann
-
merged with lp:mixxx/1.11
- 3292. By Matthew Mikolay
-
Merging from lp:mixxx/1.11
- 3293. By Matthew Mikolay
-
Merging from lp:mixxx/1.11
- 3294. By Matthew Mikolay
-
Merging from lp:mixxx
Unmerged revisions
- 3294. By Matthew Mikolay
-
Merging from lp:mixxx
- 3293. By Matthew Mikolay
-
Merging from lp:mixxx/1.11
- 3292. By Matthew Mikolay
-
Merging from lp:mixxx/1.11
Preview Diff
1 | === modified file 'mixxx/build/depends.py' |
2 | --- mixxx/build/depends.py 2012-09-05 06:24:48 +0000 |
3 | +++ mixxx/build/depends.py 2012-10-22 14:36:20 +0000 |
4 | @@ -458,7 +458,6 @@ |
5 | "engine/enginexfader.cpp", |
6 | "engine/enginemicrophone.cpp", |
7 | "engine/enginedeck.cpp", |
8 | - "engine/enginepassthrough.cpp", |
9 | |
10 | "engine/enginecontrol.cpp", |
11 | "engine/ratecontrol.cpp", |
12 | |
13 | === modified file 'mixxx/res/skins/Deere1280x800-WXGA/skin.xml' |
14 | --- mixxx/res/skins/Deere1280x800-WXGA/skin.xml 2012-09-09 09:25:58 +0000 |
15 | +++ mixxx/res/skins/Deere1280x800-WXGA/skin.xml 2012-10-22 14:36:20 +0000 |
16 | @@ -3873,7 +3873,7 @@ |
17 | |
18 | <!-- |
19 | ********************************************** |
20 | - Button - Quantize |
21 | + Button - Quantize <ConfigKey>[Channel1],quantize</ConfigKey> |
22 | ********************************************** |
23 | --> |
24 | <PushButton> |
25 | |
26 | === modified file 'mixxx/src/basetrackplayer.cpp' |
27 | --- mixxx/src/basetrackplayer.cpp 2012-06-25 00:02:38 +0000 |
28 | +++ mixxx/src/basetrackplayer.cpp 2012-10-22 14:36:20 +0000 |
29 | @@ -9,7 +9,6 @@ |
30 | #include "controlpotmeter.h" |
31 | #include "trackinfoobject.h" |
32 | #include "engine/enginebuffer.h" |
33 | -#include "engine/enginedeck.h" |
34 | #include "engine/enginemaster.h" |
35 | #include "soundsourceproxy.h" |
36 | #include "engine/cuecontrol.h" |
37 | @@ -34,10 +33,10 @@ |
38 | // pSafeGroupName is leaked. It's like 5 bytes so whatever. |
39 | const char* pSafeGroupName = strdup(getGroup().toAscii().constData()); |
40 | |
41 | - EngineDeck* pChannel = new EngineDeck(pSafeGroupName, |
42 | - pConfig, defaultOrientation); |
43 | - EngineBuffer* pEngineBuffer = pChannel->getEngineBuffer(); |
44 | - pMixingEngine->addChannel(pChannel); |
45 | + m_pChannel = new EngineDeck(pSafeGroupName, pConfig, defaultOrientation); |
46 | + |
47 | + EngineBuffer* pEngineBuffer = m_pChannel->getEngineBuffer(); |
48 | + pMixingEngine->addChannel(m_pChannel); |
49 | |
50 | ClockControl* pClockControl = new ClockControl(pSafeGroupName, pConfig); |
51 | pEngineBuffer->addControl(pClockControl); |
52 | @@ -246,3 +245,8 @@ |
53 | TrackPointer BaseTrackPlayer::getLoadedTrack() const { |
54 | return m_pLoadedTrack; |
55 | } |
56 | + |
57 | +EngineDeck* BaseTrackPlayer::getEngineDeck() const { |
58 | + return m_pChannel; |
59 | +} |
60 | + |
61 | |
62 | === modified file 'mixxx/src/basetrackplayer.h' |
63 | --- mixxx/src/basetrackplayer.h 2012-04-25 04:43:42 +0000 |
64 | +++ mixxx/src/basetrackplayer.h 2012-10-22 14:36:20 +0000 |
65 | @@ -6,6 +6,7 @@ |
66 | #include "baseplayer.h" |
67 | #include "analyserqueue.h" |
68 | #include "engine/enginechannel.h" |
69 | +#include "engine/enginedeck.h" |
70 | |
71 | class EngineMaster; |
72 | class ControlObject; |
73 | @@ -25,6 +26,7 @@ |
74 | |
75 | AnalyserQueue* getAnalyserQueue() const; |
76 | TrackPointer getLoadedTrack() const; |
77 | + EngineDeck* getEngineDeck() const; |
78 | |
79 | public slots: |
80 | void slotLoadTrack(TrackPointer track, bool bStartFromEndPos=false); |
81 | @@ -53,6 +55,8 @@ |
82 | ControlObject* m_pDuration; |
83 | ControlObjectThreadMain* m_pBPM; |
84 | ControlObjectThreadMain* m_pReplayGain; |
85 | + |
86 | + EngineDeck* m_pChannel; |
87 | }; |
88 | |
89 | |
90 | |
91 | === modified file 'mixxx/src/engine/enginedeck.cpp' |
92 | --- mixxx/src/engine/enginedeck.cpp 2011-06-11 22:55:41 +0000 |
93 | +++ mixxx/src/engine/enginedeck.cpp 2012-10-22 14:36:20 +0000 |
94 | @@ -26,11 +26,30 @@ |
95 | #include "enginevumeter.h" |
96 | #include "enginefilteriir.h" |
97 | |
98 | +#include "sampleutil.h" |
99 | + |
100 | EngineDeck::EngineDeck(const char* group, |
101 | ConfigObject<ConfigValue>* pConfig, |
102 | EngineChannel::ChannelOrientation defaultOrientation) |
103 | : EngineChannel(group, defaultOrientation), |
104 | - m_pConfig(pConfig) { |
105 | + m_pConfig(pConfig), |
106 | + m_pPassing(new ControlPushButton(ConfigKey(group, "passthrough_enabled"))), |
107 | + // Need a +1 here because the CircularBuffer only allows its size-1 |
108 | + // items to be held at once (it keeps a blank spot open persistently) |
109 | + m_sampleBuffer(MAX_BUFFER_LEN+1) { |
110 | + |
111 | + // Set up passthrough utilities and fields |
112 | + m_pPassing->setButtonMode(ControlPushButton::TOGGLE); |
113 | + m_pConversionBuffer = SampleUtil::alloc(MAX_BUFFER_LEN); |
114 | + m_bPassthroughIsActive = false; |
115 | + m_bPassthroughWasActive = false; |
116 | + |
117 | + // Set up passthrough toggle button |
118 | + connect(m_pPassing, SIGNAL(valueChanged(double)), |
119 | + this, SLOT(slotPassingToggle(double)), |
120 | + Qt::DirectConnection); |
121 | + |
122 | + // Set up additional engines |
123 | m_pPregain = new EnginePregain(group); |
124 | m_pFilter = new EngineFilterBlock(group); |
125 | m_pFlanger = new EngineFlanger(group); |
126 | @@ -41,6 +60,9 @@ |
127 | } |
128 | |
129 | EngineDeck::~EngineDeck() { |
130 | + SampleUtil::free(m_pConversionBuffer); |
131 | + delete m_pPassing; |
132 | + |
133 | delete m_pBuffer; |
134 | delete m_pClipping; |
135 | delete m_pFilter; |
136 | @@ -50,11 +72,40 @@ |
137 | delete m_pVUMeter; |
138 | } |
139 | |
140 | -void EngineDeck::process(const CSAMPLE*, const CSAMPLE * pOut, const int iBufferSize) { |
141 | - // Process the raw audio |
142 | - m_pBuffer->process(0, pOut, iBufferSize); |
143 | - // Emulate vinyl sounds |
144 | - m_pVinylSoundEmu->process(pOut, pOut, iBufferSize); |
145 | +void EngineDeck::process(const CSAMPLE*, const CSAMPLE * pOutput, const int iBufferSize) { |
146 | + |
147 | + CSAMPLE* pOut = const_cast<CSAMPLE*>(pOutput); |
148 | + |
149 | + // Feed the incoming audio through if passthrough is active |
150 | + if (isPassthroughActive()) { |
151 | + int samplesRead = m_sampleBuffer.read(pOut, iBufferSize); |
152 | + if (samplesRead < iBufferSize) { |
153 | + // Buffer underflow. There aren't getting samples fast enough. This |
154 | + // shouldn't happen since PortAudio should feed us samples just as fast |
155 | + // as we consume them, right? |
156 | + Q_ASSERT(false); |
157 | + } |
158 | + |
159 | + m_bPassthroughWasActive = true; |
160 | + |
161 | + } else { |
162 | + |
163 | + // If passthrough is no longer enabled, zero out the buffer |
164 | + if (m_bPassthroughWasActive) { |
165 | + SampleUtil::applyGain(pOut, 0.0, iBufferSize); |
166 | + m_sampleBuffer.skip(iBufferSize); |
167 | + m_bPassthroughWasActive = false; |
168 | + return; |
169 | + } |
170 | + |
171 | + // Process the raw audio |
172 | + m_pBuffer->process(0, pOut, iBufferSize); |
173 | + // Emulate vinyl sounds |
174 | + m_pVinylSoundEmu->process(pOut, pOut, iBufferSize); |
175 | + |
176 | + m_bPassthroughWasActive = false; |
177 | + } |
178 | + |
179 | // Apply pregain |
180 | m_pPregain->process(pOut, pOut, iBufferSize); |
181 | // Filter the channel with EQs |
182 | @@ -72,5 +123,79 @@ |
183 | } |
184 | |
185 | bool EngineDeck::isActive() { |
186 | - return m_pBuffer->isTrackLoaded(); |
187 | -} |
188 | + if (m_bPassthroughWasActive && !m_bPassthroughIsActive) { |
189 | + return true; |
190 | + } |
191 | + |
192 | + return (m_pBuffer->isTrackLoaded() || isPassthroughActive()); |
193 | +} |
194 | + |
195 | +void EngineDeck::receiveBuffer(AudioInput input, const short* pBuffer, unsigned int nFrames) { |
196 | + |
197 | + // Skip receiving audio input if passthrough is not active |
198 | + if (!m_bPassthroughIsActive) { |
199 | + return; |
200 | + } |
201 | + |
202 | + if (input.getType() != AudioPath::VINYLCONTROL) { |
203 | + // This is an error! |
204 | + qDebug() << "WARNING: EngineDeck receieved an AudioInput for a non-vinylcontrol type!"; |
205 | + return; |
206 | + } |
207 | + |
208 | + // Use the conversion buffer to both convert from short and double into |
209 | + // stereo. |
210 | + |
211 | + // Check that the number of mono samples doesn't exceed MAX_BUFFER_LEN/2 |
212 | + // because thats our conversion buffer size. |
213 | + if (nFrames > MAX_BUFFER_LEN / 2) { |
214 | + qDebug() << "WARNING: Dropping passthrough samples because the input buffer is too large."; |
215 | + nFrames = MAX_BUFFER_LEN / 2; |
216 | + } |
217 | + |
218 | + // There isn't a suitable SampleUtil method that can do mono->stereo and |
219 | + // short->float in one pass. |
220 | + // SampleUtil::convert(m_pConversionBuffer, pBuffer, iNumSamples); |
221 | + SampleUtil::convert(m_pConversionBuffer, pBuffer, nFrames*2); |
222 | + |
223 | + // TODO(rryan) (or bkgood?) do we need to verify the input is the one we asked for? Oh well. |
224 | + unsigned int samplesWritten = m_sampleBuffer.write(m_pConversionBuffer, nFrames*2); |
225 | + if (samplesWritten < nFrames*2) { |
226 | + // Buffer overflow. We aren't processing samples fast enough. This |
227 | + // shouldn't happen since the deck spits out samples just as fast as they |
228 | + // come in, right? |
229 | + Q_ASSERT(false); |
230 | + } |
231 | +} |
232 | + |
233 | +void EngineDeck::onInputConnected(AudioInput input) { |
234 | + if (input.getType() != AudioPath::VINYLCONTROL) { |
235 | + // This is an error! |
236 | + qDebug() << "WARNING: EngineDeck connected to AudioInput for a non-vinylcontrol type!"; |
237 | + return; |
238 | + } |
239 | + m_sampleBuffer.clear(); |
240 | +} |
241 | + |
242 | +void EngineDeck::onInputDisconnected(AudioInput input) { |
243 | + if (input.getType() != AudioPath::VINYLCONTROL) { |
244 | + // This is an error! |
245 | + qDebug() << "WARNING: EngineDeck connected to AudioInput for a non-vinylcontrol type!"; |
246 | + return; |
247 | + } |
248 | + m_sampleBuffer.clear(); |
249 | +} |
250 | + |
251 | +bool EngineDeck::isPassthroughActive() { |
252 | + return (m_bPassthroughIsActive && !m_sampleBuffer.isEmpty()); |
253 | +} |
254 | + |
255 | +void EngineDeck::slotPassingToggle(double v) { |
256 | + if (v > 0) { |
257 | + m_bPassthroughIsActive = true; |
258 | + } |
259 | + else { |
260 | + m_bPassthroughIsActive = false; |
261 | + } |
262 | +} |
263 | + |
264 | |
265 | === modified file 'mixxx/src/engine/enginedeck.h' |
266 | --- mixxx/src/engine/enginedeck.h 2011-04-01 04:51:24 +0000 |
267 | +++ mixxx/src/engine/enginedeck.h 2012-10-22 14:36:20 +0000 |
268 | @@ -18,10 +18,14 @@ |
269 | #ifndef ENGINEDECK_H |
270 | #define ENGINEDECK_H |
271 | |
272 | +#include "circularbuffer.h" |
273 | +#include "controlpushbutton.h" |
274 | #include "engine/engineobject.h" |
275 | #include "engine/enginechannel.h" |
276 | #include "configobject.h" |
277 | |
278 | +#include "soundmanagerutil.h" |
279 | + |
280 | class EngineBuffer; |
281 | class EnginePregain; |
282 | class EngineBuffer; |
283 | @@ -32,19 +36,40 @@ |
284 | class EngineVinylSoundEmu; |
285 | class ControlPushButton; |
286 | |
287 | -class EngineDeck : public EngineChannel { |
288 | +class EngineDeck : public EngineChannel, public AudioDestination { |
289 | Q_OBJECT |
290 | public: |
291 | EngineDeck(const char *group, ConfigObject<ConfigValue>* pConfig, |
292 | EngineChannel::ChannelOrientation defaultOrientation = CENTER); |
293 | virtual ~EngineDeck(); |
294 | |
295 | - virtual void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize); |
296 | + virtual void process(const CSAMPLE *pInput, const CSAMPLE *pOutput, const int iBufferSize); |
297 | |
298 | // TODO(XXX) This hack needs to be removed. |
299 | virtual EngineBuffer* getEngineBuffer(); |
300 | |
301 | virtual bool isActive(); |
302 | + |
303 | + // Begin vinyl passthrough methods |
304 | + |
305 | + // This is called by SoundManager whenever there are new samples from the |
306 | + // deck to be processed |
307 | + virtual void receiveBuffer(AudioInput input, const short *pBuffer, unsigned int nFrames); |
308 | + |
309 | + // Called by SoundManager whenever the passthrough input is connected to a |
310 | + // soundcard input. |
311 | + virtual void onInputConnected(AudioInput input); |
312 | + |
313 | + // Called by SoundManager whenever the passthrough input is disconnected from |
314 | + // a soundcard input. |
315 | + virtual void onInputDisconnected(AudioInput input); |
316 | + |
317 | + // Return whether or not passthrough is active |
318 | + bool isPassthroughActive(); |
319 | + |
320 | + public slots: |
321 | + void slotPassingToggle(double v); |
322 | + |
323 | private: |
324 | ConfigObject<ConfigValue>* m_pConfig; |
325 | EngineBuffer* m_pBuffer; |
326 | @@ -54,6 +79,13 @@ |
327 | EnginePregain* m_pPregain; |
328 | EngineVinylSoundEmu* m_pVinylSoundEmu; |
329 | EngineVuMeter* m_pVUMeter; |
330 | + |
331 | + // Begin vinyl passthrough fields |
332 | + ControlPushButton* m_pPassing; |
333 | + CSAMPLE* m_pConversionBuffer; |
334 | + CircularBuffer<CSAMPLE> m_sampleBuffer; |
335 | + bool m_bPassthroughIsActive; |
336 | + bool m_bPassthroughWasActive; |
337 | }; |
338 | |
339 | #endif |
340 | |
341 | === modified file 'mixxx/src/engine/enginemaster.cpp' |
342 | --- mixxx/src/engine/enginemaster.cpp 2012-09-23 20:26:44 +0000 |
343 | +++ mixxx/src/engine/enginemaster.cpp 2012-10-22 14:36:20 +0000 |
344 | @@ -203,6 +203,8 @@ |
345 | } |
346 | } |
347 | |
348 | + // qDebug() << "Total active channels: " << totalActive; |
349 | + |
350 | if (totalActive == 0) { |
351 | SampleUtil::applyGain(pOutput, 0.0f, iBufferSize); |
352 | } else if (totalActive == 1) { |
353 | |
354 | === removed file 'mixxx/src/engine/enginepassthrough.h' |
355 | --- mixxx/src/engine/enginepassthrough.h 2011-04-08 08:27:29 +0000 |
356 | +++ mixxx/src/engine/enginepassthrough.h 1970-01-01 00:00:00 +0000 |
357 | @@ -1,51 +0,0 @@ |
358 | -// enginepassthrough.h |
359 | -// created 4/8/2011 by Bill Good (bkgood@gmail.com) |
360 | -// unapologetically copied from enginemicrophone.h from RJ |
361 | - |
362 | -#ifndef ENGINEPASSTHROUGH_H |
363 | -#define ENGINEPASSTHROUGH_H |
364 | - |
365 | -#include "circularbuffer.h" |
366 | -#include "controlpushbutton.h" |
367 | -#include "engine/enginechannel.h" |
368 | -#include "engine/engineclipping.h" |
369 | -#include "engine/enginevumeter.h" |
370 | -#include "soundmanagerutil.h" |
371 | - |
372 | -// EnginePassthrough is an EngineChannel that implements a mixing source whose |
373 | -// samples are fed directly from the SoundManager |
374 | -class EnginePassthrough : public EngineChannel, public AudioDestination { |
375 | - Q_OBJECT |
376 | - public: |
377 | - EnginePassthrough(const char *pGroup); |
378 | - virtual ~EnginePassthrough(); |
379 | - |
380 | - bool isActive(); |
381 | - bool isPFL(); |
382 | - bool isMaster(); |
383 | - |
384 | - // Called by EngineMaster whenever is requesting a new buffer of audio. |
385 | - virtual void process(const CSAMPLE *pInput, const CSAMPLE *pOutput, const int iBufferSize); |
386 | - |
387 | - // This is called by SoundManager whenever there are new samples from the |
388 | - // deck to be processed |
389 | - virtual void receiveBuffer(AudioInput input, const short *pBuffer, unsigned int nFrames); |
390 | - |
391 | - // Called by SoundManager whenever the passthrough input is connected to a |
392 | - // soundcard input. |
393 | - virtual void onInputConnected(AudioInput input); |
394 | - |
395 | - // Called by SoundManager whenever the passthrough input is disconnected from |
396 | - // a soundcard input. |
397 | - virtual void onInputDisconnected(AudioInput input); |
398 | - |
399 | - private: |
400 | - EngineClipping m_clipping; |
401 | - EngineVuMeter m_vuMeter; |
402 | - ControlObject *m_pEnabled; |
403 | - ControlPushButton *m_pPassing; |
404 | - CSAMPLE *m_pConversionBuffer; |
405 | - CircularBuffer<CSAMPLE> m_sampleBuffer; |
406 | -}; |
407 | - |
408 | -#endif /* ENGINEPASSTHROUGH_H */ |
409 | |
410 | === modified file 'mixxx/src/engine/enginepregain.cpp' |
411 | --- mixxx/src/engine/enginepregain.cpp 2012-08-10 23:57:22 +0000 |
412 | +++ mixxx/src/engine/enginepregain.cpp 2012-10-22 14:36:20 +0000 |
413 | @@ -38,6 +38,7 @@ |
414 | //Replay Gain things |
415 | m_pControlReplayGain = new ControlObject(ConfigKey(group, "replaygain")); |
416 | m_pTotalGain = new ControlObject(ConfigKey(group, "total_gain")); |
417 | + m_pPassthroughEnabled = ControlObject::getControl(ConfigKey(group, "passthrough_enabled")); |
418 | |
419 | if (s_pReplayGainBoost == NULL) { |
420 | s_pReplayGainBoost = new ControlPotmeter(ConfigKey("[ReplayGain]", "InitialReplayGainBoost"),0., 15.); |
421 | @@ -72,58 +73,53 @@ |
422 | float fGain = potmeterPregain->get(); |
423 | float fReplayGain = m_pControlReplayGain->get(); |
424 | m_fReplayGainCorrection=1; |
425 | + float fPassing = m_pPassthroughEnabled->get(); |
426 | // TODO(XXX) Why do we do this? Removing it results in clipping at unity |
427 | // gain so I think it was trying to compensate for some issue when we added |
428 | // replaygain but even at unity gain (no RG) we are clipping. rryan 5/2012 |
429 | fGain = fGain/2; |
430 | - if(fReplayGain*fEnableReplayGain != 0) |
431 | - { |
432 | + |
433 | + // Override replaygain value if passing through |
434 | + if (fPassing == 0.0) { |
435 | + fReplayGain = 1.0; |
436 | + } |
437 | + |
438 | + else if (fReplayGain*fEnableReplayGain != 0) { |
439 | // Here is the point, when ReplayGain Analyser takes its action, suggested gain changes from 0 to a nonzero value |
440 | // We want to smoothly fade to this last. |
441 | // Anyway we have some the problem that code cannot block the full process for one second. |
442 | // So we need to alter gain each time ::process is called. |
443 | + if (m_bSmoothFade) { // This means that a ReplayGain value has been calculated after the track has been loaded |
444 | |
445 | - if(m_bSmoothFade)//This means that a ReplayGain value has been calculated after the track has been loaded |
446 | - { |
447 | - if(m_fClock==0) |
448 | + if (m_fClock==0) { |
449 | m_fClock=clock(); |
450 | + } |
451 | m_fSumClock += (float)((clock()-m_fClock)/CLOCKS_PER_SEC); |
452 | m_fClock=clock(); |
453 | - if(m_fSumClock<1) |
454 | - { |
455 | + if (m_fSumClock<1) { |
456 | //Fade smoothly |
457 | - |
458 | m_fReplayGainCorrection=(1-m_fSumClock)+(m_fSumClock)*fReplayGain*pow(10, fReplayGainBoost/20); |
459 | - |
460 | } |
461 | - else |
462 | - { |
463 | + else { |
464 | m_bSmoothFade = false; |
465 | } |
466 | } |
467 | - else |
468 | - { |
469 | + else { |
470 | //Passing a user defined boost |
471 | m_fReplayGainCorrection=fReplayGain*pow(10, fReplayGainBoost/20); |
472 | } |
473 | } |
474 | - else |
475 | - { |
476 | + else { |
477 | // If track has not ReplayGain value and ReplayGain is enabled |
478 | // we prepare for smoothfading to ReplayGain suggested gain |
479 | - if(fEnableReplayGain != 0) |
480 | - { |
481 | + if(fEnableReplayGain != 0) { |
482 | m_bSmoothFade=true; |
483 | m_fClock=0; |
484 | m_fSumClock=0; |
485 | } |
486 | } |
487 | |
488 | - // Clamp gain to within [0, 10.0] to prevent insane gains. This can happen |
489 | - // (some corrupt files get really high replay gain values). |
490 | - // 10 allows a maximum replay Gain Boost * calculated replay gain of ~2 |
491 | - fGain = fGain * math_max(0.0, math_min(10.0, m_fReplayGainCorrection)); |
492 | - |
493 | + fGain = fGain*m_fReplayGainCorrection; |
494 | m_pTotalGain->set(fGain); |
495 | |
496 | //qDebug()<<"Clock"<<(float)clock()/CLOCKS_PER_SEC; |
497 | |
498 | === modified file 'mixxx/src/engine/enginepregain.h' |
499 | --- mixxx/src/engine/enginepregain.h 2012-07-22 09:31:52 +0000 |
500 | +++ mixxx/src/engine/enginepregain.h 2012-10-22 14:36:20 +0000 |
501 | @@ -35,7 +35,8 @@ |
502 | private: |
503 | ControlLogpotmeter *potmeterPregain; |
504 | ControlObject *m_pTotalGain; |
505 | - ControlObject *m_pControlReplayGain; |
506 | + ControlObject* m_pControlReplayGain; |
507 | + ControlObject* m_pPassthroughEnabled; |
508 | static ControlPotmeter *s_pReplayGainBoost; |
509 | static ControlObject *s_pEnableReplayGain; |
510 | float m_fReplayGainCorrection, m_fReplayGain, m_fOldReplayGainCorrection; |
511 | |
512 | === modified file 'mixxx/src/mixxx.cpp' |
513 | --- mixxx/src/mixxx.cpp 2012-10-09 20:07:04 +0000 |
514 | +++ mixxx/src/mixxx.cpp 2012-10-22 14:36:20 +0000 |
515 | @@ -26,10 +26,12 @@ |
516 | #include "build.h" // Generated by SCons |
517 | #include "controlobjectthreadmain.h" |
518 | #include "controlpotmeter.h" |
519 | +#include "deck.h" |
520 | #include "defs_urls.h" |
521 | #include "defs_version.h" |
522 | #include "dlgabout.h" |
523 | #include "dlgpreferences.h" |
524 | +#include "engine/enginedeck.h" |
525 | #include "engine/enginemaster.h" |
526 | #include "engine/enginemicrophone.h" |
527 | #include "library/library.h" |
528 | @@ -309,10 +311,21 @@ |
529 | |
530 | // Create the player manager. |
531 | m_pPlayerManager = new PlayerManager(m_pConfig, m_pEngine, m_pLibrary); |
532 | - m_pPlayerManager->addDeck(); |
533 | - m_pPlayerManager->addDeck(); |
534 | - m_pPlayerManager->addDeck(); |
535 | - m_pPlayerManager->addDeck(); |
536 | + |
537 | + // Set up four decks for with the player manager |
538 | + for (unsigned int deck = 0; deck < 4; ++deck) { |
539 | + |
540 | + // Add deck to the player manager |
541 | + Deck* pDeck = m_pPlayerManager->addDeck(); |
542 | + |
543 | +#ifdef __VINYLCONTROL__ |
544 | + EngineDeck* pEngineDeck = pDeck->getEngineDeck(); |
545 | + // Register vinyl input signal with deck for passthrough |
546 | + m_pSoundManager->registerInput(AudioInput(AudioInput::VINYLCONTROL, 0, deck), pEngineDeck); |
547 | +#endif |
548 | + |
549 | + } |
550 | + |
551 | m_pPlayerManager->addSampler(); |
552 | m_pPlayerManager->addSampler(); |
553 | m_pPlayerManager->addSampler(); |
554 | |
555 | === modified file 'mixxx/src/soundmanager.cpp' |
556 | --- mixxx/src/soundmanager.cpp 2012-10-06 00:31:03 +0000 |
557 | +++ mixxx/src/soundmanager.cpp 2012-10-22 14:36:20 +0000 |
558 | @@ -177,7 +177,11 @@ |
559 | // Need to tell all registered AudioDestinations for this AudioInput |
560 | // that the input was disconnected. |
561 | if (m_registeredDestinations.contains(in)) { |
562 | - m_registeredDestinations[in]->onInputDisconnected(in); |
563 | + QList<AudioDestination*> destList = m_registeredDestinations.values(in); |
564 | + AudioDestination* dest; |
565 | + foreach(dest, destList) { |
566 | + dest->onInputDisconnected(in); |
567 | + } |
568 | } |
569 | |
570 | short *buffer = m_inputBuffers[in]; |
571 | @@ -323,7 +327,11 @@ |
572 | // Check if any AudioDestination is registered for this AudioInput, |
573 | // and call the onInputConnected method. |
574 | if (m_registeredDestinations.contains(in)) { |
575 | - m_registeredDestinations[in]->onInputConnected(in); |
576 | + QList<AudioDestination*> destList = m_registeredDestinations.values(in); |
577 | + AudioDestination* dest; |
578 | + foreach(dest, destList) { |
579 | + dest->onInputConnected(in); |
580 | + } |
581 | } |
582 | } |
583 | foreach (AudioOutput out, m_config.getOutputs().values(device->getInternalName())) { |
584 | @@ -588,9 +596,12 @@ |
585 | short* pInputBuffer = m_inputBuffers[in]; |
586 | |
587 | if (m_registeredDestinations.contains(in)) { |
588 | - AudioDestination* destination = m_registeredDestinations[in]; |
589 | - if (destination) { |
590 | - destination->receiveBuffer(in, pInputBuffer, iFramesPerBuffer); |
591 | + QList<AudioDestination*> destList = m_registeredDestinations.values(in); |
592 | + AudioDestination* dest; |
593 | + foreach(dest, destList) { |
594 | + if(dest) { |
595 | + dest->receiveBuffer(in, pInputBuffer, iFramesPerBuffer); |
596 | + } |
597 | } |
598 | } |
599 | } |
600 | @@ -613,7 +624,9 @@ |
601 | // AudioInput to be going to a different AudioDest -bkgood |
602 | qDebug() << "WARNING: AudioInput already registered!"; |
603 | } |
604 | - m_registeredDestinations[input] = dest; |
605 | + |
606 | + m_registeredDestinations.insertMulti(input, dest); |
607 | + |
608 | emit(inputRegistered(input, dest)); |
609 | } |
610 |
Thanks Matt -- Owen merged this a few days ago.