Merge lp:~ywwg/mixxx/features_xwax2 into lp:~mixxxdevelopers/mixxx/trunk

Proposed by Owen Williams
Status: Superseded
Proposed branch: lp:~ywwg/mixxx/features_xwax2
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 1496 lines (+492/-161) (has conflicts)
28 files modified
mixxx/lib/xwax/timecoder.c (+1/-1)
mixxx/lib/xwax/timecoder_win32.cpp (+1/-1)
mixxx/src/dlgprefnovinyldlg.ui (+67/-0)
mixxx/src/dlgprefvinyl.cpp (+3/-0)
mixxx/src/dlgprefvinyldlg.ui (+7/-0)
mixxx/src/engine/enginebuffer.cpp (+3/-0)
mixxx/src/engine/enginebufferscalelinear.cpp (+0/-10)
mixxx/src/engine/enginedeck.cpp (+1/-2)
mixxx/src/engine/enginevinylsoundemu.cpp (+29/-25)
mixxx/src/engine/enginevinylsoundemu.h (+1/-1)
mixxx/src/engine/vinylcontrolcontrol.cpp (+6/-0)
mixxx/src/engine/vinylcontrolcontrol.h (+2/-0)
mixxx/src/mixxx.cpp (+9/-35)
mixxx/src/skin/legacyskinparser.cpp (+4/-2)
mixxx/src/skin/legacyskinparser.h (+3/-1)
mixxx/src/skin/skinloader.cpp (+4/-2)
mixxx/src/skin/skinloader.h (+2/-1)
mixxx/src/soundmanager.cpp (+1/-0)
mixxx/src/vinylcontrol/vinylcontrol.cpp (+15/-2)
mixxx/src/vinylcontrol/vinylcontrol.h (+6/-1)
mixxx/src/vinylcontrol/vinylcontrolmanager.cpp (+2/-6)
mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp (+1/-1)
mixxx/src/vinylcontrol/vinylcontrolxwax.cpp (+103/-57)
mixxx/src/vinylcontrol/vinylcontrolxwax.h (+1/-0)
mixxx/src/waveform/waveformrenderer.cpp (+24/-1)
mixxx/src/waveform/waveformrenderer.h (+2/-1)
mixxx/src/widget/wspinny.cpp (+169/-10)
mixxx/src/widget/wspinny.h (+25/-1)
Text conflict in mixxx/src/dlgprefnovinyldlg.ui
To merge this branch: bzr merge lp:~ywwg/mixxx/features_xwax2
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Pending
Review via email: mp+69904@code.launchpad.net

Description of the change

I've continued working in features_xwax2 to make some fixes and updates to the vinyl control code. It would be nice if some of these fixes could go into trunk, other new features can probably wait if it breaks freeze too badly.

New Features:
* Show signal quality inside WSpinny
* More pleasant waveform stretching

Fixes:
* fix vinylsoundemu and take equivalent code out of EBSL
* when loading a track, update track duration with correct value
* keep vinyl control enabled when changing vinyl control preferences
* Absolute mode fixes (better for scratching)

To post a comment you must log in.
Revision history for this message
William Good (bkgood) wrote :
Download full text (59.9 KiB)

Changes in trunk won't go out until after 1.10, should this be retargeted at
LP:mixxx/1.10?
Bill

