Skip to content

Commit

Permalink
Merge pull request #511 from ubuntor/extend_flanger
Browse files Browse the repository at this point in the history
Fix and extend custom flangers
  • Loading branch information
Drewol authored Sep 20, 2021
2 parents 913c7bd + 5baae13 commit 1031612
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*.lib
*.exe
*.a
bin/usc-game
bin/Tests.Game
bin/Tests.Shared

# Memory dump files
*.dmp
Expand Down
9 changes: 8 additions & 1 deletion Audio/include/Audio/DSP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ class FlangerDSP : public DSP

void SetLength(double length);
void SetDelayRange(uint32 min, uint32 max);
void SetFeedback(float feedback);
void SetStereoWidth(float stereoWidth);
void SetVolume(float volume);

virtual void Process(float *out, uint32 numSamples);
virtual const char *GetName() const { return "FlangerDSP"; }
Expand All @@ -233,6 +236,10 @@ class FlangerDSP : public DSP
uint32 m_min = 0;
uint32 m_max = 0;

float m_feedback = 0.f;
float m_stereoWidth = 0.f;
float m_volume = 0.f;

Vector<float> m_sampleBuffer;
uint32 m_time = 0;
uint32 m_bufferLength = 0;
Expand Down Expand Up @@ -294,4 +301,4 @@ class PitchShiftDSP : public DSP

private:
class PitchShiftDSP_Impl *m_impl;
};
};
48 changes: 34 additions & 14 deletions Audio/src/DSP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,6 @@ void WobbleDSP::Process(float *out, uint32 numSamples)

BQFDSP::Process(&out[i * 2], 1);

// Apply slight mixing
float mix = 0.5f;
out[i * 2 + 0] = out[i * 2 + 0] * mix + s[0] * (1.0f - mix);
out[i * 2 + 1] = out[i * 2 + 1] * mix + s[1] * (1.0f - mix);

Expand Down Expand Up @@ -522,9 +520,21 @@ void FlangerDSP::SetDelayRange(uint32 offset, uint32 depth)
const float mult = (float)m_sampleRate / 44100.f;
m_min = static_cast<uint32>(min * mult);
m_max = static_cast<uint32>(max * mult);
m_bufferLength = m_max * 2;
m_bufferLength = (m_max + 1) * 2;
m_sampleBuffer.resize(m_bufferLength);
}
void FlangerDSP::SetFeedback(float feedback)
{
m_feedback = feedback;
}
void FlangerDSP::SetStereoWidth(float stereoWidth)
{
m_stereoWidth = stereoWidth;
}
void FlangerDSP::SetVolume(float volume)
{
m_volume = volume;
}
void FlangerDSP::Process(float *out, uint32 numSamples)
{
if (m_bufferLength <= 0)
Expand All @@ -535,6 +545,7 @@ void FlangerDSP::Process(float *out, uint32 numSamples)

const uint32 startSample = GetStartSample();
const uint32 currentSample = GetCurrentSample();
const uint32 depth = m_max - m_min;

for (uint32 i = 0; i < numSamples; i++)
{
Expand All @@ -543,24 +554,33 @@ void FlangerDSP::Process(float *out, uint32 numSamples)
continue;
}
// Determine where we want to sample past samples
float f = fmodf(((float)m_time / (float)m_length), 1.f);
float f = fmodf(((float)m_time / ((float)m_length * 2)), 1.f);
f = fabsf(f * 2 - 1);
uint32 d = (uint32)(m_min + ((m_max - 1) - m_min) * (f));
uint32 dLeft = (uint32)(m_max - (depth * f));
uint32 dRight = dLeft + (uint32)(m_stereoWidth * depth);
// "fold" dRight to fit [m_min,m_max] range: matches KSM behavior
if (dRight > m_max) dRight = m_max - (dRight - m_max);

// TODO: clean up?
int32 samplePos = ((int)m_bufferOffset - (int)d * 2) % (int)m_bufferLength;
if (samplePos < 0)
samplePos = m_bufferLength + samplePos;
int32 samplePosLeft = ((int)m_bufferOffset - (int)dLeft * 2) % (int)m_bufferLength;
if (samplePosLeft < 0) samplePosLeft = m_bufferLength + samplePosLeft;
int32 samplePosRight = ((int)m_bufferOffset - (int)dRight * 2 + 1) % (int)m_bufferLength;
if (samplePosRight < 0) samplePosRight = m_bufferLength + samplePosRight;

// Inject new sample
data[m_bufferOffset + 0] = out[i * 2];
data[m_bufferOffset + 1] = out[i * 2 + 1];
data[m_bufferOffset + 0] = Math::Clamp(
(m_feedback * data[samplePosLeft] + out[i * 2]) * (mix * m_volume + (1.f - mix)), -1.f,
1.f);
data[m_bufferOffset + 1] = Math::Clamp(
(m_feedback * data[samplePosRight] + out[i * 2 + 1]) * (mix * m_volume + (1.f - mix)),
-1.f, 1.f);

// Apply delay
out[i * 2] = (data[samplePos] + out[i * 2]) * 0.5f * mix +
out[i * 2] * (1 - mix);
out[i * 2 + 1] = (data[samplePos + 1] + out[i * 2 + 1]) * 0.5f * mix +
out[i * 2 + 1] * (1 - mix);
out[i * 2] = Math::Clamp(
(mix * data[samplePosLeft] + out[i * 2]) * (mix * m_volume + (1.f - mix)), -1.f, 1.f);
out[i * 2 + 1] = Math::Clamp(
(mix * data[samplePosRight] + out[i * 2 + 1]) * (mix * m_volume + (1.f - mix)), -1.f,
1.f);

m_bufferOffset += 2;
if (m_bufferOffset >= m_bufferLength)
Expand Down
6 changes: 6 additions & 0 deletions Beatmap/include/Beatmap/AudioEffects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ struct AudioEffect
EffectParam<int32> offset;
// Depth of the effect (samples)
EffectParam<int32> depth;
// Feedback (0-1)
EffectParam<float> feedback;
// Stereo width (0-1)
EffectParam<float> stereoWidth;
// Volume of added source audio + delayed source audio (0-1)
EffectParam<float> volume;
} flanger;
struct
{
Expand Down
10 changes: 7 additions & 3 deletions Beatmap/src/AudioEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,13 @@ static AudioEffect CreateDefault(EffectType type)
ret.wobble.q = FloatRange(2.0f);
break;
case EffectType::Flanger:
ret.duration = TimeRange(2000);
ret.flanger.offset = IntRange(10);
ret.flanger.depth = IntRange(40);
ret.duration = TimeRange(2.0f);
ret.mix = FloatRange(0.8f);
ret.flanger.offset = IntRange(30);
ret.flanger.depth = IntRange(45);
ret.flanger.feedback = FloatRange(0.6f);
ret.flanger.stereoWidth = FloatRange(0.0f);
ret.flanger.volume = FloatRange(0.75f);
break;
case EffectType::SwitchAudio:
ret.switchaudio.index = -1;
Expand Down
60 changes: 38 additions & 22 deletions Beatmap/src/BeatmapFromKSH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ struct MultiParam
{
Float,
Samples,
Milliseconds,
Int,
};
Type type;
Expand Down Expand Up @@ -164,22 +165,20 @@ struct MultiParamRange
r.isRange = isRange;
return r;
}
EffectParam<EffectDuration> ToDurationParam(bool isAbsolute)
EffectParam<EffectDuration> ToDurationParam()
{
EffectParam<EffectDuration> r;
if (isAbsolute)
if (params[0].type == MultiParam::Milliseconds)
{
if (params[0].type == MultiParam::Float)
{
r = EffectParam<EffectDuration>((int)(1000.f * params[0].fval), (int)(1000.f * params[1].fval));
}
else
{
r = EffectParam<EffectDuration>(params[0].ival, params[1].ival);
}
r = EffectParam<EffectDuration>(params[0].ival, params[1].ival);
}
else if (params[0].type == MultiParam::Float)
{
r = EffectParam<EffectDuration>(params[0].fval, params[1].fval);
}
else {
r = params[0].type == MultiParam::Float ? EffectParam<EffectDuration>(params[0].fval, params[1].fval) : EffectParam<EffectDuration>(params[0].ival, params[1].ival);
else
{
r = EffectParam<EffectDuration>((float)params[0].ival, (float)params[1].ival);
}
r.isRange = isRange;
return r;
Expand Down Expand Up @@ -210,6 +209,20 @@ static MultiParam ParseParam(const String &in)
ret.type = MultiParam::Samples;
sscanf(*in, "%i", &ret.ival);
}
else if (in.find("ms") != -1)
{
ret.type = MultiParam::Milliseconds;
float milliseconds = 0;
sscanf(*in, "%f", &milliseconds);
ret.ival = (int)(milliseconds);
}
else if (in.find("s") != -1)
{
ret.type = MultiParam::Milliseconds;
float seconds = 0;
sscanf(*in, "%f", &seconds);
ret.ival = (int)(seconds * 1000.0);
}
else if (in.find("%") != -1)
{
ret.type = MultiParam::Float;
Expand Down Expand Up @@ -319,11 +332,11 @@ AudioEffect ParseCustomEffect(const KShootEffectDefinition &def, Vector<String>
target = param->ToFloatParam();
}
};
auto AssignDurationIfSet = [&](EffectParam<EffectDuration> &target, const String &name, bool absolute) {
auto AssignDurationIfSet = [&](EffectParam<EffectDuration> &target, const String &name) {
auto *param = params.Find(name);
if (param)
{
target = param->ToDurationParam(absolute);
target = param->ToDurationParam();
}
};
auto AssignSamplesIfSet = [&](EffectParam<int32> &target, const String &name) {
Expand Down Expand Up @@ -354,31 +367,34 @@ AudioEffect ParseCustomEffect(const KShootEffectDefinition &def, Vector<String>
AssignSamplesIfSet(effect.bitcrusher.reduction, "amount");
break;
case EffectType::Echo:
AssignDurationIfSet(effect.duration, "waveLength", false);
AssignDurationIfSet(effect.duration, "waveLength");
AssignFloatIfSet(effect.echo.feedback, "feedbackLevel");
break;
case EffectType::Flanger:
AssignDurationIfSet(effect.duration, "period", true);
AssignDurationIfSet(effect.duration, "period");
AssignIntIfSet(effect.flanger.depth, "depth");
AssignIntIfSet(effect.flanger.offset, "delay");
AssignFloatIfSet(effect.flanger.feedback, "feedback");
AssignFloatIfSet(effect.flanger.stereoWidth, "stereoWidth");
AssignFloatIfSet(effect.flanger.volume, "volume");
break;
case EffectType::Gate:
AssignDurationIfSet(effect.duration, "waveLength", false);
AssignDurationIfSet(effect.duration, "waveLength");
AssignFloatIfSet(effect.gate.gate, "rate");
break;
case EffectType::Retrigger:
AssignDurationIfSet(effect.duration, "waveLength", false);
AssignDurationIfSet(effect.duration, "waveLength");
AssignFloatIfSet(effect.retrigger.gate, "rate");
AssignDurationIfSet(effect.retrigger.reset, "updatePeriod", false);
AssignDurationIfSet(effect.retrigger.reset, "updatePeriod");
break;
case EffectType::Wobble:
AssignDurationIfSet(effect.duration, "waveLength", false);
AssignDurationIfSet(effect.duration, "waveLength");
AssignFloatIfSet(effect.wobble.min, "loFreq");
AssignFloatIfSet(effect.wobble.max, "hiFreq");
AssignFloatIfSet(effect.wobble.q, "Q");
break;
case EffectType::TapeStop:
AssignDurationIfSet(effect.duration, "speed", false);
AssignDurationIfSet(effect.duration, "speed");
break;
case EffectType::SwitchAudio:
AssignIntIfSet(effect.switchaudio.index, "index");
Expand Down Expand Up @@ -1372,4 +1388,4 @@ bool Beatmap::m_ProcessKShootMap(BinaryStream &input, bool metadataOnly)
ObjectState::SortArray(m_objectStates);

return true;
}
}
5 changes: 3 additions & 2 deletions Main/src/Audio/GameAudioEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ DSP *GameAudioEffect::CreateDSP(const TimingPoint &tp, float filterInput, uint32
fl->SetLength(actualLength);
fl->SetDelayRange(abs(flanger.offset.Sample(filterInput)),
abs(flanger.depth.Sample(filterInput)));
fl->SetFeedback(flanger.feedback.Sample(filterInput));
fl->SetStereoWidth(flanger.stereoWidth.Sample(filterInput));
fl->SetVolume(flanger.volume.Sample(filterInput));
ret = fl;
break;
}
Expand Down Expand Up @@ -176,8 +179,6 @@ void GameAudioEffect::SetParams(DSP *dsp, AudioPlayback &playback, HoldObjectSta
case EffectType::Flanger:
{
FlangerDSP *fl = (FlangerDSP *)dsp;
double delay = (noteDuration) / 1000.0;
fl->SetDelayRange(10, 40);
break;
}
case EffectType::PitchShift:
Expand Down

0 comments on commit 1031612

Please sign in to comment.