integer envelope

This commit is contained in:
Gordon JC Pearce 2025-12-19 12:21:44 +00:00
parent 9b4f3a1be0
commit 05ece71acd
3 changed files with 19 additions and 10 deletions

View File

@ -26,6 +26,11 @@ 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
a = attackTable[patchRam.env_a]; // attack 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
s = patchRam.env_s << 7; // scale 0x00-0x7f to 0x0000-0x3f80
// 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);
@ -34,18 +39,17 @@ void Module::run(Voice* voice) {
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
voice[i].env *= decayTable[patchRam.env_r] / 65536.0f; // "RC" decay to zero voice[i].env = (voice[i].env * d) >> 16; // "RC" decay to zero
break; break;
case 1: // attack phase case 1: // attack phase
voice[i].env += attackTable[patchRam.env_a] / 65536.0f; // linear attack to 1 voice[i].env += a; // linear attack to 0x3fff
break; break;
case 2: case 2:
float t = patchRam.env_s / 127.0f; voice[i].env = (((voice[i].env - s) * d) >>16 ) + s;
voice[i].env = (voice[i].env - t) * (decayTable[patchRam.env_d] / 65536.0f) + t;
break; break;
} }
if (voice[i].env > 1.0f) { if (voice[i].env > 0x3fff) {
voice[i].env = 1.0f; voice[i].env = 0x3fff;
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

View File

@ -37,6 +37,9 @@ class Module {
// 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
uint16_t a, d, s, r;
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;
@ -66,7 +69,7 @@ class Voice {
void off(); void off();
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;
float env = 0; // output amplitude int16_t env = 0; // output amplitude
private: private:
float omega = 0, theta = 0; // phase increment and angle float omega = 0, theta = 0; // phase increment and angle
@ -78,4 +81,4 @@ class Voice {
float b1 = 0, b2 = 0, b3 = 0, b4 = 0; float b1 = 0, b2 = 0, b3 = 0, b4 = 0;
}; };
#endif #endif

View File

@ -51,13 +51,15 @@ 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.075*env; float cut = 0.00513 + 0.0000075*env;
// printf("%f ", delay); // printf("%f ", delay);
m->saw = 1; m->saw = 1;
m->square = 1; m->square = 1;
m->sub = .5; m->sub = .5;
m->pw = 0.5; m->pw = 0.5;
float amp = env / 4096.0f;
for (uint32_t i = 0; i < samples; i++) { for (uint32_t i = 0; i < samples; i++) {
out = delay; out = delay;
delay = 0; delay = 0;
@ -106,7 +108,7 @@ void Voice::run(Module* m, float* buffer, uint32_t samples) {
b4 = ((b3 - b4) * cut) + b4; b4 = ((b3 - b4) * cut) + b4;
} }
buffer[i] += 0.125 * env * b4; buffer[i] += 0.125 * amp * b4;
lastpw = m->pw; lastpw = m->pw;
} }
// buffer[0] += 1; // buffer[0] += 1;