double RateControl::calculateRate(double baserate, bool paused, int iSamplesPerBuffer, bool* isScratching) { double rate = (paused ? 0 : 1.0); double searching = m_pRateSearch->get(); if (searching) { // If searching is in progress, it overrides everything else rate = searching; } else { double wheelFactor = getWheelFactor(); double jogFactor = getJogFactor(); bool bVinylControlEnabled = m_pVCEnabled && m_pVCEnabled->get() > 0.0; bool scratchEnable = m_pScratchToggle->get() != 0 || bVinylControlEnabled; double scratchFactor = m_pScratch->get(); // Don't trust values from m_pScratch if (isnan(scratchFactor)) { scratchFactor = 0.0; } // Old Scratch works without scratchEnable double oldScratchFactor = m_pOldScratch->get(); // Deprecated // Don't trust values from m_pScratch if (isnan(oldScratchFactor)) { oldScratchFactor = 0.0; } // If vinyl control is enabled and scratching then also set isScratching bool bVinylControlScratching = m_pVCScratching && m_pVCScratching->get() > 0.0; if (bVinylControlEnabled && bVinylControlScratching) { *isScratching = true; } if (paused) { // Stopped. Wheel, jog and scratch controller all scrub through audio. // New scratch behavior overrides old if (scratchEnable) { rate = scratchFactor + jogFactor + wheelFactor * 40.0; } else { // Just remove oldScratchFactor in future rate = oldScratchFactor + jogFactor * 18 + wheelFactor; } } else { // The buffer is playing, so calculate the buffer rate. // There are four rate effects we apply: wheel, scratch, jog and temp. // Wheel: a linear additive effect (no spring-back) // Scratch: a rate multiplier // Jog: a linear additive effect whose value is filtered (springs back) // Temp: pitch bend // New scratch behavior - overrides playback speed (and old behavior) if (scratchEnable) { rate = scratchFactor; } else { rate = 1. + getRawRate() + getTempRate(); rate += wheelFactor; // Deprecated old scratch behavior if (oldScratchFactor < 0.) { rate *= (oldScratchFactor - 1.); } else if (oldScratchFactor > 0.) { rate *= (oldScratchFactor + 1.); } } rate += jogFactor; } double currentSample = getCurrentSample(); m_pScratchController->process(currentSample, rate, iSamplesPerBuffer, baserate); // If waveform scratch is enabled, override all other controls if (m_pScratchController->isEnabled()) { rate = m_pScratchController->getRate(); *isScratching = true; } // If master sync is on, respond to it -- but vinyl and scratch mode always override. if (getSyncMode() == SYNC_FOLLOWER && !paused && !bVinylControlEnabled && !*isScratching) { if (m_pBpmControl == NULL) { qDebug() << "ERROR: calculateRate m_pBpmControl is null during master sync"; return 1.0; } rate = m_pBpmControl->getSyncedRate(); double userTweak = getTempRate() + wheelFactor + jogFactor; bool userTweakingSync = userTweak != 0.0; rate += userTweak; rate *= m_pBpmControl->getSyncAdjustment(userTweakingSync); } // If we are reversing (and not scratching,) flip the rate. This is ok even when syncing. if (!scratchEnable && m_pReverseButton->get()) { rate = -rate; } } return rate; }
double RateControl::calculateSpeed(double baserate, double speed, bool paused, int iSamplesPerBuffer, bool* pReportScratching, bool* pReportReverse) { *pReportScratching = false; *pReportReverse = false; double rate = (paused ? 0 : 1.0); double searching = m_pRateSearch->get(); if (searching) { // If searching is in progress, it overrides everything else rate = searching; } else { double wheelFactor = getWheelFactor(); double jogFactor = getJogFactor(); bool bVinylControlEnabled = m_pVCEnabled && m_pVCEnabled->toBool(); bool useScratch2Value = m_pScratch2Enable->get() != 0; // By default scratch2_enable is enough to determine if the user is // scratching or not. Moving platter controllers have to disable // "scratch2_indicates_scratching" if they are not scratching, // to allow things like key-lock. if (useScratch2Value && m_pScratch2Scratching->get()) { *pReportScratching = true; } if (bVinylControlEnabled) { if (m_pVCScratching->toBool()) { *pReportScratching = true; } rate = speed; } else { double scratchFactor = m_pScratch2->get(); // Don't trust values from m_pScratch2 if (isnan(scratchFactor)) { scratchFactor = 0.0; } if (paused) { // Stopped. Wheel, jog and scratch controller all scrub through audio. if (useScratch2Value) { rate = scratchFactor + jogFactor + wheelFactor * kWheelMultiplier; } else { rate = jogFactor * kPausedJogMultiplier + wheelFactor; } } else { // The buffer is playing, so calculate the buffer rate. // There are four rate effects we apply: wheel, scratch, jog and temp. // Wheel: a linear additive effect (no spring-back) // Scratch: a rate multiplier // Jog: a linear additive effect whose value is filtered (springs back) // Temp: pitch bend // New scratch behavior - overrides playback speed (and old behavior) if (useScratch2Value) { rate = scratchFactor; } else { rate = speed + getTempRate(); rate += wheelFactor; } rate += jogFactor; } } double currentSample = getCurrentSample(); m_pScratchController->process(currentSample, rate, iSamplesPerBuffer, baserate); // If waveform scratch is enabled, override all other controls if (m_pScratchController->isEnabled()) { rate = m_pScratchController->getRate(); *pReportScratching = true; } else { // If master sync is on, respond to it -- but vinyl and scratch mode always override. if (getSyncMode() == SYNC_FOLLOWER && !paused && !bVinylControlEnabled && !useScratch2Value) { if (m_pBpmControl == NULL) { qDebug() << "ERROR: calculateRate m_pBpmControl is null during master sync"; return 1.0; } double userTweak = 0.0; if (!*pReportScratching) { // Only report user tweak if the user is not scratching. userTweak = getTempRate() + wheelFactor + jogFactor; } rate = m_pBpmControl->calcSyncedRate(userTweak); } // If we are reversing (and not scratching,) flip the rate. This is ok even when syncing. // Reverse with vinyl is only ok if absolute mode isn't on. int vcmode = m_pVCMode ? m_pVCMode->get() : MIXXX_VCMODE_ABSOLUTE; // TODO(owen): Instead of just ignoring reverse mode, should we // disable absolute mode instead? if (m_pReverseButton->get() && !m_pScratch2Enable->get() && (!bVinylControlEnabled || vcmode != MIXXX_VCMODE_ABSOLUTE)) { rate = -rate; *pReportReverse = true; } } } return rate; }