stereo chorus

This commit is contained in:
Gordon JC Pearce 2025-08-19 23:33:47 +01:00
parent 7b138536ef
commit 2ea0409fe7
4 changed files with 24 additions and 32 deletions

View File

@ -23,12 +23,11 @@
#include <cstdio>
Chorus::Chorus(uint32_t xbufferSize, double xsampleRate) { // no parameters, programs, or states
extern double sampleRate;
extern uint32_t bufferSize;
bufferSize = xbufferSize;
sampleRate = xsampleRate;
Chorus::Chorus() { // no parameters, programs, or states
lpfIn = new float[bufferSize];
lpfOut1 = new float[bufferSize];
lpfOut2 = new float[bufferSize];
ram = new float[DELAYSIZE]; // probably needs to be calculated based on sample rate
@ -36,8 +35,10 @@ Chorus::Chorus(uint32_t xbufferSize, double xsampleRate) { // no parameters, pr
fastPhase = 0;
slowPhase = 0;
postFilter1 = new SVF(8000, 1.3);
postFilter2 = new SVF(8000, 0.54);
postFilter1l = new SVF(POSTCUTOFF, .546);
postFilter2l = new SVF(POSTCUTOFF, 1.324);
postFilter1r = new SVF(POSTCUTOFF, .546);
postFilter2r = new SVF(POSTCUTOFF, 1.324);
// lfo values taken from a rough simulation
fastOmega = 6.283 * 5.7 / sampleRate; // approximate, can be adjusted
@ -45,18 +46,18 @@ Chorus::Chorus(uint32_t xbufferSize, double xsampleRate) { // no parameters, pr
// zero out the delay buffer
memset(ram, 0, sizeof(float) * DELAYSIZE);
memset(lpfIn, 0, sizeof(float) * bufferSize);
memset(lpfOut1, 0, sizeof(float) * bufferSize);
memset(lpfOut2, 0, sizeof(float) * bufferSize);
}
Chorus::~Chorus() {
delete lpfIn;
delete lpfOut1;
delete lpfOut2;
delete ram;
delete postFilter1;
delete postFilter2;
delete postFilter1l;
delete postFilter2l;
delete postFilter1r;
delete postFilter2r;
}
void Chorus::run(const float *input, float **outputs, uint32_t frames) {
@ -76,15 +77,6 @@ void Chorus::run(const float *input, float **outputs, uint32_t frames) {
ram[delayptr] = input[i];
// lowpass filter
// now we need to calculate the delay
// I don't know how long the Solina's delay lines are so I'm guessing 2-4ms for now
// normalised mod depths, from a quick simulation of the LFO block:
// 0deg 0.203 slow 0.635 fast
// 120deg 0.248 slow 0.745 fast
// 240deg 0.252 slow 0.609 fast
#define BASE 0.05
#define AMT 0.00175
@ -121,13 +113,15 @@ void Chorus::run(const float *input, float **outputs, uint32_t frames) {
s0 = ram[tap & 0x3ff];
out240 = ((s1 - s0) * frac) + s0;
lpfOut1[i] = (out0 + out120 + out240) / 3;
lpfOut1[i] = (out0 + (out120 * 0.66) + (out240 * 0.33));
lpfOut2[i] = (out0 + (out120 * 0.33) + (out240 * 0.66));
delayptr++;
delayptr &= 0x3ff;
}
postFilter1->runSVF(lpfOut1, lpfOut2, frames);
postFilter2->runSVF(lpfOut2, outputs[0], frames);
memcpy (outputs[1], outputs[0], frames * sizeof(float)); // only mono output for now
postFilter1l->runSVF(lpfOut1, lpfOut1, frames);
postFilter2l->runSVF(lpfOut1, outputs[0], frames);
postFilter1r->runSVF(lpfOut2, lpfOut2, frames);
postFilter2r->runSVF(lpfOut2, outputs[1], frames);
}

View File

@ -24,15 +24,15 @@
// total size of delay line buffer
#define DELAYSIZE 1028
#define POSTCUTOFF 10000
class Chorus {
public:
Chorus(uint32_t xbufferSize, double xsampleRate);
Chorus();
~Chorus();
void run(const float *input, float **outputs, uint32_t frames);
double sampleRate;
private:
uint32_t bufferSize;
double fastPhase, fastOmega;
double slowPhase, slowOmega;
double fastLfo, slowLfo;
@ -43,6 +43,6 @@ class Chorus {
float *lpfIn;
float *lpfOut1, *lpfOut2;
SVF *preFilter, *postFilter1, *postFilter2;
SVF *postFilter1l, *postFilter2l, *postFilter1r, *postFilter2r;
};
#endif

View File

@ -31,9 +31,7 @@ extern uint32_t bufferSize;
// unit-local global
static float envTc[2];
// Generator::Generator(uint32_t bufferSize, double xSampleRate) {
Generator::Generator() {
// sampleRate = xSampleRate;
output = new float[bufferSize];
// create the phase increments for each semitone
for (uint8_t i = 0; i < 12; i++) {

View File

@ -20,6 +20,7 @@
double sampleRate;
uint32_t bufferSize;
START_NAMESPACE_DISTRHO
Sonnenlicht::Sonnenlicht() : Plugin(kParameterCount, 0, 0) {
@ -27,11 +28,10 @@ Sonnenlicht::Sonnenlicht() : Plugin(kParameterCount, 0, 0) {
sampleRate = getSampleRate();
bufferSize = getBufferSize();
genny = new Generator();
assigner = new Assigner(genny->voices);
chorus = new Chorus(getBufferSize(), sampleRate);
chorus = new Chorus();
}
Sonnenlicht::~Sonnenlicht() {