sample rate stuff for chorus
This commit is contained in:
parent
6f7f9340f1
commit
5ea59fb299
|
|
@ -21,24 +21,21 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
Chorus::Chorus() {
|
Chorus::Chorus() {
|
||||||
lpfOut1 = new float[bufferSize];
|
lpfOut1 = new float[bufferSize];
|
||||||
lpfOut2 = new float[bufferSize];
|
lpfOut2 = new float[bufferSize];
|
||||||
ram = new float[DELAYSIZE]; // probably needs to be calculated based on sample rate
|
ram = new float[DELAYSIZE];
|
||||||
|
|
||||||
fastPhase = 0;
|
lfoPhase = 1;
|
||||||
|
lfoSpeed = 6.283 * 10.7 / sampleRate; // plainly silly value to show if it hasn't been set
|
||||||
|
|
||||||
// not quite Butterworth but you'd never hear the difference
|
// not quite Butterworth but you'd never hear the difference
|
||||||
|
// these are calculated from the real-world component values
|
||||||
postFilter1l = new SVF(9688, .549);
|
postFilter1l = new SVF(9688, .549);
|
||||||
postFilter2l = new SVF(10377, 1.291);
|
postFilter2l = new SVF(10377, 1.291);
|
||||||
postFilter1r = new SVF(9688, .549);
|
postFilter1r = new SVF(9688, .549);
|
||||||
postFilter2r = new SVF(10377, 1.291);
|
postFilter2r = new SVF(10377, 1.291);
|
||||||
|
|
||||||
// lfo values taken from a rough simulation
|
|
||||||
fastOmega = 6.283 * 0.7 / sampleRate; // approximate, can be adjusted
|
|
||||||
|
|
||||||
// zero out the delay buffer
|
// zero out the delay buffer
|
||||||
memset(ram, 0, sizeof(float) * DELAYSIZE);
|
memset(ram, 0, sizeof(float) * DELAYSIZE);
|
||||||
memset(lpfOut1, 0, sizeof(float) * bufferSize);
|
memset(lpfOut1, 0, sizeof(float) * bufferSize);
|
||||||
|
|
@ -56,32 +53,33 @@ Chorus::~Chorus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chorus::run(float* input, float** outputs, uint32_t frames) {
|
void Chorus::run(float* input, float** outputs, uint32_t frames) {
|
||||||
// actual effects here
|
// run highpass / bass boost and stereo chorus effect for one full block
|
||||||
|
|
||||||
// FIXME add highpass filter
|
|
||||||
|
|
||||||
// now run the DSP
|
|
||||||
float s0 = 0, s1 = 0;
|
float s0 = 0, s1 = 0;
|
||||||
float lfoMod, dly1, frac, flt;
|
float lfoMod, dly1, frac, flt;
|
||||||
uint16_t tap, delay;
|
uint16_t tap, delay;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < frames; i++) {
|
for (uint32_t i = 0; i < frames; i++) {
|
||||||
// run a step of LFO
|
// run a step of LFO
|
||||||
fastPhase += fastOmega;
|
lfoPhase += (lfoState & 0x01) ? lfoSpeed : -lfoSpeed;
|
||||||
if (fastPhase > 6.283) fastPhase -= 6.283;
|
|
||||||
|
|
||||||
flt = ((hpdelay - input[i]) * hpcut) + input[i];
|
if (abs(lfoPhase) > 1) {
|
||||||
hpdelay = flt;
|
// lfoPhase -= 2;
|
||||||
input[i] += (flt * hpgain);
|
lfoState++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// highpass/bass boost
|
||||||
|
flt = ((input[i] - hpDelay) * hpCut) + hpDelay;
|
||||||
|
hpDelay = flt;
|
||||||
|
input[i] += (flt * hpGain);
|
||||||
|
|
||||||
ram[delayptr] = input[i];
|
ram[delayptr] = input[i];
|
||||||
|
|
||||||
|
// delays in milliseconds
|
||||||
#define BASE 0.005
|
#define BASE 0.005
|
||||||
#define AMT 0.00175
|
#define AMT 0.00175
|
||||||
|
|
||||||
// FIXME make this triangle not sine, and move arithmetic out of mainloop
|
dly1 = (BASE + (AMT * lfoPhase)) * sampleRate;
|
||||||
lfoMod = sin(fastPhase);
|
|
||||||
dly1 = (BASE + (AMT * lfoMod)) * sampleRate;
|
|
||||||
delay = (int)dly1;
|
delay = (int)dly1;
|
||||||
frac = dly1 - delay;
|
frac = dly1 - delay;
|
||||||
|
|
||||||
|
|
@ -90,7 +88,7 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
|
||||||
s0 = ram[tap & 0x3ff];
|
s0 = ram[tap & 0x3ff];
|
||||||
lpfOut1[i] = ((s1 - s0) * frac) + s0;
|
lpfOut1[i] = ((s1 - s0) * frac) + s0;
|
||||||
|
|
||||||
dly1 = (BASE - (AMT * lfoMod)) * sampleRate;
|
dly1 = (BASE - (AMT * lfoPhase)) * sampleRate;
|
||||||
delay = (int)dly1;
|
delay = (int)dly1;
|
||||||
frac = dly1 - delay;
|
frac = dly1 - delay;
|
||||||
|
|
||||||
|
|
@ -99,9 +97,6 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
|
||||||
s0 = ram[tap & 0x3ff];
|
s0 = ram[tap & 0x3ff];
|
||||||
lpfOut2[i] = ((s1 - s0) * frac) + s0;
|
lpfOut2[i] = ((s1 - s0) * frac) + s0;
|
||||||
|
|
||||||
// lpfOut1[i] = input[i] + 1.2 * out0; //(out0 + (out120 * 0.66) + (out240 * 0.33));
|
|
||||||
// lpfOut2[i] = input[i] + 1.2 * out120; //(out0 + (out120 * 0.33) + (out240 * 0.66));
|
|
||||||
|
|
||||||
delayptr++;
|
delayptr++;
|
||||||
delayptr &= 0x3ff;
|
delayptr &= 0x3ff;
|
||||||
}
|
}
|
||||||
|
|
@ -119,22 +114,27 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chorus::setHpf(uint8_t mode) {
|
void Chorus::setHpf(uint8_t mode) {
|
||||||
|
// the simple 1-pole lowpass has its output
|
||||||
|
// subtracted from input for the highpass
|
||||||
|
// or added for bass boost
|
||||||
|
// cutoff is calculated as
|
||||||
|
// k = 1-exp(-2pi * Fc * sampleRate)
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
hpcut = 0.91245;
|
hpCut = 1 - exp(-6.283 * 720 / sampleRate);
|
||||||
hpgain = -1;
|
hpGain = -1;
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
hpcut = 0.97097;
|
hpCut = 1 - exp(-6.283 * 225 / sampleRate);
|
||||||
hpgain = -1;
|
hpGain = -1;
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
hpcut = 1;
|
hpCut = 1;
|
||||||
hpgain = 0;
|
hpGain = 0;
|
||||||
break;
|
break;
|
||||||
case 0x18:
|
case 0x18:
|
||||||
hpcut = 0.99088;
|
hpCut = 1 - exp(-6.283 * 85 / sampleRate);
|
||||||
hpgain = 1;
|
hpGain = 1.707;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -147,11 +147,11 @@ void Chorus::setChorus(uint8_t mode) {
|
||||||
break;
|
break;
|
||||||
case 0x40:
|
case 0x40:
|
||||||
gain = 1.2;
|
gain = 1.2;
|
||||||
fastOmega = 6.283 * 0.5 / sampleRate;
|
lfoSpeed = 6.283 * 0.5 / sampleRate;
|
||||||
break; // approximate, can be adjusted
|
break;
|
||||||
case 0x00:
|
case 0x00:
|
||||||
gain = 1.2;
|
gain = 1.2;
|
||||||
fastOmega = 6.283 * 0.9 / sampleRate;
|
lfoSpeed = 6.283 * 0.9 / sampleRate;
|
||||||
break; // approximate, can be adjusted
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,18 @@ class Chorus {
|
||||||
void setChorus(uint8_t mode);
|
void setChorus(uint8_t mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double fastPhase = 0, fastOmega = 0;
|
double lfoPhase = 0, lfoSpeed = 0;
|
||||||
|
uint8_t lfoState=0;
|
||||||
float gain = 1.2;
|
float gain = 1.2;
|
||||||
|
|
||||||
|
|
||||||
uint16_t delayptr = 0;
|
uint16_t delayptr = 0;
|
||||||
|
|
||||||
float* ram;
|
float* ram;
|
||||||
float* lpfIn;
|
float* lpfIn;
|
||||||
float *lpfOut1, *lpfOut2;
|
float *lpfOut1, *lpfOut2;
|
||||||
|
|
||||||
float hpdelay=0, hpcut=0, hpgain=1;
|
float hpDelay=0, hpCut=0, hpGain=0;
|
||||||
|
|
||||||
SVF *postFilter1l, *postFilter2l, *postFilter1r, *postFilter2r;
|
SVF *postFilter1l, *postFilter2l, *postFilter1r, *postFilter2r;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue