LFO delay, basically feature-complete

This commit is contained in:
Gordon JC Pearce 2025-12-24 01:46:37 +00:00
parent d6e5f21e5b
commit 13ff93a0a5
5 changed files with 36 additions and 30 deletions

View File

@ -110,6 +110,10 @@ void Assigner::noteOn(uint8_t note) {
return;
}
if ((noteTbl[voiceTbl[0]] & 0x80)) {
m->lfoRampOn();
}
// loop around the voices
for (i = NUM_VOICES - 1; i >= 0; i--) {
v = voiceTbl[i];
@ -137,6 +141,6 @@ void Assigner::noteOn(uint8_t note) {
// printf("at end, l=%d e=%d\n", l,e);
noteTbl[v] = note;
d_debug("send voice on %3d to voice %d", note, v);
d_debug("send voice on %3d to voice %d", note, i);
voice[v].on(note);
}

View File

@ -27,6 +27,7 @@ class Assigner {
Assigner();
void handleMidi(MidiEvent* ev);
Voice* voice;
Module *m;
private:
void noteOn(uint8_t note); // incoming note on (or off, if velocity = 0)

View File

@ -40,9 +40,29 @@ Module::~Module() {
delete subBuf;
delete pwmBuf;
}
void Module::lfoRampOn() {
lfoDelayState = 1;
lfoDelayTimer = 0;
lfoDelay = 0;
}
void Module::run(Voice* voices, uint32_t blockSize) {
// run updates for module board
if (lfoDelayState == 1) {
lfoDelayTimer += lfoDelayTable[patchRam.lfoDelay >> 4];
if (lfoDelayTimer & 0xc000) lfoDelayState = 2;
}
if ((lfoDelayState == 2)) {
lfoDelay += attackTable[patchRam.lfoDelay];
}
if (lfoDelay & 0xc000) {
lfoDelayState = 0;
lfoDelay = 0x3fff;
}
// 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
@ -70,9 +90,10 @@ void Module::run(Voice* voices, uint32_t blockSize) {
pw = 0.5 - ((0x2000 + lfo) * patchRam.pwmLfo) / (32768.0f * 128);
pw = (patchRam.switch2 & 0x01) ? 0.5 - (patchRam.pwmLfo / 256.0f) : pw;
lfo = (lfo * lfoDelay) >> 14;
float master = powf(2, (patchRam.vca / 31.75 - 4.0f));
float sub = patchRam.sub/ 127.0f;
float sub = patchRam.sub / 127.0f;
for (uint32_t i = 0; i < blockSize; i++) {
vcaRC = (master - vcaRC) * subTC + vcaRC;
@ -83,7 +104,6 @@ void Module::run(Voice* voices, uint32_t blockSize) {
pwmBuf[i] = pwmRC;
subBuf[i] = subRC;
if (bufPtr < bufferSize) bufPtr++;
}
@ -128,7 +148,7 @@ void Module::run(Voice* voices, uint32_t blockSize) {
v->vcfCut = (patchRam.vcfFreq << 7) + ((vcf * v->env) >> 14);
v->vcfCut += (lfo * patchRam.vcfLfo) >> 9;
v->vcfCut += (int)((v->note-36) * (patchRam.vcfKey << 1) * 0.375);
v->vcfCut += (int)((v->note - 36) * (patchRam.vcfKey << 1) * 0.375);
if (v->vcfCut > 0x3fff) v->vcfCut = 0x3fff;
if (v->vcfCut < 0) v->vcfCut = 0;

View File

@ -33,6 +33,8 @@ class Module {
Module();
~Module();
void lfoRampOn();
void run(Voice* voices, uint32_t blockLeft);
float res = 0;
@ -47,7 +49,6 @@ class Module {
float saw = 0, square = 0, sub = 0, noise = 0;
struct {
uint8_t lfoRate = 0x58;
uint8_t lfoDelay = 0x00;
uint8_t vcoLfo = 0x00;
@ -66,29 +67,6 @@ class Module {
uint8_t sub = 0x7f;
uint8_t switch1 = 0x4a;
uint8_t switch2 = 0x18;
/*
// VCF tune
uint8_t lfoRate = 0x40;
uint8_t lfoDelay = 0x00;
uint8_t vcoLfo = 0x00;
uint8_t pwmLfo = 0x00;
uint8_t noise = 0x00;
uint8_t vcfFreq = 0x31; // 1c; // 0x3f80
uint8_t vcfReso = 0x7f;
uint8_t vcfEnv = 0x00; // 4e;
uint8_t vcfLfo = 0x00;
uint8_t vcfKey = 0x7f; // 47;
uint8_t vca = 0x40;
uint8_t env_a = 0x00;
uint8_t env_d = 0x00;
uint8_t env_s = 0x7f; // 0x3f80
uint8_t env_r = 0x00;
uint8_t sub = 0x00;
uint8_t switch1 = 0x62;
uint8_t switch2 = 0x10;
*/
} patchRam;
Chorus* chorus;
@ -104,7 +82,9 @@ class Module {
float pwmTC = 0, subTC = 0, mVcaTC = 0;
float pwmRC = 0, subRC = 0, vcaRC = 0;
// controls
uint16_t lfoDelay = 0;
uint8_t lfoDelayState = 0;
uint16_t lfoDelayTimer = 0;
};
class Voice {

View File

@ -32,6 +32,7 @@ Peacock::Peacock() : Plugin(parameterCount, 0, 0) {
m = new Module();
ic1 = new Assigner;
ic1->voice = voice;
ic1->m = m;
m->chorus = chorus;
}