mirror of https://github.com/AxioDL/amuse.git
Add info structures for holding effect parameters
This commit is contained in:
parent
ecd990e94e
commit
2e7345f11d
|
@ -128,6 +128,7 @@ public:
|
|||
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices();
|
||||
std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr);
|
||||
void register5MsCallback(std::function<void(double)>&& callback);
|
||||
void unregister5MsCallback();
|
||||
AudioChannelSet getAvailableSet();
|
||||
void pumpAndMixVoices();
|
||||
void setVolume(float vol);
|
||||
|
|
|
@ -12,6 +12,18 @@ class EffectChorusImp;
|
|||
|
||||
#define AMUSE_CHORUS_NUM_BLOCKS 3
|
||||
|
||||
/** Parameters needed to create EffectChorus */
|
||||
struct EffectChorusInfo
|
||||
{
|
||||
uint32_t baseDelay = 5; /**< [5, 15] minimum value (in ms) for computed delay */
|
||||
uint32_t variation = 0; /**< [0, 5] time error (in ms) to set delay within */
|
||||
uint32_t period = 500; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
||||
|
||||
EffectChorusInfo() = default;
|
||||
EffectChorusInfo(uint32_t baseDelay, uint32_t variation, uint32_t period)
|
||||
: baseDelay(baseDelay), variation(variation), period(period) {}
|
||||
};
|
||||
|
||||
/** Mixes the audio back into itself after continuously-varying delay */
|
||||
class EffectChorus
|
||||
{
|
||||
|
@ -48,6 +60,13 @@ public:
|
|||
x98_period = period;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void updateParams(const EffectChorusInfo& info)
|
||||
{
|
||||
setBaseDelay(info.baseDelay);
|
||||
setVariation(info.variation);
|
||||
setPeriod(info.period);
|
||||
}
|
||||
};
|
||||
|
||||
/** Type-specific implementation of chorus effect */
|
||||
|
@ -91,6 +110,9 @@ class EffectChorusImp : public EffectBase<T>, public EffectChorus
|
|||
public:
|
||||
~EffectChorusImp();
|
||||
EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate);
|
||||
EffectChorusImp(const EffectChorusInfo& info, double sampleRate)
|
||||
: EffectChorusImp(info.baseDelay, info.variation, info.period, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
||||
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __AMUSE_EFFECTDELAY_HPP__
|
||||
|
||||
#include "EffectBase.hpp"
|
||||
#include "IBackendVoice.hpp"
|
||||
#include "Common.hpp"
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
@ -11,6 +12,38 @@ namespace amuse
|
|||
template <typename T>
|
||||
class EffectDelayImp;
|
||||
|
||||
/** Parameters needed to create EffectDelay */
|
||||
struct EffectDelayInfo
|
||||
{
|
||||
uint32_t delay[8]; /**< [10, 5000] time in ms of each channel's delay */
|
||||
uint32_t feedback[8] = {}; /**< [0, 100] percent to mix delayed signal with input signal */
|
||||
uint32_t output[8] = {}; /**< [0, 100] total output percent */
|
||||
|
||||
static uint32_t lerp(uint32_t v0, uint32_t v1, float t) { return (1.f - t) * v0 + t * v1; }
|
||||
|
||||
static void Interp3To8(uint32_t arr[8], uint32_t L, uint32_t R, uint32_t S)
|
||||
{
|
||||
arr[int(AudioChannel::FrontLeft)] = L;
|
||||
arr[int(AudioChannel::FrontRight)] = R;
|
||||
arr[int(AudioChannel::RearLeft)] = lerp(L, S, 0.75f);
|
||||
arr[int(AudioChannel::RearRight)] = lerp(R, S, 0.75f);
|
||||
arr[int(AudioChannel::FrontCenter)] = lerp(L, R, 0.5f);
|
||||
arr[int(AudioChannel::LFE)] = arr[int(AudioChannel::FrontCenter)];
|
||||
arr[int(AudioChannel::SideLeft)] = lerp(L, S, 0.5f);
|
||||
arr[int(AudioChannel::SideRight)] = lerp(R, S, 0.5f);
|
||||
}
|
||||
|
||||
EffectDelayInfo() { std::fill_n(delay, 8, 10); }
|
||||
EffectDelayInfo(uint32_t delayL, uint32_t delayR, uint32_t delayS,
|
||||
uint32_t feedbackL, uint32_t feedbackR, uint32_t feedbackS,
|
||||
uint32_t outputL, uint32_t outputR, uint32_t outputS)
|
||||
{
|
||||
Interp3To8(delay, delayL, delayR, delayS);
|
||||
Interp3To8(feedback, feedbackL, feedbackR, feedbackS);
|
||||
Interp3To8(output, outputL, outputR, outputS);
|
||||
}
|
||||
};
|
||||
|
||||
/** Mixes the audio back into itself after specified delay */
|
||||
class EffectDelay
|
||||
{
|
||||
|
@ -59,12 +92,24 @@ public:
|
|||
x54_output[i] = output;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void setChanOutput(int chanIdx, uint32_t output)
|
||||
{
|
||||
output = clamp(0u, output, 100u);
|
||||
x54_output[chanIdx] = output;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void setParams(const EffectDelayInfo& info)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
x3c_delay[i] = clamp(10u, info.delay[i], 5000u);
|
||||
x48_feedback[i] = clamp(0u, info.feedback[i], 100u);
|
||||
x54_output[i] = clamp(0u, info.output[i], 100u);
|
||||
}
|
||||
m_dirty = true;
|
||||
}
|
||||
};
|
||||
|
||||
/** Type-specific implementation of delay effect */
|
||||
|
@ -85,6 +130,8 @@ class EffectDelayImp : public EffectBase<T>, public EffectDelay
|
|||
|
||||
public:
|
||||
EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate);
|
||||
EffectDelayImp(const EffectDelayInfo& info, double sampleRate);
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
||||
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
|
||||
};
|
||||
|
|
|
@ -8,6 +8,35 @@
|
|||
namespace amuse
|
||||
{
|
||||
|
||||
/** Parameters needed to create EffectReverbStd */
|
||||
struct EffectReverbStdInfo
|
||||
{
|
||||
float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */
|
||||
float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
|
||||
float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */
|
||||
float damping = 0.f; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
||||
float preDelay = 0.f; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||
|
||||
EffectReverbStdInfo() = default;
|
||||
EffectReverbStdInfo(float coloration, float mix, float time, float damping, float preDelay)
|
||||
: coloration(coloration), mix(mix), time(time), damping(damping), preDelay(preDelay) {}
|
||||
};
|
||||
|
||||
/** Parameters needed to create EffectReverbHi */
|
||||
struct EffectReverbHiInfo
|
||||
{
|
||||
float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */
|
||||
float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
|
||||
float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */
|
||||
float damping = 0.f; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
||||
float preDelay = 0.f; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||
float crosstalk = 0.f; /**< [0.0, 1.0] factor defining how much reflections are allowed to bleed to other channels */
|
||||
|
||||
EffectReverbHiInfo() = default;
|
||||
EffectReverbHiInfo(float coloration, float mix, float time, float damping, float preDelay, float crosstalk)
|
||||
: coloration(coloration), mix(mix), time(time), damping(damping), preDelay(preDelay), crosstalk(crosstalk) {}
|
||||
};
|
||||
|
||||
/** Delay state for one 'tap' of the reverb effect */
|
||||
struct ReverbDelayLine
|
||||
{
|
||||
|
@ -78,6 +107,15 @@ public:
|
|||
x150_x1d8_preDelay = clamp(0.f, preDelay, 0.1f);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void setParams(const EffectReverbStdInfo& info)
|
||||
{
|
||||
setColoration(info.coloration);
|
||||
setMix(info.mix);
|
||||
setTime(info.time);
|
||||
setDamping(info.damping);
|
||||
setPreDelay(info.preDelay);
|
||||
}
|
||||
};
|
||||
|
||||
/** Reverb effect with configurable reflection filtering, adds per-channel low-pass and crosstalk */
|
||||
|
@ -98,6 +136,16 @@ public:
|
|||
x1dc_crosstalk = clamp(0.f, crosstalk, 1.f);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void setParams(const EffectReverbHiInfo& info)
|
||||
{
|
||||
setColoration(info.coloration);
|
||||
setMix(info.mix);
|
||||
setTime(info.time);
|
||||
setDamping(info.damping);
|
||||
setPreDelay(info.preDelay);
|
||||
setCrosstalk(info.crosstalk);
|
||||
}
|
||||
};
|
||||
|
||||
/** Standard-quality 2-stage reverb */
|
||||
|
@ -121,6 +169,9 @@ class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd
|
|||
|
||||
public:
|
||||
EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay, double sampleRate);
|
||||
EffectReverbStdImp(const EffectReverbStdInfo& info, double sampleRate)
|
||||
: EffectReverbStdImp(info.coloration, info.mix, info.time, info.damping, info.preDelay, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
||||
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
|
||||
};
|
||||
|
@ -151,6 +202,9 @@ class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi
|
|||
public:
|
||||
EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk,
|
||||
double sampleRate);
|
||||
EffectReverbHiImp(const EffectReverbHiInfo& info, double sampleRate)
|
||||
: EffectReverbHiImp(info.coloration, info.mix, info.time, info.damping, info.preDelay, info.crosstalk, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
||||
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
|
||||
};
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
|
||||
/** Amuse may request callbacks 200-updates-per-second virtually */
|
||||
virtual void register5MsCallback(std::function<void(double dt)>&& callback) = 0;
|
||||
|
||||
/** This is important to ensure orderly cleanup */
|
||||
virtual void unregister5MsCallback() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -60,16 +60,28 @@ public:
|
|||
/** Add new chorus effect to effect stack and assume ownership */
|
||||
EffectChorus& makeChorus(uint32_t baseDelay, uint32_t variation, uint32_t period);
|
||||
|
||||
/** Add new chorus effect to effect stack and assume ownership */
|
||||
EffectChorus& makeChorus(const EffectChorusInfo& info);
|
||||
|
||||
/** Add new delay effect to effect stack and assume ownership */
|
||||
EffectDelay& makeDelay(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput);
|
||||
|
||||
/** Add new delay effect to effect stack and assume ownership */
|
||||
EffectDelay& makeDelay(const EffectDelayInfo& info);
|
||||
|
||||
/** Add new standard-quality reverb effect to effect stack and assume ownership */
|
||||
EffectReverbStd& makeReverbStd(float coloration, float mix, float time, float damping, float preDelay);
|
||||
|
||||
/** Add new standard-quality reverb effect to effect stack and assume ownership */
|
||||
EffectReverbStd& makeReverbStd(const EffectReverbStdInfo& info);
|
||||
|
||||
/** Add new high-quality reverb effect to effect stack and assume ownership */
|
||||
EffectReverbHi& makeReverbHi(float coloration, float mix, float time, float damping, float preDelay,
|
||||
float crosstalk);
|
||||
|
||||
/** Add new high-quality reverb effect to effect stack and assume ownership */
|
||||
EffectReverbHi& makeReverbHi(const EffectReverbHiInfo& info);
|
||||
|
||||
/** Remove and deallocate all effects from effect stack */
|
||||
void clearEffects() { m_effectStack.clear(); }
|
||||
|
||||
|
|
|
@ -285,6 +285,11 @@ void BooBackendVoiceAllocator::register5MsCallback(std::function<void(double)>&&
|
|||
m_booEngine.register5MsCallback(std::move(callback));
|
||||
}
|
||||
|
||||
void BooBackendVoiceAllocator::unregister5MsCallback()
|
||||
{
|
||||
m_booEngine.unregister5MsCallback();
|
||||
}
|
||||
|
||||
AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); }
|
||||
|
||||
void BooBackendVoiceAllocator::pumpAndMixVoices() { m_booEngine.pumpAndMixVoices(); }
|
||||
|
|
|
@ -24,6 +24,19 @@ EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uin
|
|||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
x3c_delay[i] = clamp(10u, info.delay[i], 5000u);
|
||||
x48_feedback[i] = clamp(0u, info.feedback[i], 100u);
|
||||
x54_output[i] = clamp(0u, info.output[i], 100u);
|
||||
}
|
||||
|
||||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectDelayImp<T>::_setup(double sampleRate)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ static const float FullLevels[8] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
|
|||
|
||||
Engine::~Engine()
|
||||
{
|
||||
m_backend.unregister5MsCallback();
|
||||
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
|
||||
if (!seq->m_destroyed)
|
||||
seq->_destroy();
|
||||
|
|
|
@ -10,22 +10,42 @@ EffectChorus& Submix::makeChorus(uint32_t baseDelay, uint32_t variation, uint32_
|
|||
return makeEffect<EffectChorus>(baseDelay, variation, period);
|
||||
}
|
||||
|
||||
EffectChorus& Submix::makeChorus(const EffectChorusInfo& info)
|
||||
{
|
||||
return makeEffect<EffectChorus>(info);
|
||||
}
|
||||
|
||||
EffectDelay& Submix::makeDelay(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput)
|
||||
{
|
||||
return makeEffect<EffectDelay>(initDelay, initFeedback, initOutput);
|
||||
}
|
||||
|
||||
EffectDelay& Submix::makeDelay(const EffectDelayInfo& info)
|
||||
{
|
||||
return makeEffect<EffectDelay>(info);
|
||||
}
|
||||
|
||||
EffectReverbStd& Submix::makeReverbStd(float coloration, float mix, float time, float damping, float preDelay)
|
||||
{
|
||||
return makeEffect<EffectReverbStd>(coloration, mix, time, damping, preDelay);
|
||||
}
|
||||
|
||||
EffectReverbStd& Submix::makeReverbStd(const EffectReverbStdInfo& info)
|
||||
{
|
||||
return makeEffect<EffectReverbStd>(info);
|
||||
}
|
||||
|
||||
EffectReverbHi& Submix::makeReverbHi(float coloration, float mix, float time, float damping, float preDelay,
|
||||
float crosstalk)
|
||||
{
|
||||
return makeEffect<EffectReverbHi>(coloration, mix, time, damping, preDelay, crosstalk);
|
||||
}
|
||||
|
||||
EffectReverbHi& Submix::makeReverbHi(const EffectReverbHiInfo& info)
|
||||
{
|
||||
return makeEffect<EffectReverbHi>(info);
|
||||
}
|
||||
|
||||
void Submix::applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap) const
|
||||
{
|
||||
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
|
||||
|
|
Loading…
Reference in New Issue