Skip to content

Instantly share code, notes, and snippets.

@Xenakios
Created June 27, 2021 16:43
Show Gist options
  • Save Xenakios/b1d7a00fdb0639d2af8fa9d99ad143f9 to your computer and use it in GitHub Desktop.
Save Xenakios/b1d7a00fdb0639d2af8fa9d99ad143f9 to your computer and use it in GitHub Desktop.
class StarGateReverb
{
public:
StarGateReverb()
{
for (int i = 0; i < dram.size(); ++i)
dram[i] = 0;
for (int i = 0; i < delayTaps.size(); ++i)
{
delayTaps[i] = 0;
gainCeiling[i] = 0;
}
auto coeffs = juce::dsp::IIR::Coefficients<float>::makeFirstOrderHighPass(44100.0, 25.0f);
juce::dsp::ProcessSpec spec;
spec.maximumBlockSize = 1;
spec.numChannels = 1;
spec.sampleRate = 44100;
for (int i = 0; i < 4; ++i)
{
hpFilters[i].coefficients = coeffs;
hpFilters[i].prepare(spec);
}
}
std::pair<float,float> processSample(float in_left, float in_right)
{
in_left = (in_left + in_right) * 0.5f;
//in_left = hpFilters[3].processSample(in_left);
dram[delayTaps[0]] = juce::jmap<float>(in_left + feedbackStored, -1.0f, 1.0, 0, 65535);
gainBaseAddr = (decayTime << 5) | (program << 8);
preDelay_high = preDelay >> 3;
preDelay_low = preDelay << 5;
preDelay_low = preDelay_low >> 5;
delayBaseAddr = (preDelay_low << 6) | (program << 9) | (preDelay_high << 12);
//calculate write tap (=test tap)
//calculate address row
result = nROW;
bit6 = result << 1;
bit6 = bit6 >> 7;
MSB = result;
MSB = MSB >> 7;
delayCarryOut = result >> 8;
rowDelay = result << 2;
rowDelay = (rowDelay >> 1) | bit6 | (MSB << 7);
//calculate address column
result = nCOLUMN + delayCarryOut;
colDelay = result << 2;
colDelay = colDelay >> 2;
//store address
delayTaps[0] = (rowDelay)+(colDelay * 256);
//calculate gain value
gainAddress = gainBaseAddr + 7;
gainOut = U78[gainAddress];
//store gain value
gainCeiling[0] = gainOut; //only needed for testing purposes
//calculate feedback taps
dly_mod_addr = delayModBaseAddr + 7;
dly_addr = delayBaseAddr + 16;
gainModContAddress = gainModContBaseAddr + 8;
gainAddress = gainBaseAddr + 8;
for (int d = 0; d < 15; d++)
{
result = U79[dly_mod_addr + d] + nROW;
bit6 = result << 1;
bit6 = bit6 >> 7;
MSB = result;
MSB = MSB >> 7;
delayCarryOut = result >> 8;
rowDelay = result << 2;
rowDelay = (rowDelay >> 1) | bit6 | (MSB << 7);
result = U69[dly_addr + d * 2] + nCOLUMN + delayCarryOut;
colDelay = result << 2;
colDelay = colDelay >> 2;
delayTaps[1 + d] = (rowDelay)+(colDelay * 256);
gainModContOut = U76[gainModContAddress + d];
nGainModEnable = gainModContOut >> 3;
gainModContOut = gainModContOut << 5;
gainModContOut = gainModContOut >> 5;
gainModAddress = gainModContOut | gainModBaseAddr;
gainModOut = U77[gainModAddress];
gainOut = U78[gainAddress + d];
gainOut = gainOut;
if (gainModOut < gainOut && nGainModEnable == 0)
{
gainCeiling[1 + d] = gainModOut;
}
else
{
gainCeiling[1 + d] = gainOut;
}
}
//calculate output taps
gainAddress = gainBaseAddr + 23;
dly_mod_addr = delayBaseAddr + 45;
dly_addr = delayBaseAddr + 46;
for (int d = 0; d < 8; d++)
{
result = U69[dly_mod_addr + d * 2] + nROW;
bit6 = result << 1;
bit6 = bit6 >> 7;
MSB = result;
MSB = MSB >> 7;
delayCarryOut = result >> 8;
rowDelay = result << 2;
rowDelay = (rowDelay >> 1) | bit6 | (MSB << 7);
result = U69[dly_addr + d * 2] + nCOLUMN + delayCarryOut;
colDelay = result << 2;
colDelay = colDelay >> 2;
delayTaps[16 + d] = (rowDelay)+(colDelay * 256);
gainOut = U78[gainAddress + d];
gainCeiling[16 + d] = gainOut;
}
//mod rate counter
modClockOut = modClockOut + 1;
if (modClockOut == 16)
{
modRateCount = rateLvl | (program << 4);
modClockOut = U71[modRateCount];
}
modCarry = (modClockOut + 1) >> 4;
//increment write address & wraparound if >16bit
writeAddressCount = writeAddressCount - 1;
if (writeAddressCount < 0)
{
writeAddressCount = 16383;
}
nROW = writeAddressCount;
nCOLUMN = writeAddressCount >> 8;
MCCK = modCarry;
if (MCCK == 1)
{
modCount = modCount + 1;
if (modCount > 8191)
{
modCount = 0;
}
gainModContBaseAddr = (modCount >> 6) << 5;
gainModBaseAddr = modCount << 7;
gainModBaseAddr = gainModBaseAddr >> 4;
delayModCount = modCount >> 6;
delayModBaseAddr = delayModCount << 5;
}
float out_left = 0.0f;
float out_right = 0.0f;
for (int i = 0; i < 4; ++i)
{
out_left += juce::jmap((float)dram[delayTaps[16 + i]] * ((float)gainCeiling[16 + i] / 256.0f), 0.0f, 65535.0f, -1.0f, 1.0f);
out_right += juce::jmap((float)dram[delayTaps[20 + i]] * ((float)gainCeiling[20 + i] / 256.0f), 0.0f, 65535.0f, -1.0f, 1.0f);
}
out_left = hpFilters[0].processSample(out_left);
out_right = hpFilters[1].processSample(out_right);
feedbackStored = 0.0f;
for (int i = 1; i < 16; ++i)
{
float gain = (float)gainCeiling[i] / 256.0f;
feedbackStored += juce::jmap((float)dram[delayTaps[i]] * gain, 0.0f, 65535.0f, -1.0f, 1.0f);
}
feedbackStored *= 0.05;
//feedbackStored = hpFilters[2].processSample(feedbackStored);
return { out_left,out_right };
}
__uint8_t program = 7; // program from low to high (3,2,0,1,5,4,6,7)
__uint8_t preDelay = 1; // predelay from low to high (3,2,0,1,5,4,6,7,11,10,8,9,13,12,14,15)
__uint8_t decayTime = 7; // decay times from low to high (3,2,0,1,5,4,6,7)
__uint8_t rateLvl = 0; // 0-15 for testing
std::array<__uint16_t, 16384> dram;
std::array<__uint16_t, 24> delayTaps;
std::array<__uint8_t, 24> gainCeiling;
__uint16_t gainBaseAddr = 0;
__uint16_t gainAddress = 0;
__uint8_t gainOut = 0;
__uint8_t preDelay_low = 0;
__uint8_t preDelay_high = 0;
__uint16_t delayBaseAddr = 0;
__uint16_t dly_addr = 0;
__uint16_t result = 0;
__uint8_t bit6 = 0;
__uint8_t MSB = 0;
__uint8_t delayCarryOut = 0;
__uint8_t rowDelay = 0;
__uint8_t colDelay = 0;
__uint16_t writeAddressCount = 16383;
__uint8_t nROW = 255;
__uint8_t nCOLUMN = 255;
__uint8_t modRateCount = 0;
__uint8_t modClockOut = 0;
__uint8_t modCarry = 0;
__uint8_t MCCK = 0;
__uint16_t modCount = 0;
__uint8_t delayModCount = 0;
__uint16_t gainModContBaseAddr = 0;
__uint16_t gainModBaseAddr = 0;
__uint16_t gainModContAddress = 0;
__uint16_t gainModAddress = 0;
__uint8_t gainModOut = 0;
__uint8_t gainModContOut = 0;
__uint8_t nGainModEnable = 1;
__uint16_t delayModBaseAddr = 0;
__uint16_t dly_mod_addr = 0;
float feedbackStored = 0.0f;
juce::dsp::IIR::Filter<float> hpFilters[4];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment