From d132b1be342a8362b462b71d6867c614c473e2dc Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 31 May 2016 18:49:35 -1000 Subject: [PATCH] Support for effect sample-rate changes --- include/amuse/BooBackend.hpp | 1 + include/amuse/EffectBase.hpp | 1 + include/amuse/EffectChorus.hpp | 4 +++- include/amuse/EffectDelay.hpp | 2 ++ include/amuse/EffectReverb.hpp | 4 ++++ include/amuse/Submix.hpp | 3 +++ lib/BooBackend.cpp | 5 +++++ lib/EffectChorus.cpp | 17 ++++++++++++++--- lib/EffectDelay.cpp | 11 +++++++++-- lib/EffectReverb.cpp | 24 +++++++++++++++++++----- lib/Submix.cpp | 6 ++++++ 11 files changed, 67 insertions(+), 11 deletions(-) diff --git a/include/amuse/BooBackend.hpp b/include/amuse/BooBackend.hpp index 2ee9cfb..9af8b7f 100644 --- a/include/amuse/BooBackend.hpp +++ b/include/amuse/BooBackend.hpp @@ -55,6 +55,7 @@ class BooBackendSubmix : public IBackendSubmix const boo::ChannelMap& chanMap, double sampleRate) const; void applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const; + void resetOutputSampleRate(double sampleRate); SubmixCallback(BooBackendSubmix& parent) : m_parent(parent) {} } m_cb; std::unique_ptr m_booSubmix; diff --git a/include/amuse/EffectBase.hpp b/include/amuse/EffectBase.hpp index 07d2aeb..ce89db9 100644 --- a/include/amuse/EffectBase.hpp +++ b/include/amuse/EffectBase.hpp @@ -12,6 +12,7 @@ class EffectBaseTypeless { public: virtual ~EffectBaseTypeless() = default; + virtual void resetOutputSampleRate(double sampleRate)=0; }; template diff --git a/include/amuse/EffectChorus.hpp b/include/amuse/EffectChorus.hpp index 885a22e..ee1a8c9 100644 --- a/include/amuse/EffectChorus.hpp +++ b/include/amuse/EffectChorus.hpp @@ -53,7 +53,7 @@ public: template class EffectChorusImp : public EffectBase, public EffectChorus { - T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS]; /**< Evenly-allocated pointer-table for each channel's delay */ + T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS] = {}; /**< Evenly-allocated pointer-table for each channel's delay */ uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */ T x28_oldChans[8][4] = {}; /**< Unprocessed history of previous 4 samples */ @@ -84,12 +84,14 @@ class EffectChorusImp : public EffectBase, public EffectChorus uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */ uint32_t m_blockSamples; /**< count of samples in a 5ms block */ + void _setup(double sampleRate); void _update(); public: ~EffectChorusImp(); EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); + void resetOutputSampleRate(double sampleRate) {_setup(sampleRate);} }; } diff --git a/include/amuse/EffectDelay.hpp b/include/amuse/EffectDelay.hpp index 9c6d108..54c1ea9 100644 --- a/include/amuse/EffectDelay.hpp +++ b/include/amuse/EffectDelay.hpp @@ -80,10 +80,12 @@ class EffectDelayImp : public EffectBase, public EffectDelay uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */ uint32_t m_blockSamples; /**< count of samples in a 5ms block */ + void _setup(double sampleRate); void _update(); public: EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); + void resetOutputSampleRate(double sampleRate) {_setup(sampleRate);} }; } diff --git a/include/amuse/EffectReverb.hpp b/include/amuse/EffectReverb.hpp index 45661ac..53854b3 100644 --- a/include/amuse/EffectReverb.hpp +++ b/include/amuse/EffectReverb.hpp @@ -115,11 +115,13 @@ class EffectReverbStdImp : public EffectBase, public EffectReverbStd float* x130_preDelayPtr[8] = {}; /**< Current pre-delay pointers */ double m_sampleRate; /**< copy of sample rate */ + void _setup(double sampleRate); void _update(); public: EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay, double sampleRate); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); + void resetOutputSampleRate(double sampleRate) {_setup(sampleRate);} }; /** High-quality 3-stage reverb with per-channel low-pass and crosstalk */ @@ -140,6 +142,7 @@ class EffectReverbHiImp : public EffectBase, public EffectReverbHi float x1a8_internalCrosstalk = 0.f; double m_sampleRate; /**< copy of sample rate */ + void _setup(double sampleRate); void _update(); void _handleReverb(T* audio, int chanIdx, int chanCount, int sampleCount); void _doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount); @@ -147,6 +150,7 @@ public: EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk, double sampleRate); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); + void resetOutputSampleRate(double sampleRate) {_setup(sampleRate);} }; } diff --git a/include/amuse/Submix.hpp b/include/amuse/Submix.hpp index 6283376..4dca35e 100644 --- a/include/amuse/Submix.hpp +++ b/include/amuse/Submix.hpp @@ -99,6 +99,9 @@ public: /** in/out transformation entry for audio effect */ void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) const; + /** advice effects of changing sample rate */ + void resetOutputSampleRate(double sampleRate); + Engine& getEngine() {return m_root;} }; diff --git a/lib/BooBackend.cpp b/lib/BooBackend.cpp index 9b71268..a2fc95a 100644 --- a/lib/BooBackend.cpp +++ b/lib/BooBackend.cpp @@ -77,6 +77,11 @@ void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCou return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast(chanMap)); } +void BooBackendSubmix::SubmixCallback::resetOutputSampleRate(double sampleRate) +{ + m_parent.m_clientSmx.resetOutputSampleRate(sampleRate); +} + BooBackendSubmix::BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx) : m_clientSmx(clientSmx), m_cb(*this), m_booSubmix(engine.allocateNewSubmix(&m_cb)) {} diff --git a/lib/EffectChorus.cpp b/lib/EffectChorus.cpp index ce7ffdc..ceb3484 100644 --- a/lib/EffectChorus.cpp +++ b/lib/EffectChorus.cpp @@ -148,10 +148,19 @@ EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t peri template EffectChorusImp::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate) -: EffectChorus(baseDelay, variation, period), - m_sampsPerMs(std::ceil(sampleRate / 1000.0)), - m_blockSamples(m_sampsPerMs * 5) +: EffectChorus(baseDelay, variation, period) { + _setup(sampleRate); +} + +template +void EffectChorusImp::_setup(double sampleRate) +{ + m_sampsPerMs = std::ceil(sampleRate / 1000.0); + m_blockSamples = m_sampsPerMs * 5; + + delete[] x0_lastChans[0][0]; + T* buf = new T[m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8]; memset(buf, 0, m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8 * sizeof(T)); size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS; @@ -161,6 +170,8 @@ EffectChorusImp::EffectChorusImp(uint32_t baseDelay, uint32_t variation, x0_lastChans[c][i] = buf + chanPitch * c + m_blockSamples * i; x6c_src.x88_trigger = chanPitch; + + m_dirty = true; } template diff --git a/lib/EffectDelay.cpp b/lib/EffectDelay.cpp index 2beb5e2..7995133 100644 --- a/lib/EffectDelay.cpp +++ b/lib/EffectDelay.cpp @@ -10,8 +10,6 @@ namespace amuse template EffectDelayImp::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate) -: m_sampsPerMs(std::ceil(sampleRate / 1000.0)), - m_blockSamples(m_sampsPerMs * 5) { initDelay = clamp(10u, initDelay, 5000u); initFeedback = clamp(0u, initFeedback, 100u); @@ -24,6 +22,15 @@ EffectDelayImp::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, x54_output[i] = initOutput; } + _setup(sampleRate); +} + +template +void EffectDelayImp::_setup(double sampleRate) +{ + m_sampsPerMs = std::ceil(sampleRate / 1000.0); + m_blockSamples = m_sampsPerMs * 5; + _update(); } diff --git a/lib/EffectReverb.cpp b/lib/EffectReverb.cpp index ce9c070..78d3d0c 100644 --- a/lib/EffectReverb.cpp +++ b/lib/EffectReverb.cpp @@ -71,9 +71,17 @@ EffectReverbHi::EffectReverbHi(float coloration, float mix, float time, template EffectReverbStdImp::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay, double sampleRate) -: EffectReverbStd(coloration, mix, time, damping, preDelay), - m_sampleRate(sampleRate) -{} +: EffectReverbStd(coloration, mix, time, damping, preDelay) +{ + _setup(sampleRate); +} + +template +void EffectReverbStdImp::_setup(double sampleRate) +{ + m_sampleRate = sampleRate; + _update(); +} template void EffectReverbStdImp::_update() @@ -238,9 +246,15 @@ template EffectReverbHiImp::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk, double sampleRate) -: EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk), - m_sampleRate(sampleRate) +: EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk) { + _setup(sampleRate); +} + +template +void EffectReverbHiImp::_setup(double sampleRate) +{ + m_sampleRate = sampleRate; _update(); } diff --git a/lib/Submix.cpp b/lib/Submix.cpp index 048cdb9..1450f39 100644 --- a/lib/Submix.cpp +++ b/lib/Submix.cpp @@ -52,4 +52,10 @@ void Submix::applyEffect(float* audio, size_t frameCount, const ChannelMap& chan ((EffectBase&)*effect).applyEffect(audio, frameCount, chanMap); } +void Submix::resetOutputSampleRate(double sampleRate) +{ + for (const std::unique_ptr& effect : m_effectStack) + effect->resetOutputSampleRate(sampleRate); +} + }