On Jul 30, 2011 3:21 PM, "Owen Williams" <email address hidden> wrote:
>
> Owen Williams has proposed merging lp:~ywwg/mixxx/features_xwax2 into
lp:mixxx.
>
> Requested reviews:
> RJ Ryan (rryan)
> Related bugs:
> Bug #528113 in Mixxx: "Vinyl control signal quality doesn't refresh"
> https://bugs.launchpad.net/mixxx/+bug/528113
> Bug #624925 in Mixxx: "Mixxx should switch to relative mode if looping is
enabled in absolute mode"
> https://bugs.launchpad.net/mixxx/+bug/624925
> Bug #624931 in Mixxx: "Scale BPM display does not work for vinyl control
in Mixxx 1.8 and below"
> https://bugs.launchpad.net/mixxx/+bug/624931
> Bug #669289 in Mixxx: "Enable needle cueing in relative mode"
> https://bugs.launchpad.net/mixxx/+bug/669289
> Bug #672758 in Mixxx: "Support 45 rpm vinyl mode"
> https://bugs.launchpad.net/mixxx/+bug/672758
>
> For more details, see:
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
>
> I've continued working in features_xwax2 to make some fixes and updates to
the vinyl control code. It would be nice if some of these fixes could go
into trunk, other new features can probably wait if it breaks freeze too
badly.
>
> New Features:
> * Show signal quality inside WSpinny
> * More pleasant waveform stretching
>
> Fixes:
> * fix vinylsoundemu and take equivalent code out of EBSL
> * when loading a track, update track duration with correct value
> * keep vinyl control enabled when changing vinyl control preferences
> * Absolute mode fixes (better for scratching)
> --
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
> Your team Mixxx Development Team is subscribed to branch lp:mixxx.
>
> === modified file 'mixxx/lib/xwax/timecoder.c'
> --- mixxx/lib/xwax/timecoder.c 2011-05-25 19:52:14 +0000
> +++ mixxx/lib/xwax/timecoder.c 2011-07-30 20:21:03 +0000
> @@ -519,7 +519,7 @@
>
> if (r >= 0) {
> //normalize position to milliseconds, not timecode steps --
Owen
> - r = r * 1000 / (tc->def->resolution * tc->speed);
> + r = (float)r * (1000.0 / (tc->def->resolution *
tc->speed));
> if (when)
> *when = tc->timecode_ticker * tc->dt;
> return r;
>
> === modified file 'mixxx/lib/xwax/timecoder_win32.cpp'
> --- mixxx/lib/xwax/timecoder_win32.cpp 2011-05-25 19:52:14 +0000
> +++ mixxx/lib/xwax/timecoder_win32.cpp 2011-07-30 20:21:03 +0000
> @@ -521,7 +521,7 @@
>
> if (r >= 0) {
> //normalize position to milliseconds, not timecode steps --
Owen
> - r = r * 1000 / (tc->def->resolution * tc->speed);
> + r = (float)r * (1000.0 / (tc->def->resolution *
tc->speed));
> if (when)
> *when = tc->timecode_ticker * tc->dt;
> return r;
>
> === modified file 'mixxx/src/dlgprefnovinyldlg.ui'
> --- mixxx/src/dlgprefnovinyldlg.ui 2011-05-26 10:22:03 +0000
> +++ mixxx/src/dlgprefnovinyldlg.ui 2011-07-30 20:21:03 +0000
> @@ -9,8 +9,13 @@
> <rect>
> <x>0</x>
> <y>0</y>
> +<<<<<<< TREE
> <width>461</width>
> <height...

Revision history for this message
Owen Williams (ywwg) wrote :

Right, 1.10. I've resubmitted the proposal with my intended target

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

Have the two branches diverged yet? Anyway i'll take a look. thanks owen!

On Sun, Jul 31, 2011 at 8:15 AM, Owen Williams <email address hidden> wrote:

> Right, 1.10. I've resubmitted the proposal with my intended target
> --
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
> You are requested to review the proposed merge of
> lp:~ywwg/mixxx/features_xwax2 into lp:mixxx.
>

lp:~ywwg/mixxx/features_xwax2 updated
2664. By Owen Williams

Merge from lp:mixxx

2665. By Owen Williams

Calculate fabs value once, not three times

2666. By Owen Williams

Replace explicit number with #defined value

2667. By Owen Williams

Optimizing vinyl sound emu:
* precompute random values for dithering
* don't repeatedly calculate absolute value

2668. By Owen Williams

Also randomize position in noise buffer so right and left aren't aligned

2669. By Owen Williams

Always record pitch for steadypitch, not just when we have position

2670. By Owen Williams

Retweak pitch smoothing tweak. Make sure spurious values aren't in the ringbuffer

2671. By Owen Williams

Don't use static variables

2672. By Owen Williams

Merge from lp:mixxx

2673. By Owen Williams

include genre in search results

2674. By Owen Williams

merge from lp:mixxx

2675. By Owen Williams

Abstractify vinyl proxies more

2676. By Owen Williams

Don't change metadata-reported duration

2677. By Owen Williams

merge from lp:mixxx

2678. By Owen Williams

Merge with lp:mixxx

2679. By Owen Williams

merge from lp:mixxx

2680. By Owen Williams

merged into trunk

2681. By Owen Williams

merge from lp:mixxx

2682. By Owen Williams

If rate is exactly 1.0, don't scale audio at all

2683. By Owen Williams

Since my wave writer code is so useful, make it something I can #define to enable

2684. By Owen Williams

Create vinylcontrol_scratching CO that is 1 when pitch is changing rapidly and 0 when not.
Use new vinylcontrol_scatching CO to trigger swap between keylock and linear scaling in engine.

2685. By Owen Williams

Vinyl Control bugfixes:
  * fix steady pitch detector to work in reverse and better detect loops
  * try not to enter track selection mode when scratching

2686. By Owen Williams

typo

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mixxx/lib/xwax/timecoder.c'
--- mixxx/lib/xwax/timecoder.c 2011-05-25 19:52:14 +0000
+++ mixxx/lib/xwax/timecoder.c 2011-07-30 20:21:03 +0000
@@ -519,7 +519,7 @@
519519
520 if (r >= 0) {520 if (r >= 0) {
521 //normalize position to milliseconds, not timecode steps -- Owen521 //normalize position to milliseconds, not timecode steps -- Owen
522 r = r * 1000 / (tc->def->resolution * tc->speed);522 r = (float)r * (1000.0 / (tc->def->resolution * tc->speed));
523 if (when)523 if (when)
524 *when = tc->timecode_ticker * tc->dt;524 *when = tc->timecode_ticker * tc->dt;
525 return r;525 return r;
526526
=== modified file 'mixxx/lib/xwax/timecoder_win32.cpp'
--- mixxx/lib/xwax/timecoder_win32.cpp 2011-05-25 19:52:14 +0000
+++ mixxx/lib/xwax/timecoder_win32.cpp 2011-07-30 20:21:03 +0000
@@ -521,7 +521,7 @@
521521
522 if (r >= 0) {522 if (r >= 0) {
523 //normalize position to milliseconds, not timecode steps -- Owen523 //normalize position to milliseconds, not timecode steps -- Owen
524 r = r * 1000 / (tc->def->resolution * tc->speed);524 r = (float)r * (1000.0 / (tc->def->resolution * tc->speed));
525 if (when)525 if (when)
526 *when = tc->timecode_ticker * tc->dt;526 *when = tc->timecode_ticker * tc->dt;
527 return r;527 return r;
528528
=== modified file 'mixxx/src/dlgprefnovinyldlg.ui'
--- mixxx/src/dlgprefnovinyldlg.ui 2011-05-26 10:22:03 +0000
+++ mixxx/src/dlgprefnovinyldlg.ui 2011-07-30 20:21:03 +0000
@@ -9,8 +9,13 @@
9 <rect>9 <rect>
10 <x>0</x>10 <x>0</x>
11 <y>0</y>11 <y>0</y>
12<<<<<<< TREE
12 <width>461</width>13 <width>461</width>
13 <height>527</height>14 <height>527</height>
15=======
16 <width>504</width>
17 <height>501</height>
18>>>>>>> MERGE-SOURCE
14 </rect>19 </rect>
15 </property>20 </property>
16 <property name="windowTitle">21 <property name="windowTitle">
@@ -317,6 +322,13 @@
317 </property>322 </property>
318 </spacer>323 </spacer>
319 </item>324 </item>
325 <item row="3" column="0" colspan="3">
326 <widget class="QCheckBox" name="SignalQualityEnable">
327 <property name="text">
328 <string>Show Signal Quality in Skin</string>
329 </property>
330 </widget>
331 </item>
320 </layout>332 </layout>
321 </widget>333 </widget>
322 </item>334 </item>
@@ -406,9 +418,26 @@
406 </property>418 </property>
407 </spacer>419 </spacer>
408 </item>420 </item>
421 <item row="1" column="0">
422 <widget class="QLabel" name="label">
423 <property name="enabled">
424 <bool>false</bool>
425 </property>
426 <property name="toolTip">
427 <string>http://www.xwax.co.uk</string>
428 </property>
429 <property name="text">
430 <string>Powered by xwax</string>
431 </property>
432 <property name="alignment">
433 <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
434 </property>
435 </widget>
436 </item>
409 </layout>437 </layout>
410 </widget>438 </widget>
411 </item>439 </item>
440<<<<<<< TREE
412 <item row="6" column="0" colspan="2">441 <item row="6" column="0" colspan="2">
413 <widget class="QLabel" name="label_3">442 <widget class="QLabel" name="label_3">
414 <property name="text">443 <property name="text">
@@ -458,6 +487,9 @@
458 </widget>487 </widget>
459 </item>488 </item>
460 <item row="6" column="2" rowspan="2">489 <item row="6" column="2" rowspan="2">
490=======
491 <item row="6" column="2">
492>>>>>>> MERGE-SOURCE
461 <spacer name="verticalSpacer">493 <spacer name="verticalSpacer">
462 <property name="orientation">494 <property name="orientation">
463 <enum>Qt::Vertical</enum>495 <enum>Qt::Vertical</enum>
@@ -470,6 +502,41 @@
470 </property>502 </property>
471 </spacer>503 </spacer>
472 </item>504 </item>
505<<<<<<< TREE
506=======
507 <item row="5" column="2">
508 <widget class="QPushButton" name="applyButton">
509 <property name="enabled">
510 <bool>false</bool>
511 </property>
512 <property name="sizePolicy">
513 <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
514 <horstretch>0</horstretch>
515 <verstretch>0</verstretch>
516 </sizepolicy>
517 </property>
518 <property name="sizeHint" stdset="0">
519 <size>
520 <width>85</width>
521 <height>27</height>
522 </size>
523 </property>
524 <property name="text">
525 <string>Apply</string>
526 </property>
527 </widget>
528 </item>
529 <item row="5" column="0" colspan="2">
530 <widget class="QLabel" name="label_3">
531 <property name="text">
532 <string>&lt;b&gt;This version of Mixxx does not support vinyl control.&lt;/b&gt; &lt;br&gt; Please visit &lt;a href=&quot;http://mixxx.org&quot;&gt;Mixxx.org&lt;/a&gt; for more information.</string>
533 </property>
534 <property name="wordWrap">
535 <bool>true</bool>
536 </property>
537 </widget>
538 </item>
539>>>>>>> MERGE-SOURCE
473 </layout>540 </layout>
474 </widget>541 </widget>
475 <layoutdefault spacing="6" margin="11"/>542 <layoutdefault spacing="6" margin="11"/>
476543
=== modified file 'mixxx/src/dlgprefvinyl.cpp'
--- mixxx/src/dlgprefvinyl.cpp 2011-05-11 04:38:17 +0000
+++ mixxx/src/dlgprefvinyl.cpp 2011-07-30 20:21:03 +0000
@@ -137,6 +137,8 @@
137137
138 // Honour the Needle Skip Prevention setting.138 // Honour the Needle Skip Prevention setting.
139 NeedleSkipEnable->setChecked( (bool)config->getValueString( ConfigKey("[VinylControl]", "needle_skip_prevention") ).toInt() );139 NeedleSkipEnable->setChecked( (bool)config->getValueString( ConfigKey("[VinylControl]", "needle_skip_prevention") ).toInt() );
140
141 SignalQualityEnable->setChecked((bool)config->getValueString(ConfigKey("[VinylControl]", "show_signal_quality") ).toInt() );
140142
141 //set vinyl control gain143 //set vinyl control gain
142 VinylGain->setValue( config->getValueString(ConfigKey("[VinylControl]","gain")).toInt());144 VinylGain->setValue( config->getValueString(ConfigKey("[VinylControl]","gain")).toInt());
@@ -182,6 +184,7 @@
182 m_COMode.slotSet(iMode);184 m_COMode.slotSet(iMode);
183 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));185 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));
184 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );186 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );
187 config->set(ConfigKey("[VinylControl]","show_signal_quality" ), ConfigValue( (int)(SignalQualityEnable->isChecked( )) ) );
185188
186 m_pVCManager->reloadConfig();189 m_pVCManager->reloadConfig();
187 slotUpdate();190 slotUpdate();
188191
=== modified file 'mixxx/src/dlgprefvinyldlg.ui'
--- mixxx/src/dlgprefvinyldlg.ui 2011-05-26 10:22:03 +0000
+++ mixxx/src/dlgprefvinyldlg.ui 2011-07-30 20:21:03 +0000
@@ -308,6 +308,13 @@
308 </property>308 </property>
309 </spacer>309 </spacer>
310 </item>310 </item>
311 <item row="3" column="0" colspan="3">
312 <widget class="QCheckBox" name="SignalQualityEnable">
313 <property name="text">
314 <string>Show Signal Quality in Skin</string>
315 </property>
316 </widget>
317 </item>
311 </layout>318 </layout>
312 </widget>319 </widget>
313 </item>320 </item>
314321
=== modified file 'mixxx/src/engine/enginebuffer.cpp'
--- mixxx/src/engine/enginebuffer.cpp 2011-05-01 19:10:21 +0000
+++ mixxx/src/engine/enginebuffer.cpp 2011-07-30 20:21:03 +0000
@@ -336,6 +336,9 @@
336 m_pTrackSampleRate->set(iTrackSampleRate);336 m_pTrackSampleRate->set(iTrackSampleRate);
337 slotControlSeek(0.);337 slotControlSeek(0.);
338338
339 //fix the duration
340 pTrack->setDuration(iTrackNumSamples / (2 * iTrackSampleRate));
341
339342
340 // Let the engine know that a track is loaded now.343 // Let the engine know that a track is loaded now.
341 m_pTrackEndCOT->slotSet(0.0f); //XXX: Not sure if to use the COT or CO here344 m_pTrackEndCOT->slotSet(0.0f); //XXX: Not sure if to use the COT or CO here
342345
=== modified file 'mixxx/src/engine/enginebufferscalelinear.cpp'
--- mixxx/src/engine/enginebufferscalelinear.cpp 2011-04-16 20:51:48 +0000
+++ mixxx/src/engine/enginebufferscalelinear.cpp 2011-07-30 20:21:03 +0000
@@ -326,16 +326,6 @@
326 //at extremely low speeds, dampen the gain to hide pops and clicks326 //at extremely low speeds, dampen the gain to hide pops and clicks
327 //this does cause odd-looking linear waveforms that go to zero and back327 //this does cause odd-looking linear waveforms that go to zero and back
328328
329 //although enginevinylsoundemu does this, it works much better here
330 //because the gain ramps as the rate does
331 if (fabs(rate_add) < 0.5) {
332 float dither = (float)(rand() % 32768) / 32768 - 0.5; // dither
333 //float dither = 0;
334 float gainfrac = fabs(rate_add) / 0.5;
335 buf[i] = gainfrac * (float)buf[i] + dither;
336 buf[i+1] = gainfrac * (float)buf[i+1] + dither;
337 }
338
339 /*writer << QString("%1,%2,%3,%4\n").arg(buffer_count)329 /*writer << QString("%1,%2,%3,%4\n").arg(buffer_count)
340 .arg(buffer[i])330 .arg(buffer[i])
341 .arg(prev_sample[0])331 .arg(prev_sample[0])
342332
=== modified file 'mixxx/src/engine/enginedeck.cpp'
--- mixxx/src/engine/enginedeck.cpp 2011-04-15 22:19:45 +0000
+++ mixxx/src/engine/enginedeck.cpp 2011-07-30 20:21:03 +0000
@@ -54,8 +54,7 @@
54 // Process the raw audio54 // Process the raw audio
55 m_pBuffer->process(0, pOut, iBufferSize);55 m_pBuffer->process(0, pOut, iBufferSize);
56 // Emulate vinyl sounds56 // Emulate vinyl sounds
57 // This causes popping, disable -Owen57 m_pVinylSoundEmu->process(pOut, pOut, iBufferSize);
58 //m_pVinylSoundEmu->process(pOut, pOut, iBufferSize);
59 // Apply pregain58 // Apply pregain
60 m_pPregain->process(pOut, pOut, iBufferSize);59 m_pPregain->process(pOut, pOut, iBufferSize);
61 // Filter the channel with EQs60 // Filter the channel with EQs
6261
=== modified file 'mixxx/src/engine/enginevinylsoundemu.cpp'
--- mixxx/src/engine/enginevinylsoundemu.cpp 2010-09-17 04:15:33 +0000
+++ mixxx/src/engine/enginevinylsoundemu.cpp 2011-07-30 20:21:03 +0000
@@ -23,7 +23,7 @@
2323
24/** This class emulates the response of a vinyl record's audio to changes24/** This class emulates the response of a vinyl record's audio to changes
25 * in speed. In practice, it quiets the audio during very slow playback.25 * in speed. In practice, it quiets the audio during very slow playback.
26 * This also helps mask the aliasing due to interpolation that occurs at26 * Dithering also helps mask the aliasing due to interpolation that occurs at
27 * these slow speeds.27 * these slow speeds.
28 */28 */
2929
@@ -31,7 +31,7 @@
31{31{
32 m_pConfig = pConfig;32 m_pConfig = pConfig;
33 m_pRateEngine = ControlObject::getControl(ConfigKey(group, "rateEngine"));33 m_pRateEngine = ControlObject::getControl(ConfigKey(group, "rateEngine"));
34 m_fAbsSpeed = 0.0f;34 m_fSpeed = m_fOldSpeed = 0.0f;
35 m_fGainFactor = 1.0f;35 m_fGainFactor = 1.0f;
36}36}
3737
@@ -43,30 +43,34 @@
43void EngineVinylSoundEmu::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize)43void EngineVinylSoundEmu::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize)
44{44{
45 CSAMPLE * pOutput = (CSAMPLE *)pOut;45 CSAMPLE * pOutput = (CSAMPLE *)pOut;
46 m_fAbsSpeed = fabs((float)m_pRateEngine->get());46 m_fSpeed = (float)m_pRateEngine->get();
47 //qDebug() << m_pRateEngine->get();47 float rateFrac = 2 * (m_fSpeed - m_fOldSpeed) / (float)iBufferSize;
48 float curRate = m_fOldSpeed;
48 49
49 const float thresholdSpeed = 0.070f; //Scale volume if playback speed is below 7%.50 const float thresholdSpeed = 0.070f; //Scale volume if playback speed is below 7%.
50 if (m_fAbsSpeed < thresholdSpeed && m_fAbsSpeed > 0.0f) //Change the volume based on the playback speed.51 const float ditherSpeed = 0.85f; //Dither if playback speed is below 85%.
51 {52
52 //The numbers in this formula are important:53 //iterate over old rate to new rate to prevent audible pops
53 // - The "1 + ..." makes the minimum value of the parameter of log1054 for (int i=0; i<iBufferSize; i+=2)
54 // be 1, which makes the gain 0.55 {
55 // - The "* 9" makes the maximum value of the log10 become 10 (9 + 1 = 10)56 float dither = 0;
56 // which gives a gain of 157 if (fabs(curRate) < ditherSpeed) {
57 //m_fGainFactor = log10(1 + m_fAbsSpeed/0.50f * 9);58 dither = (float)(rand() % 32768) / 32768 - 0.5;
58 m_fGainFactor = m_fAbsSpeed/thresholdSpeed;59 }
59 //qDebug() << m_fGainFactor << m_fAbsSpeed;60
60 }61 if (fabs(curRate) < thresholdSpeed) {
61 else if (m_fAbsSpeed == 0.0f)62 float gainfrac = fabs(curRate) / thresholdSpeed;
62 m_fGainFactor = 0.0f; //Log blows up at 0 :)63 pOutput[i] = gainfrac * (float)pIn[i] + dither;
63 else 64 pOutput[i+1] = gainfrac * (float)pIn[i+1] + dither;
64 {65 }
65 m_fGainFactor = 1.0f;66 else
66 }67 {
6768 pOutput[i] = pIn[i] + dither;
68 // Apply whatever gain we calculated. SampleUtil takes care of aliased69 pOutput[i+1] = pIn[i+1] + dither;
69 // buffers and gains of 1 or 0.70 }
70 SampleUtil::copyWithGain(pOutput, pIn, m_fGainFactor, iBufferSize);71
72 curRate += rateFrac;
73 }
74 m_fOldSpeed = m_fSpeed;
71}75}
7276
7377
=== modified file 'mixxx/src/engine/enginevinylsoundemu.h'
--- mixxx/src/engine/enginevinylsoundemu.h 2009-01-24 04:39:32 +0000
+++ mixxx/src/engine/enginevinylsoundemu.h 2011-07-30 20:21:03 +0000
@@ -28,7 +28,7 @@
28private:28private:
29 ConfigObject<ConfigValue> *m_pConfig;29 ConfigObject<ConfigValue> *m_pConfig;
30 ControlObject *m_pRateEngine;30 ControlObject *m_pRateEngine;
31 float m_fAbsSpeed;31 float m_fSpeed, m_fOldSpeed;
32 float m_fGainFactor;32 float m_fGainFactor;
33};33};
3434
3535
=== modified file 'mixxx/src/engine/vinylcontrolcontrol.cpp'
--- mixxx/src/engine/vinylcontrolcontrol.cpp 2011-05-11 04:38:17 +0000
+++ mixxx/src/engine/vinylcontrolcontrol.cpp 2011-07-30 20:21:03 +0000
@@ -27,12 +27,18 @@
27 m_pControlVinylEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_enabled"));27 m_pControlVinylEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_enabled"));
28 m_pControlVinylEnabled->set(0);28 m_pControlVinylEnabled->set(0);
29 m_pControlVinylEnabled->setToggleButton(true);29 m_pControlVinylEnabled->setToggleButton(true);
30 m_pControlVinylWantEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_wantenabled"));
31 m_pControlVinylWantEnabled->set(0);
32 m_pControlVinylWantEnabled->setToggleButton(true);
30 m_pControlVinylMode = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_mode"));33 m_pControlVinylMode = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_mode"));
31 m_pControlVinylMode->setStates(3);34 m_pControlVinylMode->setStates(3);
32 m_pControlVinylMode->setToggleButton(true);35 m_pControlVinylMode->setToggleButton(true);
33 m_pControlVinylCueing = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_cueing"));36 m_pControlVinylCueing = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_cueing"));
34 m_pControlVinylCueing->setStates(3);37 m_pControlVinylCueing->setStates(3);
35 m_pControlVinylCueing->setToggleButton(true);38 m_pControlVinylCueing->setToggleButton(true);
39 m_pControlVinylSignalEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_signal_enabled"));
40 m_pControlVinylSignalEnabled->set(1);
41 m_pControlVinylSignalEnabled->setToggleButton(true);
36}42}
3743
38VinylControlControl::~VinylControlControl() {44VinylControlControl::~VinylControlControl() {
3945
=== modified file 'mixxx/src/engine/vinylcontrolcontrol.h'
--- mixxx/src/engine/vinylcontrolcontrol.h 2011-05-11 04:38:17 +0000
+++ mixxx/src/engine/vinylcontrolcontrol.h 2011-07-30 20:21:03 +0000
@@ -25,7 +25,9 @@
25 ControlObject* m_pControlVinylStatus;25 ControlObject* m_pControlVinylStatus;
26 ControlPushButton* m_pControlVinylMode;26 ControlPushButton* m_pControlVinylMode;
27 ControlPushButton* m_pControlVinylEnabled;27 ControlPushButton* m_pControlVinylEnabled;
28 ControlPushButton* m_pControlVinylWantEnabled;
28 ControlPushButton* m_pControlVinylCueing;29 ControlPushButton* m_pControlVinylCueing;
30 ControlPushButton* m_pControlVinylSignalEnabled;
29 TrackPointer m_pCurrentTrack;31 TrackPointer m_pCurrentTrack;
30};32};
3133
3234
=== modified file 'mixxx/src/mixxx.cpp'
--- mixxx/src/mixxx.cpp 2011-05-06 09:45:12 +0000
+++ mixxx/src/mixxx.cpp 2011-07-30 20:21:03 +0000
@@ -481,7 +481,8 @@
481 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,481 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,
482 m_pKeyboard,482 m_pKeyboard,
483 m_pPlayerManager,483 m_pPlayerManager,
484 m_pLibrary))) {484 m_pLibrary,
485 m_pVCManager))) {
485 qDebug() << "Could not load default skin.";486 qDebug() << "Could not load default skin.";
486 }487 }
487488
@@ -875,9 +876,6 @@
875 // Either check or uncheck the vinyl control menu item depending on what876 // Either check or uncheck the vinyl control menu item depending on what
876 // it was saved as.877 // it was saved as.
877 m_pOptionsVinylControl->setCheckable(true);878 m_pOptionsVinylControl->setCheckable(true);
878 //make sure control is off on startup (this is redundant to vinylcontrolmanager.cpp)
879 m_pConfig->set(
880 ConfigKey("[VinylControl]", "enabled_ch1"), false);
881 m_pOptionsVinylControl->setChecked(false);879 m_pOptionsVinylControl->setChecked(false);
882 m_pOptionsVinylControl->setStatusTip(tr("Activate Vinyl Control"));880 m_pOptionsVinylControl->setStatusTip(tr("Activate Vinyl Control"));
883 m_pOptionsVinylControl->setWhatsThis(881 m_pOptionsVinylControl->setWhatsThis(
@@ -891,8 +889,6 @@
891 SLOT(slotControlVinylControl(double)));889 SLOT(slotControlVinylControl(double)));
892890
893 m_pOptionsVinylControl2->setCheckable(true);891 m_pOptionsVinylControl2->setCheckable(true);
894 m_pConfig->set(
895 ConfigKey("[VinylControl]", "enabled_ch2"), false);
896 m_pOptionsVinylControl2->setChecked(false);892 m_pOptionsVinylControl2->setChecked(false);
897 m_pOptionsVinylControl2->setStatusTip(tr("Activate Vinyl Control"));893 m_pOptionsVinylControl2->setStatusTip(tr("Activate Vinyl Control"));
898 m_pOptionsVinylControl2->setWhatsThis(894 m_pOptionsVinylControl2->setWhatsThis(
@@ -1162,15 +1158,9 @@
1162{1158{
1163#ifdef __VINYLCONTROL__1159#ifdef __VINYLCONTROL__
1164 if (m_pVCManager->vinylInputEnabled(1)) {1160 if (m_pVCManager->vinylInputEnabled(1)) {
1165 m_pConfig->set(
1166 ConfigKey("[VinylControl]", "enabled_ch1"), ConfigValue((int)toggle));
1167 m_pOptionsVinylControl->setChecked((bool)toggle);1161 m_pOptionsVinylControl->setChecked((bool)toggle);
1168 if (toggle) {
1169 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_OK);
1170 } else {
1171 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
1172 }
1173 } else {1162 } else {
1163 m_pOptionsVinylControl->setChecked(false);
1174 if (toggle) {1164 if (toggle) {
1175 QMessageBox::warning(this, tr("Mixxx"),1165 QMessageBox::warning(this, tr("Mixxx"),
1176 tr("No input device(s) select.\nPlease select your soundcard(s) "1166 tr("No input device(s) select.\nPlease select your soundcard(s) "
@@ -1179,8 +1169,6 @@
1179 QMessageBox::Ok);1169 QMessageBox::Ok);
1180 m_pPrefDlg->show();1170 m_pPrefDlg->show();
1181 m_pPrefDlg->showSoundHardwarePage();1171 m_pPrefDlg->showSoundHardwarePage();
1182 m_pOptionsVinylControl->setChecked(false);
1183 m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"), ConfigValue(0));
1184 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);1172 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
1185 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set(0);1173 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set(0);
1186 }1174 }
@@ -1191,27 +1179,17 @@
1191void MixxxApp::slotCheckboxVinylControl(bool toggle)1179void MixxxApp::slotCheckboxVinylControl(bool toggle)
1192{1180{
1193#ifdef __VINYLCONTROL__1181#ifdef __VINYLCONTROL__
1194 bool current = (bool)m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch1")).toInt();1182 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set((double)toggle);
1195 if (current != toggle) {
1196 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set((double)toggle);
1197 }
1198#endif1183#endif
1199}1184}
12001185
1201void MixxxApp::slotControlVinylControl2(double toggle)1186void MixxxApp::slotControlVinylControl2(double toggle)
1202{1187{
1203#ifdef __VINYLCONTROL__1188#ifdef __VINYLCONTROL__
1204 //we just need at least 1 input (deck 1) because of single deck mode
1205 if (m_pVCManager->vinylInputEnabled(2)) {1189 if (m_pVCManager->vinylInputEnabled(2)) {
1206 m_pConfig->set(1190 m_pOptionsVinylControl2->setChecked((bool)toggle);
1207 ConfigKey("[VinylControl]", "enabled_ch2"), ConfigValue((int)toggle));
1208 m_pOptionsVinylControl2->setChecked((bool)toggle);
1209 if (toggle) {
1210 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_OK);
1211 } else {
1212 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
1213 }
1214 } else {1191 } else {
1192 m_pOptionsVinylControl2->setChecked(false);
1215 if (toggle) {1193 if (toggle) {
1216 QMessageBox::warning(this, tr("Mixxx"),1194 QMessageBox::warning(this, tr("Mixxx"),
1217 tr("No input device(s) select.\nPlease select your soundcard(s) "1195 tr("No input device(s) select.\nPlease select your soundcard(s) "
@@ -1220,8 +1198,6 @@
1220 QMessageBox::Ok);1198 QMessageBox::Ok);
1221 m_pPrefDlg->show();1199 m_pPrefDlg->show();
1222 m_pPrefDlg->showSoundHardwarePage();1200 m_pPrefDlg->showSoundHardwarePage();
1223 m_pOptionsVinylControl2->setChecked(false);
1224 m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"), ConfigValue(0));
1225 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);1201 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
1226 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set(0);1202 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set(0);
1227 }1203 }
@@ -1232,10 +1208,7 @@
1232void MixxxApp::slotCheckboxVinylControl2(bool toggle)1208void MixxxApp::slotCheckboxVinylControl2(bool toggle)
1233{1209{
1234#ifdef __VINYLCONTROL__1210#ifdef __VINYLCONTROL__
1235 bool current = (bool)m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch2")).toInt();1211 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set((double)toggle);
1236 if (current != toggle) {
1237 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set((double)toggle);
1238 }
1239#endif1212#endif
1240}1213}
12411214
@@ -1428,7 +1401,8 @@
1428 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,1401 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,
1429 m_pKeyboard,1402 m_pKeyboard,
1430 m_pPlayerManager,1403 m_pPlayerManager,
1431 m_pLibrary))) {1404 m_pLibrary,
1405 m_pVCManager))) {
1432 qDebug() << "Could not reload the skin.";1406 qDebug() << "Could not reload the skin.";
1433 }1407 }
14341408
14351409
=== modified file 'mixxx/src/skin/legacyskinparser.cpp'
--- mixxx/src/skin/legacyskinparser.cpp 2011-05-05 21:29:33 +0000
+++ mixxx/src/skin/legacyskinparser.cpp 2011-07-30 20:21:03 +0000
@@ -58,11 +58,13 @@
58LegacySkinParser::LegacySkinParser(ConfigObject<ConfigValue>* pConfig,58LegacySkinParser::LegacySkinParser(ConfigObject<ConfigValue>* pConfig,
59 MixxxKeyboard* pKeyboard,59 MixxxKeyboard* pKeyboard,
60 PlayerManager* pPlayerManager,60 PlayerManager* pPlayerManager,
61 Library* pLibrary)61 Library* pLibrary,
62 VinylControlManager* pVCMan)
62 : m_pConfig(pConfig),63 : m_pConfig(pConfig),
63 m_pKeyboard(pKeyboard),64 m_pKeyboard(pKeyboard),
64 m_pPlayerManager(pPlayerManager),65 m_pPlayerManager(pPlayerManager),
65 m_pLibrary(pLibrary),66 m_pLibrary(pLibrary),
67 m_pVCManager(pVCMan),
66 m_pParent(NULL) {68 m_pParent(NULL) {
6769
68}70}
@@ -611,7 +613,7 @@
611QWidget* LegacySkinParser::parseSpinny(QDomElement node) {613QWidget* LegacySkinParser::parseSpinny(QDomElement node) {
612 QString channelStr = lookupNodeGroup(node);614 QString channelStr = lookupNodeGroup(node);
613 const char* pSafeChannelStr = safeChannelString(channelStr);615 const char* pSafeChannelStr = safeChannelString(channelStr);
614 WSpinny* p = new WSpinny(m_pParent);616 WSpinny* p = new WSpinny(m_pParent, m_pVCManager);
615 setupWidget(node, p);617 setupWidget(node, p);
616618
617 connect(p, SIGNAL(trackDropped(QString, QString)),619 connect(p, SIGNAL(trackDropped(QString, QString)),
618620
=== modified file 'mixxx/src/skin/legacyskinparser.h'
--- mixxx/src/skin/legacyskinparser.h 2011-04-29 03:18:02 +0000
+++ mixxx/src/skin/legacyskinparser.h 2011-07-30 20:21:03 +0000
@@ -9,6 +9,7 @@
99
10#include "configobject.h"10#include "configobject.h"
11#include "skin/skinparser.h"11#include "skin/skinparser.h"
12#include "vinylcontrol/vinylcontrolmanager.h"
1213
13class Library;14class Library;
14class MixxxKeyboard;15class MixxxKeyboard;
@@ -20,7 +21,7 @@
20 public:21 public:
21 LegacySkinParser(ConfigObject<ConfigValue>* pConfig,22 LegacySkinParser(ConfigObject<ConfigValue>* pConfig,
22 MixxxKeyboard* pKeyboard, PlayerManager* pPlayerManager,23 MixxxKeyboard* pKeyboard, PlayerManager* pPlayerManager,
23 Library* pLibrary);24 Library* pLibrary, VinylControlManager* pVCMan);
24 virtual ~LegacySkinParser();25 virtual ~LegacySkinParser();
2526
26 virtual bool canParse(QString skinPath);27 virtual bool canParse(QString skinPath);
@@ -73,6 +74,7 @@
73 MixxxKeyboard* m_pKeyboard;74 MixxxKeyboard* m_pKeyboard;
74 PlayerManager* m_pPlayerManager;75 PlayerManager* m_pPlayerManager;
75 Library* m_pLibrary;76 Library* m_pLibrary;
77 VinylControlManager* m_pVCManager;
76 QWidget *m_pParent;78 QWidget *m_pParent;
77 static QList<const char*> s_channelStrs;79 static QList<const char*> s_channelStrs;
78 static QMutex s_safeStringMutex;80 static QMutex s_safeStringMutex;
7981
=== modified file 'mixxx/src/skin/skinloader.cpp'
--- mixxx/src/skin/skinloader.cpp 2011-01-07 22:31:50 +0000
+++ mixxx/src/skin/skinloader.cpp 2011-07-30 20:21:03 +0000
@@ -5,6 +5,7 @@
5#include <QDir>5#include <QDir>
6#include <QtDebug>6#include <QtDebug>
77
8#include "vinylcontrol/vinylcontrolmanager.h"
8#include "skin/skinloader.h"9#include "skin/skinloader.h"
9#include "skin/legacyskinparser.h"10#include "skin/legacyskinparser.h"
1011
@@ -52,10 +53,11 @@
52QWidget* SkinLoader::loadDefaultSkin(QWidget* pParent,53QWidget* SkinLoader::loadDefaultSkin(QWidget* pParent,
53 MixxxKeyboard* pKeyboard,54 MixxxKeyboard* pKeyboard,
54 PlayerManager* pPlayerManager,55 PlayerManager* pPlayerManager,
55 Library* pLibrary) {56 Library* pLibrary,
57 VinylControlManager* pVCMan) {
56 QString skinPath = getConfiguredSkinPath();58 QString skinPath = getConfiguredSkinPath();
5759
58 LegacySkinParser legacy(m_pConfig, pKeyboard, pPlayerManager, pLibrary);60 LegacySkinParser legacy(m_pConfig, pKeyboard, pPlayerManager, pLibrary, pVCMan);
59 qDebug() << "Legacy can parse:" << legacy.canParse(skinPath);61 qDebug() << "Legacy can parse:" << legacy.canParse(skinPath);
60 return legacy.parseSkin(skinPath, pParent);62 return legacy.parseSkin(skinPath, pParent);
61}63}
6264
=== modified file 'mixxx/src/skin/skinloader.h'
--- mixxx/src/skin/skinloader.h 2011-01-06 19:05:52 +0000
+++ mixxx/src/skin/skinloader.h 2011-07-30 20:21:03 +0000
@@ -17,7 +17,8 @@
17 QWidget* loadDefaultSkin(QWidget* pParent,17 QWidget* loadDefaultSkin(QWidget* pParent,
18 MixxxKeyboard* pKeyboard,18 MixxxKeyboard* pKeyboard,
19 PlayerManager* pPlayerManager,19 PlayerManager* pPlayerManager,
20 Library* pLibrary);20 Library* pLibrary,
21 VinylControlManager* pVCMan);
2122
22 QString getConfiguredSkinPath();23 QString getConfiguredSkinPath();
2324
2425
=== modified file 'mixxx/src/soundmanager.cpp'
--- mixxx/src/soundmanager.cpp 2011-07-19 18:12:33 +0000
+++ mixxx/src/soundmanager.cpp 2011-07-30 20:21:03 +0000
@@ -26,6 +26,7 @@
26#include "sounddevice.h"26#include "sounddevice.h"
27#include "sounddeviceportaudio.h"27#include "sounddeviceportaudio.h"
28#include "engine/enginemaster.h"28#include "engine/enginemaster.h"
29#include "engine/enginebuffer.h"
29#include "controlobjectthreadmain.h"30#include "controlobjectthreadmain.h"
30#include "soundmanagerutil.h"31#include "soundmanagerutil.h"
31#include "controlobject.h"32#include "controlobject.h"
3233
=== modified file 'mixxx/src/vinylcontrol/vinylcontrol.cpp'
--- mixxx/src/vinylcontrol/vinylcontrol.cpp 2011-04-29 16:57:44 +0000
+++ mixxx/src/vinylcontrol/vinylcontrol.cpp 2011-07-30 20:21:03 +0000
@@ -11,6 +11,8 @@
1111
12 // Get Control objects12 // Get Control objects
13 playPos = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "playposition"))); //Range: -.14 to 1.1413 playPos = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "playposition"))); //Range: -.14 to 1.14
14 trackSamples = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "track_samples")));
15 trackSampleRate = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "track_samplerate")));
14 vinylSeek = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_seek")));16 vinylSeek = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_seek")));
15 controlScratch = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "scratch2")));17 controlScratch = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "scratch2")));
16 rateSlider = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate"))); //Range -1.0 to 1.018 rateSlider = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate"))); //Range -1.0 to 1.0
@@ -19,11 +21,13 @@
19 duration = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "duration")));21 duration = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "duration")));
20 mode = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_mode")));22 mode = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_mode")));
21 enabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_enabled")));23 enabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_enabled")));
24 wantenabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_wantenabled")));
22 cueing = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_cueing")));25 cueing = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_cueing")));
23 rateRange = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rateRange")));26 rateRange = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rateRange")));
24 vinylStatus = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_status")));27 vinylStatus = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_status")));
25 rateDir = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate_dir")));28 rateDir = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate_dir")));
26 loopEnabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "loop_enabled")));29 loopEnabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "loop_enabled")));
30 signalenabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_signal_enabled")));
2731
28 dVinylPitch = 0.0f;32 dVinylPitch = 0.0f;
29 dVinylPosition = 0.0f;33 dVinylPosition = 0.0f;
@@ -47,8 +51,8 @@
47 //Vinyl control mode51 //Vinyl control mode
48 iVCMode = m_pConfig->getValueString(ConfigKey("[VinylControl]","mode")).toInt();52 iVCMode = m_pConfig->getValueString(ConfigKey("[VinylControl]","mode")).toInt();
4953
50 //Enabled or not54 //Enabled or not -- load from saved value in case vinyl control is restarting
51 bIsEnabled = m_pConfig->getValueString(ConfigKey(group,"vinylcontrol_enabled")).toInt();55 bIsEnabled = wantenabled->get();
5256
53 //Gain57 //Gain
54 ControlObject::getControl(ConfigKey("[VinylControl]", "gain"))->set(58 ControlObject::getControl(ConfigKey("[VinylControl]", "gain"))->set(
@@ -59,7 +63,9 @@
59{63{
60 bIsEnabled = enable;64 bIsEnabled = enable;
61 if (m_pConfig)65 if (m_pConfig)
66 {
62 m_pConfig->set(ConfigKey(m_group,"vinylcontrol_enabled"), ConfigValue((int)enable));67 m_pConfig->set(ConfigKey(m_group,"vinylcontrol_enabled"), ConfigValue((int)enable));
68 }
6369
64 enabled->slotSet(enable);70 enabled->slotSet(enable);
6571
@@ -71,8 +77,15 @@
7177
72VinylControl::~VinylControl()78VinylControl::~VinylControl()
73{79{
80 bool wasEnabled = bIsEnabled;
74 enabled->slotSet(false);81 enabled->slotSet(false);
75 vinylStatus->slotSet(VINYL_STATUS_DISABLED);82 vinylStatus->slotSet(VINYL_STATUS_DISABLED);
83 if (wasEnabled)
84 {
85 //if vinyl control is just restarting, indicate that it should
86 //be enabled
87 wantenabled->slotSet(true);
88 }
76}89}
7790
78float VinylControl::getSpeed()91float VinylControl::getSpeed()
7992
=== modified file 'mixxx/src/vinylcontrol/vinylcontrol.h'
--- mixxx/src/vinylcontrol/vinylcontrol.h 2011-05-11 04:38:17 +0000
+++ mixxx/src/vinylcontrol/vinylcontrol.h 2011-07-30 20:21:03 +0000
@@ -35,7 +35,7 @@
3535
36#define MIXXX_VC_DEFAULT_LEADINTIME 036#define MIXXX_VC_DEFAULT_LEADINTIME 0
3737
38#define MIXXX_VINYL_SCOPE_SIZE 12838#define MIXXX_VINYL_SCOPE_SIZE 100
3939
40//TODO: Make this an EngineObject instead one day? (need to route all the input audio through the engine that way too...)40//TODO: Make this an EngineObject instead one day? (need to route all the input audio through the engine that way too...)
4141
@@ -62,6 +62,8 @@
62 QString m_group;62 QString m_group;
63 ControlObjectThread *playButton; //The ControlObject used to start/stop playback of the song.63 ControlObjectThread *playButton; //The ControlObject used to start/stop playback of the song.
64 ControlObjectThread *playPos; //The ControlObject used to read the playback position in the song.64 ControlObjectThread *playPos; //The ControlObject used to read the playback position in the song.
65 ControlObjectThread *trackSamples;
66 ControlObjectThread *trackSampleRate;
65 ControlObjectThread *vinylSeek; //The ControlObject used to change the playback position in the song.67 ControlObjectThread *vinylSeek; //The ControlObject used to change the playback position in the song.
66 ControlObjectThread *controlScratch; //The ControlObject used to seek when the record is spinning fast.68 ControlObjectThread *controlScratch; //The ControlObject used to seek when the record is spinning fast.
67 ControlObjectThread *rateSlider; //The ControlObject used to change the speed/pitch of the song.69 ControlObjectThread *rateSlider; //The ControlObject used to change the speed/pitch of the song.
@@ -69,11 +71,13 @@
69 ControlObjectThread *duration; //The ControlObject used to get the duration of the current song.71 ControlObjectThread *duration; //The ControlObject used to get the duration of the current song.
70 ControlObjectThread *mode; //The ControlObject used to get the vinyl control mode (absolute/relative/scratch)72 ControlObjectThread *mode; //The ControlObject used to get the vinyl control mode (absolute/relative/scratch)
71 ControlObjectThread *enabled; //The ControlObject used to get if the vinyl control is enabled or disabled.73 ControlObjectThread *enabled; //The ControlObject used to get if the vinyl control is enabled or disabled.
74 ControlObjectThread *wantenabled; //The ControlObject used to get if the vinyl control should try to enable itself
72 ControlObjectThread *cueing; //Should cueing mode be active?75 ControlObjectThread *cueing; //Should cueing mode be active?
73 ControlObjectThread *rateRange; //The ControlObject used to the get the pitch range from the prefs.76 ControlObjectThread *rateRange; //The ControlObject used to the get the pitch range from the prefs.
74 ControlObjectThread *vinylStatus;77 ControlObjectThread *vinylStatus;
75 ControlObjectThread *rateDir; //direction of rate78 ControlObjectThread *rateDir; //direction of rate
76 ControlObjectThread *loopEnabled; //looping enabled?79 ControlObjectThread *loopEnabled; //looping enabled?
80 ControlObjectThread *signalenabled; //show the signal in the skin?
77 //ControlObject *vinylStatus; //Status of vinyl control81 //ControlObject *vinylStatus; //Status of vinyl control
7882
79 int iLeadInTime; //The lead-in time...83 int iLeadInTime; //The lead-in time...
@@ -86,6 +90,7 @@
86 float fRateRange; //The pitch range setting from Mixxx's preferences90 float fRateRange; //The pitch range setting from Mixxx's preferences
87 float m_fTimecodeQuality; //Used as a measure of the quality of the timecode signal.91 float m_fTimecodeQuality; //Used as a measure of the quality of the timecode signal.
8892
93 float fTrackDuration;
89 unsigned long iSampleRate;94 unsigned long iSampleRate;
90 bool bIsEnabled;95 bool bIsEnabled;
91 int iRIAACorrection;96 int iRIAACorrection;
9297
=== modified file 'mixxx/src/vinylcontrol/vinylcontrolmanager.cpp'
--- mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 2011-07-19 20:54:56 +0000
+++ mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 2011-07-30 20:21:03 +0000
@@ -26,11 +26,9 @@
26{26{
27 // load a bunch of stuff27 // load a bunch of stuff
28 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))28 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))
29 ->queueFromThread(m_pConfig->getValueString(29 ->queueFromThread(0);
30 ConfigKey("[VinylControl]","enabled_ch1")).toDouble());
31 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))30 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))
32 ->queueFromThread(m_pConfig->getValueString(31 ->queueFromThread(0);
33 ConfigKey("[VinylControl]","enabled_ch2")).toDouble());
34 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))32 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))
35 ->queueFromThread(m_pConfig->getValueString(33 ->queueFromThread(m_pConfig->getValueString(
36 ConfigKey("[VinylControl]","mode")).toDouble());34 ConfigKey("[VinylControl]","mode")).toDouble());
@@ -62,8 +60,6 @@
6260
63 // save a bunch of stuff to config61 // save a bunch of stuff to config
64 // turn off vinyl control so it won't be enabled on load (this is redundant to mixxx.cpp)62 // turn off vinyl control so it won't be enabled on load (this is redundant to mixxx.cpp)
65 m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"), false);
66 m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"), false);
67 m_pConfig->set(ConfigKey("[Channel 1]","vinylcontrol_enabled"), false);63 m_pConfig->set(ConfigKey("[Channel 1]","vinylcontrol_enabled"), false);
68 m_pConfig->set(ConfigKey("[Channel 2]","vinylcontrol_enabled"), false);64 m_pConfig->set(ConfigKey("[Channel 2]","vinylcontrol_enabled"), false);
69 m_pConfig->set(ConfigKey("[VinylControl]","mode"),65 m_pConfig->set(ConfigKey("[VinylControl]","mode"),
7066
=== modified file 'mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp'
--- mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp 2011-04-17 04:16:00 +0000
+++ mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp 2011-07-30 20:21:03 +0000
@@ -31,7 +31,7 @@
31 : QWidget(),31 : QWidget(),
32 m_iTimerId(0),32 m_iTimerId(0),
33 m_pVinylControl(NULL),33 m_pVinylControl(NULL),
34 m_iSize(128),34 m_iSize(100),
35 m_qImage(),35 m_qImage(),
36 m_bVinylActive(FALSE) {36 m_bVinylActive(FALSE) {
37}37}
3838
=== modified file 'mixxx/src/vinylcontrol/vinylcontrolxwax.cpp'
--- mixxx/src/vinylcontrol/vinylcontrolxwax.cpp 2011-05-21 01:07:25 +0000
+++ mixxx/src/vinylcontrol/vinylcontrolxwax.cpp 2011-07-30 20:21:03 +0000
@@ -47,6 +47,7 @@
47 iOldMode = MIXXX_VCMODE_ABSOLUTE;47 iOldMode = MIXXX_VCMODE_ABSOLUTE;
48 dUiUpdateTime = -1.0f;48 dUiUpdateTime = -1.0f;
49 m_bNeedleSkipPrevention = (bool)(m_pConfig->getValueString( ConfigKey( "[VinylControl]", "needle_skip_prevention" ) ).toInt());49 m_bNeedleSkipPrevention = (bool)(m_pConfig->getValueString( ConfigKey( "[VinylControl]", "needle_skip_prevention" ) ).toInt());
50 signalenabled->slotSet(m_pConfig->getValueString( ConfigKey( "[VinylControl]", "show_signal_quality" ) ).toInt());
5051
51 dLastTrackSelectPos = 0.0;52 dLastTrackSelectPos = 0.0;
52 dCurTrackSelectPos = 0.0;53 dCurTrackSelectPos = 0.0;
@@ -97,6 +98,7 @@
97 //Note that timecoder_init will not double-malloc the LUTs, and after this we are guaranteed98 //Note that timecoder_init will not double-malloc the LUTs, and after this we are guaranteed
98 //that the LUT has been generated unless we ran out of memory.99 //that the LUT has been generated unless we ran out of memory.
99 m_bLUTInitialized = true;100 m_bLUTInitialized = true;
101 m_uiSafeZone = timecoder_get_safe(&timecoder);
100 //}102 //}
101 s_xwaxLUTMutex.unlock();103 s_xwaxLUTMutex.unlock();
102104
@@ -177,6 +179,7 @@
177 double dPitchRing[RING_SIZE];179 double dPitchRing[RING_SIZE];
178 int ringPos = 0;180 int ringPos = 0;
179 int ringFilled = 0;181 int ringFilled = 0;
182 double cur_duration = -1.0f;
180 double old_duration = -1.0f;183 double old_duration = -1.0f;
181 int reportedMode = 0;184 int reportedMode = 0;
182 bool reportedPlayButton = 0;185 bool reportedPlayButton = 0;
@@ -225,36 +228,62 @@
225 //if no track loaded, let track selection work but that's it228 //if no track loaded, let track selection work but that's it
226 if (duration == NULL)229 if (duration == NULL)
227 {230 {
228 bTrackSelectMode = true;231 //until I can figure out how to detect "track 2" on serato CD,
229 doTrackSelection(false, dVinylPitch, iPosition);232 //don't try track selection
233 if (!m_bCDControl)
234 {
235 bTrackSelectMode = true;
236 doTrackSelection(false, dVinylPitch, iPosition);
237 }
230 continue;238 continue;
231 }239 }
232 //qDebug() << m_group << id << iPosition << dVinylPitch;240 //qDebug() << m_group << id << iPosition << dVinylPitch;
233241
234 double cur_duration = duration->get();242 cur_duration = duration->get();
243
244
245 //Has a new track been loaded?
235 //FIXME? we should really sync on all track changes246 //FIXME? we should really sync on all track changes
236 if (cur_duration != old_duration)247 if (cur_duration != old_duration)
237 {248 {
238 bForceResync=true;249 bForceResync=true;
239 bTrackSelectMode = false; //just in case250 bTrackSelectMode = false; //just in case
240 old_duration = cur_duration;251 old_duration = cur_duration;
252 //duration from the control object is an integer. We need
253 //more precision:
254 fTrackDuration = trackSamples->get() / 2 / trackSampleRate->get();
255
256 //we were at record end, so turn it off and restore mode
257 if(atRecordEnd)
258 {
259 disableRecordEndMode();
260 if (iOldMode == MIXXX_VCMODE_CONSTANT)
261 iVCMode = MIXXX_VCMODE_RELATIVE;
262 else
263 iVCMode = iOldMode;
264 }
241 }265 }
242266
243 dVinylPosition = iPosition;267 //make sure dVinylPosition only has good values
244 dVinylPosition = dVinylPosition / 1000.0f;268 if (iPosition != -1)
245 dVinylPosition -= iLeadInTime;269 {
270 dVinylPosition = iPosition;
271 dVinylPosition = dVinylPosition / 1000.0f;
272 dVinylPosition -= iLeadInTime;
273 }
274
275
246276
247 //Initialize drift control to zero in case we don't get any position data to calculate it with.277 //Initialize drift control to zero in case we don't get any position data to calculate it with.
248 dDriftControl = 0.0f;278 dDriftControl = 0.0f;
249279
250 filePosition = playPos->get() * cur_duration; //Get the playback position in the file in seconds.280 filePosition = playPos->get() * fTrackDuration; //Get the playback position in the file in seconds.
251281
252 reportedMode = mode->get();282 reportedMode = mode->get();
253 reportedPlayButton = playButton->get();283 reportedPlayButton = playButton->get();
254284
255 if (iVCMode != reportedMode)285 if (iVCMode != reportedMode)
256 {286 {
257 //qDebug() << "cur mode" << iVCMode << "new mode" << reportedMode;
258 //if we are playing, don't allow change287 //if we are playing, don't allow change
259 //to absolute mode (would cause sudden track skip)288 //to absolute mode (would cause sudden track skip)
260 if (reportedPlayButton && reportedMode == MIXXX_VCMODE_ABSOLUTE)289 if (reportedPlayButton && reportedMode == MIXXX_VCMODE_ABSOLUTE)
@@ -282,7 +311,6 @@
282 iVCMode = MIXXX_VCMODE_RELATIVE;311 iVCMode = MIXXX_VCMODE_RELATIVE;
283 mode->slotSet((double)iVCMode);312 mode->slotSet((double)iVCMode);
284 }313 }
285
286 //are we newly playing near the end of the record? (in absolute mode, this happens314 //are we newly playing near the end of the record? (in absolute mode, this happens
287 //when the filepos is past safe (more accurate),315 //when the filepos is past safe (more accurate),
288 //but it can also happen in relative mode if the vinylpos is nearing the end316 //but it can also happen in relative mode if the vinylpos is nearing the end
@@ -292,13 +320,13 @@
292 {320 {
293 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)321 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)
294 {322 {
295 if ((filePosition + iLeadInTime) * 1000.0f > timecoder_get_safe(&timecoder) &&323 if ((filePosition + iLeadInTime) * 1000.0f > m_uiSafeZone &&
296 !bForceResync) //corner case: we are waiting for resync so don't enable just yet324 !bForceResync) //corner case: we are waiting for resync so don't enable just yet
297 enableRecordEndMode();325 enableRecordEndMode();
298 }326 }
299 else if (iVCMode == MIXXX_VCMODE_RELATIVE || iVCMode == MIXXX_VCMODE_CONSTANT)327 else if (iVCMode == MIXXX_VCMODE_RELATIVE || iVCMode == MIXXX_VCMODE_CONSTANT)
300 {328 {
301 if (iPosition != -1 && iPosition > timecoder_get_safe(&timecoder))329 if (iPosition != -1 && iPosition > m_uiSafeZone)
302 enableRecordEndMode();330 enableRecordEndMode();
303 }331 }
304 }332 }
@@ -307,25 +335,20 @@
307 {335 {
308 //if atRecordEnd was true, maybe it no longer applies:336 //if atRecordEnd was true, maybe it no longer applies:
309337
310 if ((iVCMode == MIXXX_VCMODE_ABSOLUTE &&338 if (!reportedPlayButton)
311 (filePosition + iLeadInTime) * 1000.0f <= timecoder_get_safe(&timecoder)))
312 {
313 //if we are in absolute mode and the file position is in a safe zone now
314 disableRecordEndMode();
315 }
316 else if (!reportedPlayButton)
317 {339 {
318 //if we turned off play button, also disable340 //if we turned off play button, also disable
319 disableRecordEndMode();341 disableRecordEndMode();
320 }342 }
321 else if (iPosition != -1)343 else if (iPosition != -1 &&
344 iPosition <= m_uiSafeZone &&
345 dVinylPosition > 0 &&
346 checkSteadyPitch(dVinylPitch, filePosition) > 0.5)
347
322 {348 {
323 //if relative mode, and vinylpos is safe349 //if good position, and safe, and not in leadin, and steady,
324 if (iVCMode == MIXXX_VCMODE_RELATIVE &&350 //disable
325 iPosition <= timecoder_get_safe(&timecoder))351 disableRecordEndMode();
326 {
327 disableRecordEndMode();
328 }
329 }352 }
330353
331 if (atRecordEnd)354 if (atRecordEnd)
@@ -345,17 +368,22 @@
345368
346 if (!atRecordEnd)369 if (!atRecordEnd)
347 {370 {
348 if (iPosition != -1 && iPosition > timecoder_get_safe(&timecoder))371 if (iPosition != -1 && iPosition > m_uiSafeZone)
349 {372 {
350 if (!bTrackSelectMode)373 //until I can figure out how to detect "track 2" on serato CD,
374 //don't try track selection
375 if (!m_bCDControl)
351 {376 {
352 qDebug() << "position greater than safe, select mode" << iPosition << timecoder_get_safe(&timecoder);377 if (!bTrackSelectMode)
353 bTrackSelectMode = true;378 {
354 togglePlayButton(FALSE);379 qDebug() << "position greater than safe, select mode" << iPosition << m_uiSafeZone;
355 resetSteadyPitch(0.0f, 0.0f);380 bTrackSelectMode = true;
356 controlScratch->slotSet(0.0f);381 togglePlayButton(FALSE);
382 resetSteadyPitch(0.0f, 0.0f);
383 controlScratch->slotSet(0.0f);
384 }
385 doTrackSelection(true, dVinylPitch, iPosition);
357 }386 }
358 doTrackSelection(true, dVinylPitch, iPosition);
359387
360 //hm I wonder if track will keep playing while this happens?388 //hm I wonder if track will keep playing while this happens?
361 //not sure what we want to do here... probably enforce389 //not sure what we want to do here... probably enforce
@@ -432,8 +460,9 @@
432460
433 //save the absolute amount of drift for when we need to estimate vinyl position461 //save the absolute amount of drift for when we need to estimate vinyl position
434 dDriftAmt = dVinylPosition - filePosition;462 dDriftAmt = dVinylPosition - filePosition;
463
464 //qDebug() << "drift" << dDriftAmt;
435465
436 //qDebug() << "vinyl" << dVinylPosition << "file" << filePosition;
437 if (bForceResync)466 if (bForceResync)
438 {467 {
439 //if forceresync was set but we're no longer absolute,468 //if forceresync was set but we're no longer absolute,
@@ -504,12 +533,14 @@
504533
505 //Calculate how much the vinyl's position has drifted from it's timecode and compensate for it.534 //Calculate how much the vinyl's position has drifted from it's timecode and compensate for it.
506 //(This is caused by the manufacturing process of the vinyl.)535 //(This is caused by the manufacturing process of the vinyl.)
507 dDriftControl = ((filePosition - dVinylPosition) / dVinylPosition) / 100 * 4.0f;536 if (fabs(dDriftAmt) > 0.1 && fabs(dDriftAmt) < 5.0) {
537 dDriftControl = dDriftAmt;
538 } else {
539 dDriftControl = 0.0;
540 }
508541
509 //if we hit the end of the ring, loop around542 //if we hit the end of the ring, loop around
510 ringPos++;543 ringPos = (ringPos + 1) % RING_SIZE;
511 if(ringPos >= RING_SIZE)
512 ringPos = 0;
513 dOldPos = dVinylPosition;544 dOldPos = dVinylPosition;
514 }545 }
515 else546 else
@@ -528,6 +559,14 @@
528 ringFilled = 0;559 ringFilled = 0;
529 continue;560 continue;
530 }561 }
562
563 if (iVCMode == MIXXX_VCMODE_ABSOLUTE &&
564 fabs(dVinylPitch) < 0.05 &&
565 fabs(dDriftAmt) >= 0.3f)
566 {
567 qDebug() << "slow, out of sync, syncing position";
568 syncPosition();
569 }
531570
532 dOldPos = filePosition + dDriftAmt;571 dOldPos = filePosition + dDriftAmt;
533572
@@ -556,13 +595,12 @@
556 else595 else
557 averagePitch = dVinylPitch;596 averagePitch = dVinylPitch;
558597
559
560 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)598 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)
561 {599 {
562 controlScratch->slotSet(averagePitch + dDriftControl);600 controlScratch->slotSet(dVinylPitch + dDriftControl);
563 if (iPosition != -1 && reportedPlayButton && uiUpdateTime(filePosition))601 if (iPosition != -1 && reportedPlayButton && uiUpdateTime(filePosition))
564 {602 {
565 rateSlider->slotSet(rateDir->get() * (fabs(averagePitch + dDriftControl) - 1.0f) / fRateRange);603 rateSlider->slotSet(rateDir->get() * (fabs(dVinylPitch + dDriftControl) - 1.0f) / fRateRange);
566 dUiUpdateTime = filePosition;604 dUiUpdateTime = filePosition;
567 }605 }
568 }606 }
@@ -587,14 +625,21 @@
587 //let the track play a wee bit more before deciding we've stopped625 //let the track play a wee bit more before deciding we've stopped
588626
589 rateSlider->slotSet(0.0f);627 rateSlider->slotSet(0.0f);
628
629 if (iVCMode == MIXXX_VCMODE_ABSOLUTE &&
630 fabs(dVinylPosition - filePosition) >= 0.1f)
631 {
632 qDebug() << "stopped, out of sync, syncing position";
633 syncPosition();
634 }
590635
591 if(fabs(filePosition - dOldFilePos) >= 0.1 ||636 if(fabs(filePosition - dOldFilePos) >= 0.1 ||
592 !m_bNeedleSkipPrevention ||637 !m_bNeedleSkipPrevention ||
593 filePosition == dOldFilePos)638 filePosition == dOldFilePos)
594 {639 {
595 //We are not playing any more640 //We are not playing any more
596 togglePlayButton(FALSE);641 togglePlayButton(FALSE);
597 resetSteadyPitch(0.0f, 0.0f);642 resetSteadyPitch(0.0f, 0.0f);
598 controlScratch->slotSet(0.0f);643 controlScratch->slotSet(0.0f);
599 //resetSteadyPitch(dVinylPitch, filePosition);644 //resetSteadyPitch(dVinylPitch, filePosition);
600 //Notify the UI that the timecode quality is garbage/missing.645 //Notify the UI that the timecode quality is garbage/missing.
@@ -643,15 +688,8 @@
643{688{
644 vinylStatus->slotSet(VINYL_STATUS_OK);689 vinylStatus->slotSet(VINYL_STATUS_OK);
645 atRecordEnd = false;690 atRecordEnd = false;
646 //don't start a new track with constant mode691 iVCMode = MIXXX_VCMODE_RELATIVE;
647 if (iVCMode == MIXXX_VCMODE_CONSTANT)692 mode->slotSet((double)iVCMode);
648 {
649 if (iOldMode == MIXXX_VCMODE_CONSTANT)
650 iVCMode = MIXXX_VCMODE_RELATIVE;
651 else
652 iVCMode = iOldMode;
653 mode->slotSet((double)iVCMode);
654 }
655}693}
656694
657void VinylControlXwax::togglePlayButton(bool on)695void VinylControlXwax::togglePlayButton(bool on)
@@ -769,11 +807,19 @@
769void VinylControlXwax::syncPosition()807void VinylControlXwax::syncPosition()
770{808{
771 //qDebug() << "sync position" << dVinylPosition / duration->get();809 //qDebug() << "sync position" << dVinylPosition / duration->get();
772 vinylSeek->slotSet(dVinylPosition / duration->get()); //VinylPos in seconds / total length of song810 vinylSeek->slotSet(dVinylPosition / fTrackDuration); //VinylPos in seconds / total length of song
773}811}
774812
775bool VinylControlXwax::checkEnabled(bool was, bool is)813bool VinylControlXwax::checkEnabled(bool was, bool is)
776{814{
815 // if we're not enabled, but the last object was, try turning ourselves on
816 // XXX: is this just a race that's working right now?
817 if (!is and wantenabled->get())
818 {
819 enabled->slotSet(true);
820 wantenabled->slotSet(false); //don't try to do this over and over
821 return true; //optimism!
822 }
777 if (was != is)823 if (was != is)
778 {824 {
779 //we reset the scratch value, but we don't reset the rate slider.825 //we reset the scratch value, but we don't reset the rate slider.
@@ -824,7 +870,9 @@
824{870{
825 bQualityRing[iQualPos] = quality_sample;871 bQualityRing[iQualPos] = quality_sample;
826 if(iQualFilled < QUALITY_RING_SIZE)872 if(iQualFilled < QUALITY_RING_SIZE)
827 iQualFilled++;873 {
874 iQualFilled++;
875 }
828876
829 int quality = 0;877 int quality = 0;
830 for (int i=0; i<iQualFilled; i++)878 for (int i=0; i<iQualFilled; i++)
@@ -836,9 +884,7 @@
836 //qDebug() << "quality" << m_fTimecodeQuality;884 //qDebug() << "quality" << m_fTimecodeQuality;
837 m_fTimecodeQuality = (float)quality / (float)iQualFilled;885 m_fTimecodeQuality = (float)quality / (float)iQualFilled;
838886
839 iQualPos++;887 iQualPos = (iQualPos + 1) % QUALITY_RING_SIZE;
840 if(iQualPos >= QUALITY_RING_SIZE)
841 iQualPos = 0;
842}888}
843889
844float VinylControlXwax::getAngle()890float VinylControlXwax::getAngle()
845891
=== modified file 'mixxx/src/vinylcontrol/vinylcontrolxwax.h'
--- mixxx/src/vinylcontrol/vinylcontrolxwax.h 2011-04-17 04:16:00 +0000
+++ mixxx/src/vinylcontrol/vinylcontrolxwax.h 2011-07-30 20:21:03 +0000
@@ -48,6 +48,7 @@
48 void establishQuality(bool quality_sample);48 void establishQuality(bool quality_sample);
4949
50 double dFileLength; // The length (in samples) of the current song.50 double dFileLength; // The length (in samples) of the current song.
51 unsigned int m_uiSafeZone; // Cache the position of the end of record
5152
52 double dOldPos; // The position read last time it was polled.53 double dOldPos; // The position read last time it was polled.
53 double dOldPitch;54 double dOldPitch;
5455
=== modified file 'mixxx/src/waveform/waveformrenderer.cpp'
--- mixxx/src/waveform/waveformrenderer.cpp 2011-04-06 21:20:35 +0000
+++ mixxx/src/waveform/waveformrenderer.cpp 2011-07-30 20:21:03 +0000
@@ -26,6 +26,8 @@
26#define DEFAULT_SUBPIXELS_PER_PIXEL 426#define DEFAULT_SUBPIXELS_PER_PIXEL 4
27#define DEFAULT_PIXELS_PER_SECOND 10027#define DEFAULT_PIXELS_PER_SECOND 100
2828
29#define RATE_INCREMENT 0.015
30
29void WaveformRenderer::run() {31void WaveformRenderer::run() {
30 double msecs_old = 0, msecs_elapsed = 0;32 double msecs_old = 0, msecs_elapsed = 0;
3133
@@ -61,6 +63,7 @@
61 m_dRate(0),63 m_dRate(0),
62 m_dRateRange(0),64 m_dRateRange(0),
63 m_dRateDir(0),65 m_dRateDir(0),
66 m_iRateAdjusting(0),
64 m_iDupes(0),67 m_iDupes(0),
65 m_dPlayPosAdjust(0),68 m_dPlayPosAdjust(0),
66 m_iLatency(0),69 m_iLatency(0),
@@ -190,7 +193,7 @@
190}193}
191194
192void WaveformRenderer::slotUpdateRate(double v) {195void WaveformRenderer::slotUpdateRate(double v) {
193 m_dRate = v;196 m_dTargetRate = v;
194}197}
195198
196void WaveformRenderer::slotUpdateRateRange(double v) {199void WaveformRenderer::slotUpdateRateRange(double v) {
@@ -501,6 +504,26 @@
501504
502 //qDebug() << m_dPlayPosAdjust;505 //qDebug() << m_dPlayPosAdjust;
503506
507 // Gradually stretch the waveform
508 if (fabs(m_dTargetRate - m_dRate) > RATE_INCREMENT)
509 {
510 if ((m_dTargetRate - m_dRate) > 0)
511 {
512 m_iRateAdjusting = m_iRateAdjusting > 0 ? m_iRateAdjusting + 1 : 1;
513 m_dRate = math_min(m_dTargetRate, m_dRate + RATE_INCREMENT * pow(m_iRateAdjusting, 2) / 80);
514 }
515 else
516 {
517 m_iRateAdjusting = m_iRateAdjusting < 0 ? m_iRateAdjusting - 1 : -1;
518 m_dRate = math_max(m_dTargetRate, m_dRate - RATE_INCREMENT * pow(m_iRateAdjusting, 2) / 80);
519 }
520 }
521 else
522 {
523 m_iRateAdjusting = 0;
524 m_dRate = m_dTargetRate;
525 }
526
504 // Limit our rate adjustment to < 99%, "Bad Things" might happen otherwise.527 // Limit our rate adjustment to < 99%, "Bad Things" might happen otherwise.
505 double rateAdjust = m_dRateDir * math_min(0.99, m_dRate * m_dRateRange);528 double rateAdjust = m_dRateDir * math_min(0.99, m_dRate * m_dRateRange);
506529
507530
=== modified file 'mixxx/src/waveform/waveformrenderer.h'
--- mixxx/src/waveform/waveformrenderer.h 2011-03-08 22:17:41 +0000
+++ mixxx/src/waveform/waveformrenderer.h 2011-07-30 20:21:03 +0000
@@ -61,7 +61,8 @@
6161
62 int m_iPlayPosTime, m_iPlayPosTimeOld;62 int m_iPlayPosTime, m_iPlayPosTimeOld;
63 QTime m_playPosTime, m_playPosTimeOld;63 QTime m_playPosTime, m_playPosTimeOld;
64 double m_dPlayPos, m_dPlayPosOld, m_dRate, m_dRateRange, m_dRateDir;64 double m_dPlayPos, m_dPlayPosOld, m_dTargetRate, m_dRate, m_dRateRange, m_dRateDir;
65 int m_iRateAdjusting;
65 int m_iDupes;66 int m_iDupes;
66 double m_dPlayPosAdjust;67 double m_dPlayPosAdjust;
67 int m_iLatency;68 int m_iLatency;
6869
=== modified file 'mixxx/src/widget/wspinny.cpp'
--- mixxx/src/widget/wspinny.cpp 2011-05-12 14:46:18 +0000
+++ mixxx/src/widget/wspinny.cpp 2011-07-30 20:21:03 +0000
@@ -6,7 +6,7 @@
6#include "sharedglcontext.h"6#include "sharedglcontext.h"
7#include "wspinny.h"7#include "wspinny.h"
88
9WSpinny::WSpinny(QWidget* parent) : QGLWidget(SharedGLContext::getContext(), parent),9WSpinny::WSpinny(QWidget* parent, VinylControlManager* pVCMan) : QGLWidget(SharedGLContext::getContext(), parent),
10 m_pBG(NULL), 10 m_pBG(NULL),
11 m_pFG(NULL),11 m_pFG(NULL),
12 m_pGhost(NULL),12 m_pGhost(NULL),
@@ -20,6 +20,12 @@
20 m_pScratchToggle(NULL),20 m_pScratchToggle(NULL),
21 m_pScratchPos(NULL),21 m_pScratchPos(NULL),
22 m_pVinylControlSpeedType(NULL),22 m_pVinylControlSpeedType(NULL),
23 m_pVinylControlEnabled(NULL),
24 m_bVinylActive(false),
25 m_bSignalActive(true),
26 m_iSize(0),
27 m_iTimerId(0),
28 m_iSignalUpdateTick(0),
23 m_fAngle(0.0f),29 m_fAngle(0.0f),
24 m_fGhostAngle(0.0f),30 m_fGhostAngle(0.0f),
25 m_dPausedPosition(0.0f),31 m_dPausedPosition(0.0f),
@@ -29,6 +35,10 @@
29 m_iFullRotations(0),35 m_iFullRotations(0),
30 m_dPrevTheta(0.)36 m_dPrevTheta(0.)
31{37{
38#ifdef __VINYLCONTROL__
39 m_pVCManager = pVCMan;
40 m_pVinylControl = NULL;
41#endif
32 //Drag and drop42 //Drag and drop
33 setAcceptDrops(true);43 setAcceptDrops(true);
34}44}
@@ -69,6 +79,13 @@
69 if (m_pBG && !m_pBG->isNull()) {79 if (m_pBG && !m_pBG->isNull()) {
70 setFixedSize(m_pBG->size());80 setFixedSize(m_pBG->size());
71 }81 }
82
83#ifdef __VINYLCONTROL__
84 m_iSize = MIXXX_VINYL_SCOPE_SIZE;
85 m_qImage = QImage(m_iSize, m_iSize, QImage::Format_ARGB32);
86 //fill with transparent black
87 m_qImage.fill(qRgba(0,0,0,0));
88#endif
7289
73 m_pPlay = new ControlObjectThreadMain(ControlObject::getControl(90 m_pPlay = new ControlObjectThreadMain(ControlObject::getControl(
74 ConfigKey(group, "play")));91 ConfigKey(group, "play")));
@@ -92,6 +109,15 @@
92 ConfigKey(group, "scratch_position_enable")));109 ConfigKey(group, "scratch_position_enable")));
93 m_pScratchPos = new ControlObjectThreadMain(ControlObject::getControl(110 m_pScratchPos = new ControlObjectThreadMain(ControlObject::getControl(
94 ConfigKey(group, "scratch_position")));111 ConfigKey(group, "scratch_position")));
112
113 Q_ASSERT(m_pPlayPos);
114 Q_ASSERT(m_pDuration);
115
116 //Repaint when visual_playposition changes.
117 connect(m_pVisualPlayPos, SIGNAL(valueChanged(double)),
118 this, SLOT(updateAngle(double)));
119
120#ifdef __VINYLCONTROL__
95 m_pVinylControlSpeedType = new ControlObjectThreadMain(ControlObject::getControl(121 m_pVinylControlSpeedType = new ControlObjectThreadMain(ControlObject::getControl(
96 ConfigKey(group, "vinylcontrol_speed_type")));122 ConfigKey(group, "vinylcontrol_speed_type")));
97 if (m_pVinylControlSpeedType)123 if (m_pVinylControlSpeedType)
@@ -99,17 +125,26 @@
99 //Initialize the rotational speed.125 //Initialize the rotational speed.
100 this->updateVinylControlSpeed(m_pVinylControlSpeedType->get());126 this->updateVinylControlSpeed(m_pVinylControlSpeedType->get());
101 }127 }
102 Q_ASSERT(m_pPlayPos);128 m_pVinylControlEnabled = new ControlObjectThreadMain(ControlObject::getControl(
103 Q_ASSERT(m_pDuration);129 ConfigKey(group, "vinylcontrol_enabled")));
104130 m_pSignalEnabled = new ControlObjectThreadMain(ControlObject::getControl(
105 //Repaint when visual_playposition changes.131 ConfigKey(group, "vinylcontrol_signal_enabled")));
106 connect(m_pVisualPlayPos, SIGNAL(valueChanged(double)),132 m_pRate = new ControlObjectThreadMain(ControlObject::getControl(
107 this, SLOT(updateAngle(double)));133 ConfigKey(group, "rate")));
108134
109 //Match the vinyl control's set RPM so that the spinny widget rotates at the same 135 //Match the vinyl control's set RPM so that the spinny widget rotates at the same
110 //speed as your physical decks, if you're using vinyl control.136 //speed as your physical decks, if you're using vinyl control.
111 connect(m_pVinylControlSpeedType, SIGNAL(valueChanged(double)),137 connect(m_pVinylControlSpeedType, SIGNAL(valueChanged(double)),
112 this, SLOT(updateVinylControlSpeed(double)));138 this, SLOT(updateVinylControlSpeed(double)));
139
140 //Make sure vinyl control proxies are up to date
141 connect(m_pVinylControlEnabled, SIGNAL(valueChanged(double)),
142 this, SLOT(updateVinylControlEnabled(double)));
143
144 //Check the rate to see if we are stopped
145 connect(m_pRate, SIGNAL(valueChanged(double)),
146 this, SLOT(updateRate(double)));
147#endif
113}148}
114149
115void WSpinny::paintEvent(QPaintEvent *e)150void WSpinny::paintEvent(QPaintEvent *e)
@@ -121,6 +156,49 @@
121 if (m_pBG) {156 if (m_pBG) {
122 p.drawPixmap(0, 0, *m_pBG);157 p.drawPixmap(0, 0, *m_pBG);
123 }158 }
159
160#ifdef __VINYLCONTROL__
161 // Overlay the signal quality drawing if vinyl is active
162 if (m_bVinylActive && m_bSignalActive)
163 {
164 //reduce cpu load by only updating every 3 times
165 m_iSignalUpdateTick = (m_iSignalUpdateTick + 1) % 3;
166 if (m_iSignalUpdateTick == 0)
167 {
168 unsigned char * buf = m_pVinylControl->getScopeBytemap();
169 int r,g,b;
170 QColor qual_color = QColor();
171 float signalQuality = m_pVinylControl->getTimecodeQuality();
172
173 //color is related to signal quality
174 //hsv: s=1, v=1
175 //h is the only variable.
176 //h=0 is red, h=120 is green
177 qual_color.setHsv((int)(120.0 * signalQuality), 255, 255);
178 qual_color.getRgb(&r, &g, &b);
179
180 if (buf) {
181 for (int y=0; y<m_iSize; y++) {
182 QRgb *line = (QRgb *)m_qImage.scanLine(y);
183 for(int x=0; x<m_iSize; x++) {
184 //use xwax's bitmap to set alpha data only
185 //adjust alpha by 3/4 so it's not quite so distracting
186 //setpixel is slow, use scanlines instead
187 //m_qImage.setPixel(x, y, qRgba(r,g,b,(int)buf[x+m_iSize*y] * .75));
188 *line = qRgba(r,g,b,(int)(buf[x+m_iSize*y] * .75));
189 line++;
190 }
191 }
192 p.drawImage(this->rect(), m_qImage);
193 }
194 }
195 else
196 {
197 //draw the last good image
198 p.drawImage(this->rect(), m_qImage);
199 }
200 }
201#endif
124202
125 //To rotate the foreground pixmap around the center of the image,203 //To rotate the foreground pixmap around the center of the image,
126 //we use the classic trick of translating the coordinate system such that204 //we use the classic trick of translating the coordinate system such that
@@ -147,7 +225,7 @@
147 //Rotate back to the playback position (not the ghost positon), 225 //Rotate back to the playback position (not the ghost positon),
148 //and draw the beat marks from there.226 //and draw the beat marks from there.
149 p.restore();227 p.restore();
150228
151 /*229 /*
152 //Draw a line where the next 4 beats are 230 //Draw a line where the next 4 beats are
153 double bpm = m_pBPM->get();231 double bpm = m_pBPM->get();
@@ -247,6 +325,29 @@
247void WSpinny::updateAngle(double playpos)325void WSpinny::updateAngle(double playpos)
248{326{
249 m_fAngle = calculateAngle(playpos);327 m_fAngle = calculateAngle(playpos);
328
329 // if we had the timer going, kill it
330 if (m_iTimerId != 0) {
331 killTimer(m_iTimerId);
332 m_iTimerId = 0;
333 }
334 update();
335}
336
337void WSpinny::updateRate(double rate)
338{
339 //if rate is zero, updateAngle won't get called,
340 if (rate == 0.0 && m_bVinylActive)
341 {
342 if (m_iTimerId == 0)
343 {
344 m_iTimerId = startTimer(10);
345 }
346 }
347}
348
349void WSpinny::timerEvent(QTimerEvent *event)
350{
250 update();351 update();
251}352}
252353
@@ -266,6 +367,60 @@
266 m_dRotationsPerSecond = rpm/60.;367 m_dRotationsPerSecond = rpm/60.;
267}368}
268369
370void WSpinny::updateVinylControlEnabled(double enabled)
371{
372#ifdef __VINYLCONTROL__
373 if (enabled)
374 {
375 if (m_pVinylControl == NULL)
376 {
377 QList<VinylControlProxy*> VCProxiesList = m_pVCManager->vinylControlProxies();
378 if (m_group == "[Channel1]")
379 {
380 m_pVinylControl = VCProxiesList.value(0);
381 }
382 else if (m_group == "[Channel2]")
383 {
384 m_pVinylControl = VCProxiesList.value(1);
385 }
386
387 if (m_pVinylControl != NULL)
388 {
389 m_bVinylActive = true;
390 m_bSignalActive = m_pSignalEnabled->get();
391 connect(m_pVinylControl, SIGNAL(destroyed()),
392 this, SLOT(invalidateVinylControl()));
393 }
394 }
395 else
396 {
397 m_bVinylActive = true;
398 }
399 }
400 else
401 {
402 m_bVinylActive = false;
403 //don't need the timer anymore
404 if (m_iTimerId != 0)
405 {
406 killTimer(m_iTimerId);
407 }
408 // draw once more to erase signal
409 update();
410 }
411#endif
412}
413
414void WSpinny::invalidateVinylControl()
415{
416#ifdef __VINYLCONTROL__
417 m_bVinylActive = false;
418 m_pVinylControl = NULL;
419 update();
420#endif
421}
422
423
269void WSpinny::mouseMoveEvent(QMouseEvent * e)424void WSpinny::mouseMoveEvent(QMouseEvent * e)
270{425{
271 int y = e->y();426 int y = e->y();
@@ -301,7 +456,7 @@
301 //qDebug() << "c t:" << theta << "pt:" << m_dPrevTheta << 456 //qDebug() << "c t:" << theta << "pt:" << m_dPrevTheta <<
302 // "icr" << m_iFullRotations;457 // "icr" << m_iFullRotations;
303458
304 if (e->buttons() & Qt::LeftButton)459 if (e->buttons() & Qt::LeftButton && !m_bVinylActive)
305 {460 {
306 //Convert deltaTheta into a percentage of song length.461 //Convert deltaTheta into a percentage of song length.
307 double absPos = calculatePositionFromAngle(theta);462 double absPos = calculatePositionFromAngle(theta);
@@ -325,6 +480,10 @@
325480
326 m_iStartMouseX = x;481 m_iStartMouseX = x;
327 m_iStartMouseY = y;482 m_iStartMouseY = y;
483
484 //don't do anything if vinyl control is active
485 if (m_bVinylActive)
486 return;
328487
329 if (e->button() == Qt::LeftButton)488 if (e->button() == Qt::LeftButton)
330 {489 {
@@ -394,7 +553,7 @@
394 Q_UNUSED(e); //ditch unused param warning553 Q_UNUSED(e); //ditch unused param warning
395554
396 /*555 /*
397 double wheelDirection = ((QWheelEvent *)e)->delta() / 120.;556 double wheelDirection = ((QWheelEvent *)e)->delta() / 120.;
398 double newValue = getValue() + (wheelDirection);557 double newValue = getValue() + (wheelDirection);
399 this->updateValue(newValue);558 this->updateValue(newValue);
400559
401560
=== modified file 'mixxx/src/widget/wspinny.h'
--- mixxx/src/widget/wspinny.h 2011-05-11 04:38:17 +0000
+++ mixxx/src/widget/wspinny.h 2011-07-30 20:21:03 +0000
@@ -4,6 +4,11 @@
44
5#include <QGLWidget>5#include <QGLWidget>
6#include "wwidget.h"6#include "wwidget.h"
7#include "vinylcontrol/vinylcontrolmanager.h"
8#ifdef __VINYLCONTROL__
9#include "vinylcontrol/vinylcontrolproxy.h"
10#include "vinylcontrol/vinylcontrol.h"
11#endif
712
8class ControlObjectThreadMain;13class ControlObjectThreadMain;
914
@@ -11,15 +16,18 @@
11{16{
12 Q_OBJECT17 Q_OBJECT
13 public:18 public:
14 WSpinny(QWidget* parent);19 WSpinny(QWidget* parent, VinylControlManager* pVCMan);
15 ~WSpinny();20 ~WSpinny();
16 void setup(QDomNode node, QString group);21 void setup(QDomNode node, QString group);
17 void dragEnterEvent(QDragEnterEvent *event);22 void dragEnterEvent(QDragEnterEvent *event);
18 void dropEvent(QDropEvent *event);23 void dropEvent(QDropEvent *event);
19 public slots:24 public slots:
20 void updateAngle(double);25 void updateAngle(double);
26 void updateRate(double);
21 void updateAngleForGhost();27 void updateAngleForGhost();
22 void updateVinylControlSpeed(double rpm);28 void updateVinylControlSpeed(double rpm);
29 void updateVinylControlEnabled(double enabled);
30 void invalidateVinylControl();
23 signals:31 signals:
24 void trackDropped(QString filename, QString group);32 void trackDropped(QString filename, QString group);
25 protected:33 protected:
@@ -29,6 +37,7 @@
29 void mousePressEvent(QMouseEvent * e);37 void mousePressEvent(QMouseEvent * e);
30 void mouseReleaseEvent(QMouseEvent * e);38 void mouseReleaseEvent(QMouseEvent * e);
31 void wheelEvent(QWheelEvent *e);39 void wheelEvent(QWheelEvent *e);
40 void timerEvent(QTimerEvent* event);
3241
33 double calculateAngle(double playpos);42 double calculateAngle(double playpos);
34 int calculateFullRotations(double playpos);43 int calculateFullRotations(double playpos);
@@ -47,7 +56,22 @@
47 ControlObjectThreadMain* m_pScratch;56 ControlObjectThreadMain* m_pScratch;
48 ControlObjectThreadMain* m_pScratchToggle;57 ControlObjectThreadMain* m_pScratchToggle;
49 ControlObjectThreadMain* m_pScratchPos;58 ControlObjectThreadMain* m_pScratchPos;
59 ControlObjectThreadMain* m_pRate;
50 ControlObjectThreadMain* m_pVinylControlSpeedType;60 ControlObjectThreadMain* m_pVinylControlSpeedType;
61 ControlObjectThreadMain* m_pVinylControlEnabled;
62 ControlObjectThreadMain* m_pSignalEnabled;
63
64#ifdef __VINYLCONTROL__
65 VinylControlManager* m_pVCManager;
66 VinylControlProxy* m_pVinylControl;
67#endif
68 bool m_bVinylActive;
69 bool m_bSignalActive;
70 QImage m_qImage;
71 int m_iSize;
72 int m_iTimerId;
73 int m_iSignalUpdateTick;
74
51 QString m_group;75 QString m_group;
52 float m_fAngle; //Degrees76 float m_fAngle; //Degrees
53 float m_fGhostAngle; 77 float m_fGhostAngle;

Subscribers

People subscribed via source and target branches