2024-09-03 11:42:16 +00:00
|
|
|
/*
|
2024-09-03 15:17:32 +00:00
|
|
|
Chassis polysynth framework
|
2024-09-03 11:42:16 +00:00
|
|
|
|
|
|
|
Copyright 2024 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.
|
|
|
|
*/
|
|
|
|
|
2024-09-08 19:48:10 +00:00
|
|
|
#pragma once
|
2024-09-03 11:42:16 +00:00
|
|
|
#include <cstdint>
|
|
|
|
|
2024-09-08 19:48:10 +00:00
|
|
|
// uint16_t attack_table[128];
|
|
|
|
// uint16_t decay_table[128];
|
2024-09-08 00:08:00 +00:00
|
|
|
|
2024-09-03 22:41:01 +00:00
|
|
|
class Synth;
|
|
|
|
|
2024-09-03 11:42:16 +00:00
|
|
|
class Voice {
|
|
|
|
public:
|
2024-09-09 10:34:13 +00:00
|
|
|
uint8_t note = 60; // per-voice note, set to middle C at 02b1h
|
2024-09-03 12:50:46 +00:00
|
|
|
|
2024-09-03 14:22:56 +00:00
|
|
|
void on(uint32_t key, bool reset);
|
|
|
|
void off();
|
2024-09-03 14:31:54 +00:00
|
|
|
bool isFree();
|
2024-09-03 22:41:01 +00:00
|
|
|
void run(Synth &s, float *buffer, uint32_t samples);
|
2024-09-09 19:40:16 +00:00
|
|
|
void envelope(Synth &s);
|
2024-09-09 12:34:02 +00:00
|
|
|
void calcPitch(Synth &s);
|
2024-09-09 15:31:43 +00:00
|
|
|
|
2024-09-09 13:05:43 +00:00
|
|
|
uint16_t ff71 = 0; // stores pitch + fraction
|
2024-09-09 12:34:02 +00:00
|
|
|
|
|
|
|
float omega;
|
2024-09-05 22:18:41 +00:00
|
|
|
|
2024-09-03 12:50:46 +00:00
|
|
|
private:
|
|
|
|
enum { ATTACK,
|
|
|
|
DECAY,
|
|
|
|
SUSTAIN,
|
|
|
|
RELEASE } envState = RELEASE;
|
|
|
|
enum { K_OFF,
|
2024-09-05 22:18:41 +00:00
|
|
|
K_WAIT,
|
2024-09-03 12:50:46 +00:00
|
|
|
K_ON,
|
|
|
|
K_SUSTAIN } keyState = K_OFF;
|
2024-09-05 22:18:41 +00:00
|
|
|
|
2024-09-08 23:55:14 +00:00
|
|
|
bool ff00 = 0; // reset DCO clock flag
|
|
|
|
bool ff07 = 0; // set to indicate attack phase
|
|
|
|
bool ff08 = 0; // set to indicate decay/sustain phase
|
2024-09-08 19:48:10 +00:00
|
|
|
bool ff10 = 0; // note on bit
|
2024-09-08 23:55:14 +00:00
|
|
|
bool ff11 = 0; // drives the "gate" signal for VCA
|
2024-09-08 19:48:10 +00:00
|
|
|
bool ff33 = 0; // releasing flag
|
2024-09-08 00:08:00 +00:00
|
|
|
|
|
|
|
uint16_t env;
|
|
|
|
|
2024-09-09 12:34:02 +00:00
|
|
|
float phase = 0, subosc = 1;
|
2024-09-08 00:08:00 +00:00
|
|
|
// float env, target;
|
2024-09-06 20:44:41 +00:00
|
|
|
float delay;
|
2024-09-08 00:08:00 +00:00
|
|
|
uint8_t pulseStage = 0;
|
2024-09-04 20:08:27 +00:00
|
|
|
|
2024-09-08 23:55:14 +00:00
|
|
|
float lastpw = 0;
|
2024-09-07 19:46:57 +00:00
|
|
|
float vr58c106 = 0;
|
2024-09-09 15:31:43 +00:00
|
|
|
|
|
|
|
float b1, b2, b3, b4;
|
2024-09-03 11:42:16 +00:00
|
|
|
};
|
2024-09-03 22:30:08 +00:00
|
|
|
class Synth {
|
2024-09-04 20:08:27 +00:00
|
|
|
public:
|
|
|
|
Voice voice[8];
|
|
|
|
float lfo = 0, lfosw = 0.01;
|
|
|
|
float lastpw = 0;
|
2024-09-05 09:01:22 +00:00
|
|
|
uint32_t blockLeft;
|
|
|
|
uint32_t framesLeft = 0;
|
2024-09-08 00:08:00 +00:00
|
|
|
|
2024-09-09 10:34:13 +00:00
|
|
|
bool keyon;
|
2024-09-09 13:05:43 +00:00
|
|
|
uint8_t ff63 = 0;
|
2024-09-09 10:34:13 +00:00
|
|
|
|
|
|
|
// RAM from ff00h to ffffh is cleared to zero
|
|
|
|
// this is in the startup routine at 0280h
|
|
|
|
uint8_t ff1e = 0;
|
2024-09-09 12:34:02 +00:00
|
|
|
uint8_t ff34 = 0;
|
2024-09-09 10:34:13 +00:00
|
|
|
uint8_t ff4a = 0; // LFO flags
|
2024-09-08 23:55:14 +00:00
|
|
|
uint16_t ff4d = 0; // LFO output value
|
2024-09-09 10:34:13 +00:00
|
|
|
uint16_t ff4f = 0; // computed PWM LFO
|
|
|
|
uint16_t ff51 = 0; // computed pitch LFO
|
|
|
|
uint16_t ff53 = 0; // computed VCF LFO
|
|
|
|
uint16_t ff56 = 0; // LFO Delay envelope
|
|
|
|
uint16_t ff5a = 0; // LFO Delay holdoff
|
|
|
|
uint8_t ff64 = 0; // LFO mod sens amount
|
2024-09-09 13:05:43 +00:00
|
|
|
uint8_t ff6e = 0; // fractional pitch temp
|
2024-09-09 12:34:02 +00:00
|
|
|
uint16_t ff6f = 0; // computed pitch amount
|
2024-09-09 13:05:43 +00:00
|
|
|
// uint16_t ff71 = 0; // unsure, to do with pitch
|
2024-09-08 23:55:14 +00:00
|
|
|
|
2024-09-08 19:48:10 +00:00
|
|
|
// okay, not the greatest, this right here
|
|
|
|
// this struct contains the bytes that make up a Juno 106 patch in
|
|
|
|
// sysex order, exactly as they'd be transmitted or received by a
|
|
|
|
// real one.
|
|
|
|
// the horrifying implication here is that we can just shunt this
|
|
|
|
// around and memcpy() values from sysex on top of it
|
|
|
|
|
2024-09-09 10:34:13 +00:00
|
|
|
// this is set to a "sensible" patch
|
|
|
|
// the comments indicate what the defaults are set to
|
|
|
|
// in the routine at 02c2h, in case they're important
|
2024-09-08 19:48:10 +00:00
|
|
|
struct {
|
2024-09-09 10:34:13 +00:00
|
|
|
uint8_t lfoRate = 57; // lookup value defaults to 0x0200
|
2024-09-08 20:50:42 +00:00
|
|
|
uint8_t lfoDelay = 45;
|
|
|
|
uint8_t vcoLfo = 0;
|
|
|
|
uint8_t pwmLfo = 55;
|
2024-09-08 19:48:10 +00:00
|
|
|
uint8_t noise = 0;
|
2024-09-09 10:34:13 +00:00
|
|
|
uint8_t vcfFreq = 85; // 0x3f80
|
2024-09-08 21:21:03 +00:00
|
|
|
uint8_t vcfReso = 0;
|
2024-09-08 20:50:42 +00:00
|
|
|
uint8_t vcfEnv = 0;
|
|
|
|
uint8_t vcfLfo = 0;
|
|
|
|
uint8_t vcfKey = 108;
|
2024-09-08 19:48:10 +00:00
|
|
|
uint8_t vca = 52;
|
|
|
|
uint8_t env_a = 59;
|
|
|
|
uint8_t env_d = 32;
|
2024-09-09 10:34:13 +00:00
|
|
|
uint8_t env_s = 86; // 0x3f80
|
2024-09-08 19:48:10 +00:00
|
|
|
uint8_t env_r = 40;
|
|
|
|
uint8_t sub = 0;
|
|
|
|
uint8_t switch1 = 26;
|
|
|
|
uint8_t switch2 = 24;
|
|
|
|
} patchRam;
|
|
|
|
|
2024-09-09 10:34:13 +00:00
|
|
|
|
2024-09-09 12:34:02 +00:00
|
|
|
float pitchCV[104];
|
|
|
|
|
2024-09-08 23:55:14 +00:00
|
|
|
void runLFO();
|
2024-09-09 10:34:13 +00:00
|
|
|
void lfoDelay();
|
2024-09-08 23:55:14 +00:00
|
|
|
};
|