Skip to content

Commit

Permalink
Merge pull request mixxxdj#12435 from daschuer/gh10550
Browse files Browse the repository at this point in the history
Fix gain issue with cloned tracks
  • Loading branch information
daschuer authored Feb 4, 2024
2 parents 4cfb8c4 + bc6374e commit b11437a
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 15 deletions.
7 changes: 7 additions & 0 deletions src/engine/enginebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ EngineBuffer::EngineBuffer(const QString& group,
m_pKeylock = new ControlPushButton(ConfigKey(m_group, "keylock"), true);
m_pKeylock->setButtonMode(ControlPushButton::TOGGLE);

m_pReplayGain = new ControlProxy(m_group, QStringLiteral("replaygain"), this);

m_pTrackLoaded = new ControlObject(ConfigKey(m_group, "track_loaded"), false);
m_pTrackLoaded->setReadOnly();

Expand Down Expand Up @@ -315,6 +317,7 @@ EngineBuffer::~EngineBuffer() {
#endif

delete m_pKeylock;
delete m_pReplayGain;

SampleUtil::free(m_pCrossfadeBuffer);

Expand Down Expand Up @@ -546,6 +549,8 @@ void EngineBuffer::slotTrackLoaded(TrackPointer pTrack,
m_dSlipRate = 0;
m_slipModeState = SlipModeState::Disabled;

m_pReplayGain->set(pTrack->getReplayGain().getRatio());

m_queuedSeek.setValue(kNoQueuedSeek);

// Reset the pitch value for the new track.
Expand Down Expand Up @@ -610,6 +615,8 @@ void EngineBuffer::ejectTrack() {
m_playposSlider->set(0);
m_pCueControl->resetIndicators();

m_pReplayGain->set(0.0);

m_queuedSeek.setValue(kNoQueuedSeek);

m_pause.unlock();
Expand Down
1 change: 1 addition & 0 deletions src/engine/enginebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ class EngineBuffer : public EngineObject {
ControlProxy* m_pSampleRate;
ControlProxy* m_pKeylockEngine;
ControlPushButton* m_pKeylock;
ControlProxy* m_pReplayGain;

// This ControlProxys is created as parent to this and deleted by
// the Qt object tree. This helps that they are deleted by the creating
Expand Down
28 changes: 15 additions & 13 deletions src/engine/enginepregain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
namespace {

// Bends the speed to gain curve for a natural vinyl sound
constexpr float kSpeedGainMultiplier = 4.0f;
constexpr CSAMPLE_GAIN kSpeedGainMultiplier = 4.0f;
// -1 dB to not risk any clipping even for lossy track that may have samples above 1.0
constexpr float kMaxTotalGainBySpeed = 0.9f;
constexpr CSAMPLE_GAIN kMaxTotalGainBySpeed = 0.9f;
// value to normalize gain to 1 at speed one
const float kSpeedOneDiv = std::log10((1 * kSpeedGainMultiplier) + 1);
const CSAMPLE_GAIN kSpeedOneDiv = std::log10((1 * kSpeedGainMultiplier) + 1);
} // anonymous namespace

ControlPotmeter* EnginePregain::s_pReplayGainBoost = nullptr;
ControlPotmeter* EnginePregain::s_pDefaultBoost = nullptr;
ControlObject* EnginePregain::s_pEnableReplayGain = nullptr;

EnginePregain::EnginePregain(const QString& group)
: m_dSpeed(1.0),
m_dOldSpeed(1.0),
: m_dSpeed(0.0),
m_dOldSpeed(0.0),
m_dNonScratchSpeed(1.0),
m_scratching(false),
m_fPrevGain(1.0),
Expand Down Expand Up @@ -75,7 +75,7 @@ void EnginePregain::process(CSAMPLE* pInOut, const int iBufferSize) {
fReplayGainCorrection = 1; // We expect a replaygain leveled input
} else if (fReplayGain == 0) {
// use predicted replaygain
fReplayGainCorrection = (float)s_pDefaultBoost->get();
fReplayGainCorrection = static_cast<CSAMPLE_GAIN>(s_pDefaultBoost->get());
// We prepare for smoothfading to ReplayGain suggested gain
// if ReplayGain value changes or ReplayGain is enabled
m_bSmoothFade = true;
Expand All @@ -88,17 +88,17 @@ void EnginePregain::process(CSAMPLE* pInOut, const int iBufferSize) {
// full process for one second.
// So we need to alter gain each time ::process is called.

const float fullReplayGainBoost =
fReplayGain * static_cast<float>(s_pReplayGainBoost->get());
const CSAMPLE_GAIN fullReplayGainBoost =
fReplayGain * static_cast<CSAMPLE_GAIN>(s_pReplayGainBoost->get());

// This means that a ReplayGain value has been calculated after the
// track has been loaded
constexpr float kFadeSeconds = 1.0;
constexpr float kFadeSeconds = 1.0f;

if (m_bSmoothFade) {
float seconds = static_cast<float>(m_timer.elapsed().toDoubleSeconds());
if (seconds < kFadeSeconds) {
// Fade smoothly
if (seconds < kFadeSeconds && m_dSpeed != 0.0 && m_dOldSpeed != 0.0) {
// Fade smoothly if not stopped, stopping or starting
const float fadeFrac = seconds / kFadeSeconds;
fReplayGainCorrection = m_fPrevGain * (1.0f - fadeFrac) +
fadeFrac * fullReplayGainBoost;
Expand All @@ -115,7 +115,7 @@ void EnginePregain::process(CSAMPLE* pInOut, const int iBufferSize) {
// Clamp gain to within [0, 10.0] to prevent insane gains. This can happen
// (some corrupt files get really high replay gain values).
// 10 allows a maximum replay Gain Boost * calculated replay gain of ~2
CSAMPLE_GAIN totalGain = (CSAMPLE_GAIN)m_pPotmeterPregain->get() *
auto totalGain = static_cast<CSAMPLE_GAIN>(m_pPotmeterPregain->get()) *
math_clamp(fReplayGainCorrection, 0.0f, 10.0f);

m_pTotalGain->set(totalGain);
Expand Down Expand Up @@ -151,7 +151,9 @@ void EnginePregain::process(CSAMPLE* pInOut, const int iBufferSize) {
SampleUtil::applyRampingGain(&pInOut[0], m_fPrevGain, 0, iBufferSize / 2);
SampleUtil::applyRampingGain(&pInOut[iBufferSize / 2], 0, totalGain, iBufferSize / 2);
} else if (totalGain != m_fPrevGain) {
// Prevent sound wave discontinuities by interpolating from old to new gain.
// Prevent sound wave discontinuities by interpolating from old to new gain
// if not stopped or starting
// This handles also the ramping of play (from speed 0) and pause (to speed 0)
SampleUtil::applyRampingGain(pInOut, m_fPrevGain, totalGain, iBufferSize);
} else {
// SampleUtil deals with aliased buffers and gains of 1 or 0.
Expand Down
2 changes: 0 additions & 2 deletions src/mixer/basetrackplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,6 @@ void BaseTrackPlayerImpl::slotTrackLoaded(TrackPointer pNewTrack,
m_pDuration->set(0);
m_pFileBPM->set(0);
m_pKey->set(0);
setReplayGain(0);
slotSetTrackColor(std::nullopt);
m_pLoopInPoint->set(kNoTrigger);
m_pLoopOutPoint->set(kNoTrigger);
Expand All @@ -547,7 +546,6 @@ void BaseTrackPlayerImpl::slotTrackLoaded(TrackPointer pNewTrack,
m_pDuration->set(m_pLoadedTrack->getDuration());
m_pFileBPM->set(m_pLoadedTrack->getBpm());
m_pKey->set(m_pLoadedTrack->getKey());
setReplayGain(m_pLoadedTrack->getReplayGain().getRatio());
slotSetTrackColor(m_pLoadedTrack->getColor());

if(m_pConfig->getValue(
Expand Down

0 comments on commit b11437a

Please sign in to comment.