From c637e3943ba21dd280151622a66435944fbc6217 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Fri, 6 Aug 2021 13:56:32 +0200 Subject: [PATCH] engine: Use mixxx::audio::SampleRate in EngineSync/EngineMaster code Use `mixxx::audio::SampleRate` instead of `int` in the `EngineMaster`, `EngineSync` and `InternalClock` code. The type was not applied to the channel mixer and effects code to reduce potential merge conflicts with #1966 and #2618. Based on PR #4071. --- src/engine/enginemaster.cpp | 100 +++++++++++++++++------------- src/engine/enginemaster.h | 11 ++-- src/engine/sync/enginesync.cpp | 4 +- src/engine/sync/enginesync.h | 5 +- src/engine/sync/internalclock.cpp | 18 +++--- src/engine/sync/internalclock.h | 11 ++-- 6 files changed, 84 insertions(+), 65 deletions(-) diff --git a/src/engine/enginemaster.cpp b/src/engine/enginemaster.cpp index 34cb9d22e86..6a446093a94 100644 --- a/src/engine/enginemaster.cpp +++ b/src/engine/enginemaster.cpp @@ -271,7 +271,7 @@ const CSAMPLE* EngineMaster::getSidechainBuffer() const { void EngineMaster::processChannels(int iBufferSize) { // Update internal sync lock rate. - m_pMasterSync->onCallbackStart(m_iSampleRate, m_iBufferSize); + m_pMasterSync->onCallbackStart(m_sampleRate, m_iBufferSize); m_activeBusChannels[EngineChannel::LEFT].clear(); m_activeBusChannels[EngineChannel::CENTER].clear(); @@ -372,7 +372,7 @@ void EngineMaster::processChannels(int iBufferSize) { // Note, because we call this on the internal clock first, // it will have an up-to-date beatDistance, whereas the other // Syncables will not. - m_pMasterSync->onCallbackEnd(m_iSampleRate, m_iBufferSize); + m_pMasterSync->onCallbackEnd(m_sampleRate, m_iBufferSize); // After all the engines have been processed, trigger post-processing // which ensures that all channels are updating certain values at the @@ -396,7 +396,7 @@ void EngineMaster::process(const int iBufferSize) { bool boothEnabled = m_pBoothEnabled->toBool(); bool headphoneEnabled = m_pHeadphoneEnabled->toBool(); - m_iSampleRate = static_cast(m_pMasterSampleRate->get()); + m_sampleRate = mixxx::audio::SampleRate::fromDouble(m_pMasterSampleRate->get()); m_iBufferSize = iBufferSize; // TODO: remove assumption of stereo buffer const unsigned int kChannels = 2; @@ -428,12 +428,14 @@ void EngineMaster::process(const int iBufferSize) { // Process effects and mix PFL channels together for the headphones. // Effects will be reprocessed post-fader for the crossfader buses // and master mix, so the channel input buffers cannot be modified here. - ChannelMixer::applyEffectsAndMixChannels( - m_headphoneGain, &m_activeHeadphoneChannels, - &m_channelHeadphoneGainCache, - m_pHead, m_headphoneHandle.handle(), - m_iBufferSize, m_iSampleRate, - m_pEngineEffectsManager); + ChannelMixer::applyEffectsAndMixChannels(m_headphoneGain, + &m_activeHeadphoneChannels, + &m_channelHeadphoneGainCache, + m_pHead, + m_headphoneHandle.handle(), + m_iBufferSize, + static_cast(m_sampleRate.value()), + m_pEngineEffectsManager); // Process headphone channel effects if (m_pEngineEffectsManager) { @@ -448,21 +450,25 @@ void EngineMaster::process(const int iBufferSize) { headphoneFeatures = m_activeHeadphoneChannels.at(0)->m_features; } m_pEngineEffectsManager->processPostFaderInPlace( - m_headphoneHandle.handle(), - m_headphoneHandle.handle(), - m_pHead, - m_iBufferSize, m_iSampleRate, - headphoneFeatures); + m_headphoneHandle.handle(), + m_headphoneHandle.handle(), + m_pHead, + m_iBufferSize, + static_cast(m_sampleRate.value()), + headphoneFeatures); } } // Mix all the talkover enabled channels together. // Effects processing is done in place to avoid unnecessary buffer copying. - ChannelMixer::applyEffectsInPlaceAndMixChannels( - m_talkoverGain, &m_activeTalkoverChannels, + ChannelMixer::applyEffectsInPlaceAndMixChannels(m_talkoverGain, + &m_activeTalkoverChannels, &m_channelTalkoverGainCache, - m_pTalkover, m_masterHandle.handle(), - m_iBufferSize, m_iSampleRate, m_pEngineEffectsManager); + m_pTalkover, + m_masterHandle.handle(), + m_iBufferSize, + static_cast(m_sampleRate.value()), + m_pEngineEffectsManager); // Process effects on all microphones mixed together // We have no metadata for mixed effect buses, so use an empty GroupFeatureState. @@ -473,7 +479,7 @@ void EngineMaster::process(const int iBufferSize) { m_masterHandle.handle(), m_pTalkover, m_iBufferSize, - m_iSampleRate, + static_cast(m_sampleRate.value()), busFeatures); } @@ -511,31 +517,39 @@ void EngineMaster::process(const int iBufferSize) { m_pTalkoverDucking->getGain(m_iBufferSize / 2)); for (int o = EngineChannel::LEFT; o <= EngineChannel::RIGHT; o++) { - ChannelMixer::applyEffectsInPlaceAndMixChannels( - m_masterGain, - &m_activeBusChannels[o], - &m_channelMasterGainCache, // no [o] because the old gain follows an orientation switch - m_pOutputBusBuffers[o], m_masterHandle.handle(), - m_iBufferSize, m_iSampleRate, m_pEngineEffectsManager); + ChannelMixer::applyEffectsInPlaceAndMixChannels(m_masterGain, + &m_activeBusChannels[o], + &m_channelMasterGainCache, // no [o] because the old gain follows an orientation switch + m_pOutputBusBuffers[o], + m_masterHandle.handle(), + m_iBufferSize, + static_cast(m_sampleRate.value()), + m_pEngineEffectsManager); } // Process crossfader orientation bus channel effects if (m_pEngineEffectsManager) { m_pEngineEffectsManager->processPostFaderInPlace( - m_busCrossfaderLeftHandle.handle(), - m_masterHandle.handle(), - m_pOutputBusBuffers[EngineChannel::LEFT], - m_iBufferSize, m_iSampleRate, busFeatures); + m_busCrossfaderLeftHandle.handle(), + m_masterHandle.handle(), + m_pOutputBusBuffers[EngineChannel::LEFT], + m_iBufferSize, + static_cast(m_sampleRate.value()), + busFeatures); m_pEngineEffectsManager->processPostFaderInPlace( - m_busCrossfaderCenterHandle.handle(), - m_masterHandle.handle(), - m_pOutputBusBuffers[EngineChannel::CENTER], - m_iBufferSize, m_iSampleRate, busFeatures); + m_busCrossfaderCenterHandle.handle(), + m_masterHandle.handle(), + m_pOutputBusBuffers[EngineChannel::CENTER], + m_iBufferSize, + static_cast(m_sampleRate.value()), + busFeatures); m_pEngineEffectsManager->processPostFaderInPlace( - m_busCrossfaderRightHandle.handle(), - m_masterHandle.handle(), - m_pOutputBusBuffers[EngineChannel::RIGHT], - m_iBufferSize, m_iSampleRate, busFeatures); + m_busCrossfaderRightHandle.handle(), + m_masterHandle.handle(), + m_pOutputBusBuffers[EngineChannel::RIGHT], + m_iBufferSize, + static_cast(m_sampleRate.value()), + busFeatures); } if (masterEnabled) { @@ -705,7 +719,8 @@ void EngineMaster::process(const int iBufferSize) { m_masterOutputHandle.handle(), m_masterHandle.handle(), m_pMaster, - m_iBufferSize, m_iSampleRate, + m_iBufferSize, + static_cast(m_sampleRate.value()), masterFeatures); } @@ -761,10 +776,11 @@ void EngineMaster::applyMasterEffects() { masterFeatures.has_gain = true; masterFeatures.gain = m_pMasterGain->get(); m_pEngineEffectsManager->processPostFaderInPlace(m_masterHandle.handle(), - m_masterHandle.handle(), - m_pMaster, - m_iBufferSize, m_iSampleRate, - masterFeatures); + m_masterHandle.handle(), + m_pMaster, + m_iBufferSize, + static_cast(m_sampleRate.value()), + masterFeatures); } } diff --git a/src/engine/enginemaster.h b/src/engine/enginemaster.h index f85af0b11c1..7033f9ca2ca 100644 --- a/src/engine/enginemaster.h +++ b/src/engine/enginemaster.h @@ -3,15 +3,16 @@ #include #include -#include "preferences/usersettings.h" +#include "audio/types.h" #include "control/controlobject.h" #include "control/controlpushbutton.h" -#include "engine/engineobject.h" -#include "engine/channels/enginechannel.h" #include "engine/channelhandle.h" +#include "engine/channels/enginechannel.h" +#include "engine/engineobject.h" +#include "preferences/usersettings.h" +#include "recording/recordingmanager.h" #include "soundio/soundmanager.h" #include "soundio/soundmanagerutil.h" -#include "recording/recordingmanager.h" class EngineWorkerScheduler; class EngineBuffer; @@ -283,7 +284,7 @@ class EngineMaster : public QObject, public AudioSource { QVarLengthArray m_activeHeadphoneChannels; QVarLengthArray m_activeTalkoverChannels; - unsigned int m_iSampleRate; + mixxx::audio::SampleRate m_sampleRate; unsigned int m_iBufferSize; // Mixing buffers for each output. diff --git a/src/engine/sync/enginesync.cpp b/src/engine/sync/enginesync.cpp index f10debccb6d..cda9d12f534 100644 --- a/src/engine/sync/enginesync.cpp +++ b/src/engine/sync/enginesync.cpp @@ -527,11 +527,11 @@ void EngineSync::addSyncableDeck(Syncable* pSyncable) { m_syncables.append(pSyncable); } -void EngineSync::onCallbackStart(int sampleRate, int bufferSize) { +void EngineSync::onCallbackStart(mixxx::audio::SampleRate sampleRate, int bufferSize) { m_pInternalClock->onCallbackStart(sampleRate, bufferSize); } -void EngineSync::onCallbackEnd(int sampleRate, int bufferSize) { +void EngineSync::onCallbackEnd(mixxx::audio::SampleRate sampleRate, int bufferSize) { m_pInternalClock->onCallbackEnd(sampleRate, bufferSize); } diff --git a/src/engine/sync/enginesync.h b/src/engine/sync/enginesync.h index b656aa12a75..aa57cfd880e 100644 --- a/src/engine/sync/enginesync.h +++ b/src/engine/sync/enginesync.h @@ -2,6 +2,7 @@ #include +#include "audio/types.h" #include "engine/sync/syncable.h" #include "preferences/usersettings.h" @@ -57,8 +58,8 @@ class EngineSync : public SyncableListener { void addSyncableDeck(Syncable* pSyncable); EngineChannel* getLeader() const; - void onCallbackStart(int sampleRate, int bufferSize); - void onCallbackEnd(int sampleRate, int bufferSize); + void onCallbackStart(mixxx::audio::SampleRate sampleRate, int bufferSize); + void onCallbackEnd(mixxx::audio::SampleRate sampleRate, int bufferSize); private: /// Iterate over decks, and based on sync and play status, pick a new Leader. diff --git a/src/engine/sync/internalclock.cpp b/src/engine/sync/internalclock.cpp index aed7e8f210a..b81152c90d5 100644 --- a/src/engine/sync/internalclock.cpp +++ b/src/engine/sync/internalclock.cpp @@ -19,10 +19,10 @@ InternalClock::InternalClock(const QString& group, SyncableListener* pEngineSync : m_group(group), m_pEngineSync(pEngineSync), m_mode(SyncMode::None), - m_iOldSampleRate(44100), + m_oldSampleRate(mixxx::audio::SampleRate{44100}), m_oldBpm(kDefaultBpm), m_baseBpm(kDefaultBpm), - m_dBeatLength(m_iOldSampleRate * 60.0 / m_oldBpm.value()), + m_dBeatLength(m_oldSampleRate * 60.0 / m_oldBpm.value()), m_dClockPosition(0) { // Pick a wide range (1 to 200) and allow out of bounds sets. This lets you // map a soft-takeover MIDI knob to the leader BPM. This also creates bpm_up @@ -132,7 +132,7 @@ void InternalClock::updateLeaderBpm(mixxx::Bpm bpm) { return; } m_pClockBpm->set(bpm.value()); - updateBeatLength(m_iOldSampleRate, bpm); + updateBeatLength(m_oldSampleRate, bpm); } void InternalClock::updateInstantaneousBpm(mixxx::Bpm bpm) { @@ -160,7 +160,7 @@ void InternalClock::reinitLeaderParams(double beatDistance, mixxx::Bpm baseBpm, void InternalClock::slotBpmChanged(double bpm) { m_baseBpm = mixxx::Bpm(bpm); - updateBeatLength(m_iOldSampleRate, m_baseBpm); + updateBeatLength(m_oldSampleRate, m_baseBpm); if (!isSynchronized()) { return; } @@ -177,8 +177,8 @@ void InternalClock::slotBeatDistanceChanged(double beatDistance) { updateLeaderBeatDistance(beatDistance); } -void InternalClock::updateBeatLength(int sampleRate, mixxx::Bpm bpm) { - if (m_iOldSampleRate == sampleRate && bpm == m_oldBpm) { +void InternalClock::updateBeatLength(mixxx::audio::SampleRate sampleRate, mixxx::Bpm bpm) { + if (m_oldSampleRate == sampleRate && bpm == m_oldBpm) { return; } @@ -207,19 +207,19 @@ void InternalClock::updateBeatLength(int sampleRate, mixxx::Bpm bpm) { } } - m_iOldSampleRate = sampleRate; + m_oldSampleRate = sampleRate; // Restore the old beat distance. updateLeaderBeatDistance(oldBeatDistance); } -void InternalClock::onCallbackStart(int sampleRate, int bufferSize) { +void InternalClock::onCallbackStart(mixxx::audio::SampleRate sampleRate, int bufferSize) { Q_UNUSED(sampleRate) Q_UNUSED(bufferSize) m_pEngineSync->notifyInstantaneousBpmChanged(this, getBpm()); } -void InternalClock::onCallbackEnd(int sampleRate, int bufferSize) { +void InternalClock::onCallbackEnd(mixxx::audio::SampleRate sampleRate, int bufferSize) { updateBeatLength(sampleRate, getBpm()); // stereo samples, so divide by 2 diff --git a/src/engine/sync/internalclock.h b/src/engine/sync/internalclock.h index c6150866697..4dc7db7a435 100644 --- a/src/engine/sync/internalclock.h +++ b/src/engine/sync/internalclock.h @@ -1,9 +1,10 @@ #pragma once #include -#include #include +#include +#include "audio/types.h" #include "engine/sync/clock.h" #include "engine/sync/syncable.h" @@ -57,8 +58,8 @@ class InternalClock : public QObject, public Clock, public Syncable { void updateInstantaneousBpm(mixxx::Bpm bpm) override; void reinitLeaderParams(double beatDistance, mixxx::Bpm baseBpm, mixxx::Bpm bpm) override; - void onCallbackStart(int sampleRate, int bufferSize); - void onCallbackEnd(int sampleRate, int bufferSize); + void onCallbackStart(mixxx::audio::SampleRate sampleRate, int bufferSize); + void onCallbackEnd(mixxx::audio::SampleRate sampleRate, int bufferSize); private slots: void slotBpmChanged(double bpm); @@ -66,7 +67,7 @@ class InternalClock : public QObject, public Clock, public Syncable { void slotSyncLeaderEnabledChangeRequest(double state); private: - void updateBeatLength(int sampleRate, mixxx::Bpm bpm); + void updateBeatLength(mixxx::audio::SampleRate sampleRate, mixxx::Bpm bpm); const QString m_group; SyncableListener* m_pEngineSync; @@ -75,7 +76,7 @@ class InternalClock : public QObject, public Clock, public Syncable { QScopedPointer m_pSyncLeaderEnabled; SyncMode m_mode; - int m_iOldSampleRate; + mixxx::audio::SampleRate m_oldSampleRate; mixxx::Bpm m_oldBpm; // This is the BPM value at unity adopted when sync is enabled.