Support for effect sample-rate changes

This commit is contained in:
Jack Andersen 2016-05-31 18:49:35 -10:00
parent 44204d7b08
commit d132b1be34
11 changed files with 67 additions and 11 deletions

View File

@ -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<boo::IAudioSubmix> m_booSubmix;

View File

@ -12,6 +12,7 @@ class EffectBaseTypeless
{
public:
virtual ~EffectBaseTypeless() = default;
virtual void resetOutputSampleRate(double sampleRate)=0;
};
template <typename T>

View File

@ -53,7 +53,7 @@ public:
template <typename T>
class EffectChorusImp : public EffectBase<T>, 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<T>, 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);}
};
}

View File

@ -80,10 +80,12 @@ class EffectDelayImp : public EffectBase<T>, 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);}
};
}

View File

@ -115,11 +115,13 @@ class EffectReverbStdImp : public EffectBase<T>, 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<T>, 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);}
};
}

View File

@ -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;}
};

View File

@ -77,6 +77,11 @@ void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCou
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(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))
{}

View File

@ -148,10 +148,19 @@ EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t peri
template <typename T>
EffectChorusImp<T>::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 <typename T>
void EffectChorusImp<T>::_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<T>::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 <typename T>

View File

@ -10,8 +10,6 @@ namespace amuse
template <typename T>
EffectDelayImp<T>::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<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback,
x54_output[i] = initOutput;
}
_setup(sampleRate);
}
template <typename T>
void EffectDelayImp<T>::_setup(double sampleRate)
{
m_sampsPerMs = std::ceil(sampleRate / 1000.0);
m_blockSamples = m_sampsPerMs * 5;
_update();
}

View File

@ -71,9 +71,17 @@ EffectReverbHi::EffectReverbHi(float coloration, float mix, float time,
template <typename T>
EffectReverbStdImp<T>::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 <typename T>
void EffectReverbStdImp<T>::_setup(double sampleRate)
{
m_sampleRate = sampleRate;
_update();
}
template <typename T>
void EffectReverbStdImp<T>::_update()
@ -238,9 +246,15 @@ template <typename T>
EffectReverbHiImp<T>::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 <typename T>
void EffectReverbHiImp<T>::_setup(double sampleRate)
{
m_sampleRate = sampleRate;
_update();
}

View File

@ -52,4 +52,10 @@ void Submix::applyEffect(float* audio, size_t frameCount, const ChannelMap& chan
((EffectBase<float>&)*effect).applyEffect(audio, frameCount, chanMap);
}
void Submix::resetOutputSampleRate(double sampleRate)
{
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
effect->resetOutputSampleRate(sampleRate);
}
}