#pragma once #include #include #include #include #include "Utils.h" #include "RandomBuffer.h" namespace ReverbHallRoom { class MultitapDelay { public: static const int MaxTaps = 256; static const int DelayBufferSize = 192000 * 2; private: //float delayBuffer[DelayBufferSize] = { 0 }; std::vector delayBuffer; float tapGains[MaxTaps] = { 0 }; float tapPosition[MaxTaps] = { 0 }; std::vector seedValues; int writeIdx; int seed; float crossSeed; int count; float lengthSamples; float decay; public: MultitapDelay() : delayBuffer(DelayBufferSize, 0) { writeIdx = 0; seed = 0; crossSeed = 0.0; count = 1; lengthSamples = 1000; decay = 1.0; UpdateSeeds(); } void SetSeed(int seed) { this->seed = seed; UpdateSeeds(); } void SetCrossSeed(float crossSeed) { this->crossSeed = crossSeed; UpdateSeeds(); } void SetTapCount(int tapCount) { if (tapCount < 1) tapCount = 1; count = tapCount; Update(); } void SetTapLength(int tapLengthSamples) { if (tapLengthSamples < 10) tapLengthSamples = 10; lengthSamples = tapLengthSamples; Update(); } void SetTapDecay(float tapDecay) { decay = tapDecay; } void Process(float* input, float* output, int bufSize) { float lengthScaler = lengthSamples / (float)count; float totalGain = 3.0 / std::sqrtf(1 + count); totalGain *= (1 + decay * 2); for (int i = 0; i < bufSize; i++) { delayBuffer[writeIdx] = input[i]; output[i] = 0; for (int j = 0; j < count; j++) { float offset = tapPosition[j] * lengthScaler; float decayEffective = std::expf(-offset / lengthSamples * 3.3) * decay + (1-decay); int readIdx = writeIdx - (int)offset; if (readIdx < 0) readIdx += DelayBufferSize; output[i] += delayBuffer[readIdx] * tapGains[j] * decayEffective * totalGain; } writeIdx = (writeIdx + 1) % DelayBufferSize; } } void ClearBuffers() { Utils::ZeroBuffer(delayBuffer.data(), DelayBufferSize); } private: void Update() { int s = 0; auto rand = [&]() {return seedValues[s++]; }; for (int i = 0; i < MaxTaps; i++) { float phase = rand() < 0.5 ? 1 : -1; tapGains[i] = Utils::DB2Gainf(-20 + rand() * 20) * phase; tapPosition[i] = i + rand(); } } void UpdateSeeds() { this->seedValues = RandomBuffer::Generate(seed, MaxTaps * 3, crossSeed); Update(); } }; }