adjustable filter envelope and vca gate
This commit is contained in:
parent
05ece71acd
commit
6a00521656
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#include "module.hpp"
|
#include "module.hpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
Module::Module() {
|
Module::Module() {
|
||||||
|
|
@ -26,16 +28,26 @@ Module::Module() {
|
||||||
void Module::run(Voice* voice) {
|
void Module::run(Voice* voice) {
|
||||||
// run updates for module board
|
// run updates for module board
|
||||||
|
|
||||||
// FIXME break these out to the patch setter
|
// FIXME break these out to the patch setter
|
||||||
a = attackTable[patchRam.env_a]; // attack time coeff looked up in table
|
a = attackTable[patchRam.env_a]; // attack time coeff looked up in table
|
||||||
d = decayTable[patchRam.env_d]; // decay time coeff looked up in table
|
d = decayTable[patchRam.env_d]; // decay time coeff looked up in table
|
||||||
r = decayTable[patchRam.env_r]; // release time coeff looked up in table
|
r = decayTable[patchRam.env_r]; // release time coeff looked up in table
|
||||||
s = patchRam.env_s << 7; // scale 0x00-0x7f to 0x0000-0x3f80
|
s = patchRam.env_s << 7; // scale 0x00-0x7f to 0x0000-0x3f80
|
||||||
|
|
||||||
|
square = (patchRam.switch2 & 0x08) ? 0.63 : 0;
|
||||||
|
saw = (patchRam.switch2 & 0x10) ? 0.8 : 0;
|
||||||
|
sub = patchRam.sub / 127.0f;
|
||||||
|
|
||||||
|
// printf("%f %f %f %02x\n", square, saw, sub, patchRam.switch2);
|
||||||
|
|
||||||
// work out the "master" cutoff
|
// work out the "master" cutoff
|
||||||
vcfCutoff = patchRam.vcfFreq / 127.0f;
|
// vcfCutoff = patchRam.vcfFreq / 127.0f;
|
||||||
vcfCutoff += lfo * (patchRam.vcfLfo/127.0f);
|
// vcfCutoff += lfo * (patchRam.vcfLfo / 127.0f);
|
||||||
// also needs pitch bend amount for the base level
|
// also needs pitch bend amount for the base level
|
||||||
|
|
||||||
|
int16_t vcf = (patchRam.vcfEnv << 7) * ((patchRam.switch2 & 0x02) ? -1 : 1);
|
||||||
|
// int16_t vca = (patchRam.vcfEnv << 7) * (patchRam.switch2 & 0x01) ? -1 : 1;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < NUM_VOICES; i++) {
|
for (uint32_t i = 0; i < NUM_VOICES; i++) {
|
||||||
switch (voice[i].envPhase) {
|
switch (voice[i].envPhase) {
|
||||||
case 0: // release phase FIXME use an enum I guess
|
case 0: // release phase FIXME use an enum I guess
|
||||||
|
|
@ -45,7 +57,7 @@ void Module::run(Voice* voice) {
|
||||||
voice[i].env += a; // linear attack to 0x3fff
|
voice[i].env += a; // linear attack to 0x3fff
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
voice[i].env = (((voice[i].env - s) * d) >>16 ) + s;
|
voice[i].env = (((voice[i].env - s) * d) >> 16) + s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (voice[i].env > 0x3fff) {
|
if (voice[i].env > 0x3fff) {
|
||||||
|
|
@ -53,5 +65,13 @@ void Module::run(Voice* voice) {
|
||||||
voice[i].envPhase = 2; // flip to decay
|
voice[i].envPhase = 2; // flip to decay
|
||||||
}
|
}
|
||||||
// per voice we need to calculate the key follow amount and envelope amount
|
// per voice we need to calculate the key follow amount and envelope amount
|
||||||
|
voice[i].vcfCut = (patchRam.vcfFreq << 7) + ((vcf * voice[i].env) >> 16);
|
||||||
|
|
||||||
|
if (voice[i].vcfCut > 0x3fff) voice[i].vcfCut = 0x3fff;
|
||||||
|
if (voice[i].vcfCut < 0) voice[i].vcfCut = 0;
|
||||||
|
|
||||||
|
|
||||||
|
voice[i].vcaEnv = (patchRam.switch2 & 0x04) ? (voice[i].envPhase ? 0x3fff : 0) : voice[i].env;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,31 +35,37 @@ class Module {
|
||||||
float lfo = 0, lfoTheta = 0;
|
float lfo = 0, lfoTheta = 0;
|
||||||
|
|
||||||
// precomputed values for all voices
|
// precomputed values for all voices
|
||||||
float pw, saw, square, sub;
|
float pw;//, saw, square, sub;
|
||||||
|
|
||||||
// "internal state" values for patch parameters
|
// "internal state" values for patch parameters
|
||||||
uint16_t a, d, s, r;
|
uint16_t a, d, s, r;
|
||||||
|
|
||||||
|
float saw = 0, square = 0, sub = 0, noise = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t lfoRate = 0x30; // lookup value defaults to 0x0200
|
uint8_t lfoRate = 0x30; // lookup value defaults to 0x0200
|
||||||
uint8_t lfoDelay = 0x00;
|
uint8_t lfoDelay = 0x00;
|
||||||
uint8_t vcoLfo = 0x0a;
|
uint8_t vcoLfo = 0x0a;
|
||||||
uint8_t pwmLfo = 0x30;
|
uint8_t pwmLfo = 0x30;
|
||||||
uint8_t noise = 0x00;
|
uint8_t noise = 0x00;
|
||||||
uint8_t vcfFreq = 0x3c; // 0x3f80
|
uint8_t vcfFreq = 0x4c; // 0x3f80
|
||||||
uint8_t vcfReso = 0x00;
|
uint8_t vcfReso = 0x00;
|
||||||
uint8_t vcfEnv = 0x2e;
|
uint8_t vcfEnv = 0x4e;
|
||||||
uint8_t vcfLfo = 0;
|
uint8_t vcfLfo = 0;
|
||||||
uint8_t vcfKey = 0x47;
|
uint8_t vcfKey = 0x47;
|
||||||
uint8_t vca = 0x28;
|
uint8_t vca = 0x28;
|
||||||
uint8_t env_a = 0x1b;
|
uint8_t env_a = 0x00;
|
||||||
uint8_t env_d = 0x39;
|
uint8_t env_d = 0x39;
|
||||||
uint8_t env_s = 0x39; // 0x3f80
|
uint8_t env_s = 0x39; // 0x3f80
|
||||||
uint8_t env_r = 0x30;
|
uint8_t env_r = 0x30;
|
||||||
uint8_t sub = 0x00;
|
uint8_t sub = 0x7f;
|
||||||
uint8_t switch1 = 0x1a;
|
uint8_t switch1 = 0x1a;
|
||||||
uint8_t switch2 = 0x18;
|
uint8_t switch2 = 0x18;
|
||||||
} patchRam;
|
} patchRam;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// controls
|
||||||
|
float subRC = 0, outRC = 0, pwmRC = 0, resRC = 0, noiseRC = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Voice {
|
class Voice {
|
||||||
|
|
@ -70,9 +76,14 @@ class Voice {
|
||||||
void run(Module* m, float* buffer, uint32_t samples);
|
void run(Module* m, float* buffer, uint32_t samples);
|
||||||
uint8_t envPhase = 0;
|
uint8_t envPhase = 0;
|
||||||
int16_t env = 0; // output amplitude
|
int16_t env = 0; // output amplitude
|
||||||
|
int16_t vcfCut;
|
||||||
|
int16_t vcaEnv;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float omega = 0, theta = 0; // phase increment and angle
|
// control
|
||||||
|
float vcaRC = 0, vcfRC = 0;
|
||||||
|
|
||||||
|
float omega = 0, theta = 0; // phase increment and angle FIXME better names
|
||||||
float delay = 0, lastpw = 0; // delay slots for antialiasing
|
float delay = 0, lastpw = 0; // delay slots for antialiasing
|
||||||
uint8_t pulseStage = 1; // pulse wave phase
|
uint8_t pulseStage = 1; // pulse wave phase
|
||||||
float subosc = 1; // sub oscillator flipflop output
|
float subosc = 1; // sub oscillator flipflop output
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,17 @@ void Voice::run(Module* m, float* buffer, uint32_t samples) {
|
||||||
// carry out per-voice calculations for each block of samples
|
// carry out per-voice calculations for each block of samples
|
||||||
float out, t, fb, res;
|
float out, t, fb, res;
|
||||||
|
|
||||||
float cut = 0.00513 + 0.0000075*env;
|
//float cut = 0.00513 + 0.0000075*env;
|
||||||
|
|
||||||
|
// calculate cutoff frequency
|
||||||
|
float cut = 248.0f * (powf(2, (vcfCut - 0x1880) / 1143.0f));
|
||||||
|
cut = 0.25 * 6.2832 * cut / 48000.0f; // FIXME hardcoded values
|
||||||
|
cut = cut/(1+cut); // correct tuning warp
|
||||||
|
|
||||||
// printf("%f ", delay);
|
// printf("%f ", delay);
|
||||||
m->saw = 1;
|
|
||||||
m->square = 1;
|
|
||||||
m->sub = .5;
|
|
||||||
m->pw = 0.5;
|
m->pw = 0.5;
|
||||||
|
|
||||||
float amp = env / 4096.0f;
|
float amp = vcaEnv / 4096.0f;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < samples; i++) {
|
for (uint32_t i = 0; i < samples; i++) {
|
||||||
out = delay;
|
out = delay;
|
||||||
|
|
@ -101,14 +104,14 @@ void Voice::run(Module* m, float* buffer, uint32_t samples) {
|
||||||
if (fb > 1) fb = 1;
|
if (fb > 1) fb = 1;
|
||||||
if (fb < -1) fb = -1;
|
if (fb < -1) fb = -1;
|
||||||
|
|
||||||
fb = out - (fb * 2);
|
fb = out - (fb * 1.7);
|
||||||
b1 = ((fb - b1) * cut) + b1;
|
b1 = ((fb - b1) * cut) + b1;
|
||||||
b2 = ((b1 - b2) * cut) + b2;
|
b2 = ((b1 - b2) * cut) + b2;
|
||||||
b3 = ((b2 - b3) * cut) + b3;
|
b3 = ((b2 - b3) * cut) + b3;
|
||||||
b4 = ((b3 - b4) * cut) + b4;
|
b4 = ((b3 - b4) * cut) + b4;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[i] += 0.125 * amp * b4;
|
buffer[i] += 0.0625 * amp * b4;
|
||||||
lastpw = m->pw;
|
lastpw = m->pw;
|
||||||
}
|
}
|
||||||
// buffer[0] += 1;
|
// buffer[0] += 1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue