string ensemble chorus crudely grafted on
This commit is contained in:
parent
b736c6534e
commit
8f604d10c2
|
|
@ -15,6 +15,8 @@ FILES_DSP = \
|
|||
voice.cpp \
|
||||
tables.cpp \
|
||||
parameters.cpp \
|
||||
svf.cpp \
|
||||
chorus.cpp \
|
||||
peacock.cpp
|
||||
|
||||
FILES_UI = \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
sonnenlicht poly ensemble
|
||||
|
||||
Copyright 2025 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "chorus.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
//extern double sampleRate;
|
||||
//extern uint32_t bufferSize;
|
||||
|
||||
double sampleRate = 48000;
|
||||
uint32_t bufferSize = 1024;
|
||||
Chorus::Chorus() { // no parameters, programs, or states
|
||||
|
||||
lpfOut1 = new float[bufferSize];
|
||||
lpfOut2 = new float[bufferSize];
|
||||
ram = new float[DELAYSIZE]; // probably needs to be calculated based on sample rate
|
||||
|
||||
fastPhase = 0;
|
||||
slowPhase = 0;
|
||||
|
||||
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
|
||||
slowOmega = 6.283 * 0.7 / sampleRate; // again approximate
|
||||
|
||||
// zero out the delay buffer
|
||||
memset(ram, 0, sizeof(float) * DELAYSIZE);
|
||||
memset(lpfOut1, 0, sizeof(float) * bufferSize);
|
||||
memset(lpfOut2, 0, sizeof(float) * bufferSize);
|
||||
}
|
||||
|
||||
Chorus::~Chorus() {
|
||||
delete lpfOut1;
|
||||
delete lpfOut2;
|
||||
delete ram;
|
||||
delete postFilter1l;
|
||||
delete postFilter2l;
|
||||
delete postFilter1r;
|
||||
delete postFilter2r;
|
||||
}
|
||||
|
||||
void Chorus::run(const float *input, float **outputs, uint32_t frames) {
|
||||
// actual effects here
|
||||
|
||||
// now run the DSP
|
||||
float out0 = 0, out120 = 0, out240 = 0, s0 = 0, s1 = 0;
|
||||
float lfoMod, dly1, frac;
|
||||
uint16_t tap, delay;
|
||||
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
// run a step of LFO
|
||||
fastPhase += fastOmega;
|
||||
if (fastPhase > 6.283) fastPhase -= 6.283;
|
||||
slowPhase += slowOmega;
|
||||
if (slowPhase > 6.283) slowPhase -= 6.283;
|
||||
|
||||
ram[delayptr] = input[i];
|
||||
|
||||
#define BASE 0.05
|
||||
#define AMT 0.00175
|
||||
|
||||
// 0 degree delay line
|
||||
lfoMod = 0.203 * sin(fastPhase) + 0.835 * sin(slowPhase);
|
||||
dly1 = (BASE + (AMT * lfoMod)) * sampleRate;
|
||||
delay = (int)dly1;
|
||||
frac = dly1 - delay;
|
||||
|
||||
tap = delayptr - delay;
|
||||
s1 = ram[(tap - 1) & 0x3ff];
|
||||
s0 = ram[tap & 0x3ff];
|
||||
out0 = ((s1 - s0) * frac) + s0;
|
||||
|
||||
// 120 degree delay line
|
||||
lfoMod = 0.248 * sin(fastPhase + 2.09) + 0.745 * sin(slowPhase + 2.09);
|
||||
dly1 = (BASE + (AMT * lfoMod)) * sampleRate;
|
||||
delay = (int)dly1;
|
||||
frac = dly1 - delay;
|
||||
|
||||
tap = delayptr - delay;
|
||||
s1 = ram[(tap - 1) & 0x3ff];
|
||||
s0 = ram[tap & 0x3ff];
|
||||
out120 = ((s1 - s0) * frac) + s0;
|
||||
|
||||
// 240 degree delay line
|
||||
lfoMod = 0.252 * sin(fastPhase + 4.18) + 0.809 * sin(slowPhase + 4.18);
|
||||
dly1 = (BASE + (AMT * lfoMod)) * sampleRate;
|
||||
delay = (int)dly1;
|
||||
frac = dly1 - delay;
|
||||
|
||||
tap = delayptr - delay;
|
||||
s1 = ram[(tap - 1) & 0x3ff];
|
||||
s0 = ram[tap & 0x3ff];
|
||||
out240 = ((s1 - s0) * frac) + s0;
|
||||
|
||||
lpfOut1[i] = (out0 + (out120 * 0.66) + (out240 * 0.33));
|
||||
lpfOut2[i] = (out0 + (out120 * 0.33) + (out240 * 0.66));
|
||||
|
||||
delayptr++;
|
||||
delayptr &= 0x3ff;
|
||||
}
|
||||
|
||||
postFilter1l->runSVF(lpfOut1, lpfOut1, frames);
|
||||
postFilter2l->runSVF(lpfOut1, outputs[0], frames);
|
||||
postFilter1r->runSVF(lpfOut2, lpfOut2, frames);
|
||||
postFilter2r->runSVF(lpfOut2, outputs[1], frames);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
sonnenlicht poly ensemble
|
||||
|
||||
Copyright 2025 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Chorus_HPP
|
||||
#define Chorus_HPP
|
||||
|
||||
#include "svf.hpp"
|
||||
|
||||
// total size of delay line buffer
|
||||
#define DELAYSIZE 1028
|
||||
|
||||
#define POSTCUTOFF 10000
|
||||
|
||||
class Chorus {
|
||||
public:
|
||||
Chorus();
|
||||
~Chorus();
|
||||
void run(const float *input, float **outputs, uint32_t frames);
|
||||
|
||||
private:
|
||||
double fastPhase, fastOmega;
|
||||
double slowPhase, slowOmega;
|
||||
double fastLfo, slowLfo;
|
||||
|
||||
uint16_t delayptr;
|
||||
|
||||
float *ram;
|
||||
float *lpfIn;
|
||||
float *lpfOut1, *lpfOut2;
|
||||
|
||||
SVF *postFilter1l, *postFilter2l, *postFilter1r, *postFilter2r;
|
||||
};
|
||||
#endif
|
||||
|
|
@ -26,11 +26,14 @@ Peacock::Peacock() : Plugin(parameterCount, 0, 0) {
|
|||
m = new Module;
|
||||
ic1 = new Assigner;
|
||||
ic1->voice = voice;
|
||||
chorus = new Chorus;
|
||||
|
||||
}
|
||||
|
||||
Peacock::~Peacock() {
|
||||
free(m);
|
||||
free(ic1);
|
||||
free(chorus);
|
||||
}
|
||||
|
||||
void Peacock::initAudioPort(bool input, uint32_t index, AudioPort& port) {
|
||||
|
|
@ -93,7 +96,9 @@ void Peacock::run(const float**, float** outputs, uint32_t frames, const MidiEve
|
|||
// now we've assembled a full chunk of audio
|
||||
// we'd apply the highpass filter and chorus here
|
||||
// for now just copy left to right
|
||||
memcpy(outputs[1], outputs[0], sizeof(float) * frames);
|
||||
//memcpy(outputs[1], outputs[0], sizeof(float) * frames);
|
||||
chorus->run(outputs[0], outputs, frames);
|
||||
|
||||
//outputs[0][0]=1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "DistrhoPlugin.hpp"
|
||||
#include "assigner.hpp"
|
||||
#include "module.hpp"
|
||||
#include "chorus.hpp"
|
||||
|
||||
START_NAMESPACE_DISTRHO
|
||||
|
||||
class Peacock : public Plugin {
|
||||
|
|
@ -55,6 +57,7 @@ class Peacock : public Plugin {
|
|||
private:
|
||||
Assigner* ic1;
|
||||
Module* m;
|
||||
Chorus* chorus;
|
||||
|
||||
uint32_t sampleRate;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
State Variable Filter
|
||||
|
||||
Copyright 2025 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "svf.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
SVF::SVF(float cutoff, float Q) {
|
||||
// zero out all values
|
||||
z1 = 0;
|
||||
z2 = 0;
|
||||
setCutoff(cutoff, Q);
|
||||
}
|
||||
|
||||
void SVF::setCutoff(float cutoff, float Q) {
|
||||
float F = cutoff / sampleRate;
|
||||
float w = 2 * tan(3.14159 * F);
|
||||
float a = w / Q;
|
||||
float b = w * w;
|
||||
|
||||
// "corrected" SVF params, per Fons Adriaensen
|
||||
c1 = (a + b) / (1 + a / 2 + b / 4);
|
||||
c2 = b / (a + b);
|
||||
d0 = c1 * c2 / 4;
|
||||
}
|
||||
|
||||
void SVF::runSVF(const float *input, float *output, uint32_t frames) {
|
||||
float x;
|
||||
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
// lowpass filter
|
||||
x = input[i] - z1 - z2;
|
||||
z2 += c2 * z1;
|
||||
z1 += c1 * x;
|
||||
output[i] = d0 * x + z2;
|
||||
}
|
||||
// printf("%f\n", x);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
State Variable Filter
|
||||
|
||||
Copyright 2025 Gordon JC Pearce <gordonjcp@gjcp.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SVF_HPP
|
||||
#define SVF_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern double sampleRate;
|
||||
|
||||
class SVF {
|
||||
public:
|
||||
SVF(float cutoff=1000, float Q=0.707);
|
||||
void setCutoff(float cutoff, float Q);
|
||||
|
||||
void runSVF(const float *input, float *output, uint32_t frames);
|
||||
|
||||
protected:
|
||||
private:
|
||||
float c1, c2, d0;
|
||||
float z1, z2;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue