mirror of
https://codeberg.org/armin/chromaflock.git
synced 2026-09-01 04:10:47 +02:00
Add delay invert + flatten LEDs; fix flatten to narrow bounce width instead of shortening tail
This commit is contained in:
parent
0af34cd89d
commit
cd2caf7821
4 changed files with 67 additions and 18 deletions
|
|
@ -13,13 +13,20 @@ public:
|
|||
writePos = 0;
|
||||
}
|
||||
|
||||
void setParameters(float timeMs, float fb, float mx, bool pingpong = false) {
|
||||
void setParameters(float timeMs, float fb, float mx, bool pingpong = false,
|
||||
bool invert = false, bool flatten = false) {
|
||||
timeSamplesF = timeMs * 0.001f * static_cast<float>(sampleRate);
|
||||
float bufMax = static_cast<float>(bufferL.size()) - 1.0f;
|
||||
timeSamplesF = std::clamp(timeSamplesF, 1.0f, bufMax);
|
||||
feedback = std::clamp(fb, 0.0f, 0.95f);
|
||||
mix = std::clamp(mx, 0.0f, 1.0f);
|
||||
pingPong = pingpong;
|
||||
pingSign = invert ? -1 : 1;
|
||||
// Flatten reduces the bounce *width* by 60% (0.4 of full) without
|
||||
// touching the echo tail — tail length is governed solely by feedback.
|
||||
pingStrength = flatten ? 0.4f : 1.0f;
|
||||
timeSamplesI = static_cast<int>(std::round(timeSamplesF));
|
||||
if (timeSamplesI < 1) timeSamplesI = 1;
|
||||
}
|
||||
|
||||
void process(float& left, float& right) {
|
||||
|
|
@ -32,27 +39,40 @@ public:
|
|||
int i1 = (i0 + 1) % bufSize;
|
||||
float frac = readPosF - std::floor(readPosF);
|
||||
|
||||
float outL = bufferL[i0] * (1.0f - frac) + bufferL[i1] * frac;
|
||||
float outR = bufferR[i0] * (1.0f - frac) + bufferR[i1] * frac;
|
||||
|
||||
if (pingPong) {
|
||||
// Classic ping-pong: the (summed) input enters one line and each
|
||||
// echo is bounced to the opposite channel on the next repeat, so the
|
||||
// taps alternate L/R. Only the cross-coupled echo is fed into the
|
||||
// opposite line (never the dry input) so the bounce is audible even
|
||||
// for a mono source where L == R.
|
||||
// Mono echo line. The tail length is set by feedback alone; the
|
||||
// ping-pong bounce is applied as alternating L/R panning whose
|
||||
// width is scaled by pingStrength, so flattening narrows the image
|
||||
// without shortening the number of repeats.
|
||||
float out = bufferL[i0] * (1.0f - frac) + bufferL[i1] * frac;
|
||||
|
||||
float in = 0.5f * (left + right);
|
||||
bufferL[writePos] = in + outR * feedback;
|
||||
bufferR[writePos] = outL * feedback;
|
||||
bufferL[writePos] = in + out * feedback;
|
||||
|
||||
pingCounter += 1;
|
||||
if (pingCounter >= timeSamplesI) {
|
||||
pingCounter -= timeSamplesI;
|
||||
pingPhase = -pingPhase;
|
||||
}
|
||||
float s = pingStrength * static_cast<float>(pingPhase * pingSign);
|
||||
float lPan = 0.5f + 0.5f * s;
|
||||
float rPan = 0.5f - 0.5f * s;
|
||||
|
||||
float wet = out * mix;
|
||||
left = left * (1.0f - mix) + wet * lPan;
|
||||
right = right * (1.0f - mix) + wet * rPan;
|
||||
} else {
|
||||
float outL = bufferL[i0] * (1.0f - frac) + bufferL[i1] * frac;
|
||||
float outR = bufferR[i0] * (1.0f - frac) + bufferR[i1] * frac;
|
||||
|
||||
bufferL[writePos] = left + outL * feedback;
|
||||
bufferR[writePos] = right + outR * feedback;
|
||||
|
||||
left = left * (1.0f - mix) + outL * mix;
|
||||
right = right * (1.0f - mix) + outR * mix;
|
||||
}
|
||||
|
||||
writePos = (writePos + 1) % bufSize;
|
||||
|
||||
left = left * (1.0f - mix) + outL * mix;
|
||||
right = right * (1.0f - mix) + outR * mix;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -60,7 +80,12 @@ private:
|
|||
int writePos = 0;
|
||||
double sampleRate = 44100;
|
||||
float timeSamplesF = 8820.0f;
|
||||
int timeSamplesI = 8820;
|
||||
float feedback = 0.3f;
|
||||
float mix = 0.25f;
|
||||
bool pingPong = false;
|
||||
int pingSign = 1;
|
||||
float pingStrength = 1.0f;
|
||||
int pingCounter = 0;
|
||||
int pingPhase = 1;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue