Simplify generating chorus delays a bit

This commit is contained in:
Chris Robinson
2020-04-09 20:57:12 -07:00
parent c83609277b
commit 35a2b0e5f8
+67 -55
View File
@@ -54,37 +54,7 @@ enum class WaveForm {
Triangle
};
void GetTriangleDelays(ALuint *delays, const ALuint start_offset, const ALuint lfo_range,
const float lfo_scale, const float depth, const ALsizei delay, const size_t todo)
{
ASSUME(lfo_range > 0);
ASSUME(todo > 0);
ALuint offset{start_offset};
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
{
offset = (offset+1)%lfo_range;
const float offset_norm{static_cast<float>(offset) * lfo_scale};
return static_cast<ALuint>(fastf2i((1.0f-std::abs(2.0f-offset_norm)) * depth) + delay);
};
std::generate_n(delays, todo, gen_lfo);
}
void GetSinusoidDelays(ALuint *delays, const ALuint start_offset, const ALuint lfo_range,
const float lfo_scale, const float depth, const ALsizei delay, const size_t todo)
{
ASSUME(lfo_range > 0);
ASSUME(todo > 0);
ALuint offset{start_offset};
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
{
offset = (offset+1)%lfo_range;
const float offset_norm{static_cast<float>(offset) * lfo_scale};
return static_cast<ALuint>(fastf2i(std::sin(offset_norm)*depth) + delay);
};
std::generate_n(delays, todo, gen_lfo);
}
#define MAX_UPDATE_SAMPLES 256
struct ChorusState final : public EffectState {
al::vector<float,16> mSampleBuffer;
@@ -107,6 +77,8 @@ struct ChorusState final : public EffectState {
float mDepth{0.0f};
float mFeedback{0.0f};
void getTriangleDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
void getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
bool deviceUpdate(const ALCdevice *device) override;
void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override;
@@ -191,12 +163,12 @@ void ChorusState::update(const ALCcontext *Context, const ALeffectslot *Slot, co
mLfoRange = lfo_range;
switch(mWaveform)
{
case WaveForm::Triangle:
mLfoScale = 4.0f / static_cast<float>(mLfoRange);
break;
case WaveForm::Sinusoid:
mLfoScale = al::MathDefs<float>::Tau() / static_cast<float>(mLfoRange);
break;
case WaveForm::Triangle:
mLfoScale = 4.0f / static_cast<float>(mLfoRange);
break;
case WaveForm::Sinusoid:
mLfoScale = al::MathDefs<float>::Tau() / static_cast<float>(mLfoRange);
break;
}
/* Calculate lfo phase displacement */
@@ -206,6 +178,57 @@ void ChorusState::update(const ALCcontext *Context, const ALeffectslot *Slot, co
}
}
void ChorusState::getTriangleDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
{
const ALuint lfo_range{mLfoRange};
const float lfo_scale{mLfoScale};
const float depth{mDepth};
const int delay{mDelay};
ASSUME(lfo_range > 0);
ASSUME(todo > 0);
ALuint offset{mLfoOffset};
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
{
offset = (offset+1)%lfo_range;
const float offset_norm{static_cast<float>(offset) * lfo_scale};
return static_cast<ALuint>(fastf2i((1.0f-std::abs(2.0f-offset_norm)) * depth) + delay);
};
std::generate_n(delays[0], todo, gen_lfo);
offset = (mLfoOffset+mLfoDisp) % lfo_range;
std::generate_n(delays[1], todo, gen_lfo);
mLfoOffset = static_cast<ALuint>(mLfoOffset+todo) % lfo_range;
}
void ChorusState::getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
{
const ALuint lfo_range{mLfoRange};
const float lfo_scale{mLfoScale};
const float depth{mDepth};
const int delay{mDelay};
ASSUME(lfo_range > 0);
ASSUME(todo > 0);
ALuint offset{mLfoOffset};
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
{
offset = (offset+1)%lfo_range;
const float offset_norm{static_cast<float>(offset) * lfo_scale};
return static_cast<ALuint>(fastf2i(std::sin(offset_norm)*depth) + delay);
};
std::generate_n(delays[0], todo, gen_lfo);
offset = (mLfoOffset+mLfoDisp) % lfo_range;
std::generate_n(delays[1], todo, gen_lfo);
mLfoOffset = static_cast<ALuint>(mLfoOffset+todo) % lfo_range;
}
void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
{
const size_t bufmask{mSampleBuffer.size()-1};
@@ -216,27 +239,16 @@ void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBu
for(size_t base{0u};base < samplesToDo;)
{
const size_t todo{minz(256, samplesToDo-base)};
const size_t todo{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)};
ALuint moddelays[2][256];
ALuint moddelays[2][MAX_UPDATE_SAMPLES];
if(mWaveform == WaveForm::Sinusoid)
{
GetSinusoidDelays(moddelays[0], mLfoOffset, mLfoRange, mLfoScale, mDepth, mDelay,
todo);
GetSinusoidDelays(moddelays[1], (mLfoOffset+mLfoDisp)%mLfoRange, mLfoRange, mLfoScale,
mDepth, mDelay, todo);
}
getSinusoidDelays(moddelays, todo);
else /*if(mWaveform == WaveForm::Triangle)*/
{
GetTriangleDelays(moddelays[0], mLfoOffset, mLfoRange, mLfoScale, mDepth, mDelay,
todo);
GetTriangleDelays(moddelays[1], (mLfoOffset+mLfoDisp)%mLfoRange, mLfoRange, mLfoScale,
mDepth, mDelay, todo);
}
mLfoOffset = (mLfoOffset+static_cast<ALuint>(todo)) % mLfoRange;
getTriangleDelays(moddelays, todo);
alignas(16) float temps[2][256];
for(size_t i{0u};i < todo;i++)
alignas(16) float temps[2][MAX_UPDATE_SAMPLES];
for(size_t i{0u};i < todo;++i)
{
// Feed the buffer's input first (necessary for delays < 1).
delaybuf[offset&bufmask] = samplesIn[0][base+i];
@@ -258,7 +270,7 @@ void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBu
++offset;
}
for(ALsizei c{0};c < 2;c++)
for(ALsizei c{0};c < 2;++c)
MixSamples({temps[c], todo}, samplesOut, mGains[c].Current, mGains[c].Target,
samplesToDo-base, base);