143 lines
4.2 KiB
C++
143 lines
4.2 KiB
C++
/*
|
|
Chassis polysynth framework
|
|
|
|
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.
|
|
*/
|
|
|
|
#pragma once
|
|
#include <cstdint>
|
|
|
|
// uint16_t attack_table[128];
|
|
// uint16_t decay_table[128];
|
|
|
|
class Synth;
|
|
|
|
class Voice {
|
|
public:
|
|
uint8_t note = 60; // per-voice note, set to middle C at 02b1h
|
|
|
|
void on(uint32_t key, bool reset);
|
|
void off();
|
|
bool isFree();
|
|
void run(Synth &s, float *buffer, uint32_t samples);
|
|
void envelope(Synth &s);
|
|
void calcPitch(Synth &s);
|
|
void calcFilter(Synth &s);
|
|
|
|
uint16_t ff71 = 0; // stores pitch + fraction
|
|
|
|
float omega;
|
|
uint16_t vcfenv;
|
|
|
|
private:
|
|
enum { ATTACK,
|
|
DECAY,
|
|
SUSTAIN,
|
|
RELEASE } envState = RELEASE;
|
|
enum { K_OFF,
|
|
K_WAIT,
|
|
K_ON,
|
|
K_SUSTAIN } keyState = K_OFF;
|
|
|
|
bool ff00 = 0; // reset DCO clock flag
|
|
bool ff07 = 0; // set to indicate attack phase
|
|
bool ff08 = 0; // set to indicate decay/sustain phase
|
|
bool ff10 = 0; // note on bit
|
|
bool ff11 = 0; // drives the "gate" signal for VCA
|
|
uint16_t ff27 = 0; // envelope for voice
|
|
bool ff33 = 0; // releasing flag
|
|
|
|
uint16_t env;
|
|
|
|
float phase = 0, subosc = 1;
|
|
// float env, target;
|
|
float delay;
|
|
uint8_t pulseStage = 0;
|
|
|
|
float lastpw = 0;
|
|
float vr58c106 = 0;
|
|
|
|
float b1, b2, b3, b4;
|
|
};
|
|
class Synth {
|
|
public:
|
|
Voice voice[8];
|
|
float lfo = 0, lfosw = 0.01;
|
|
float lastpw = 0;
|
|
uint32_t blockLeft;
|
|
uint32_t framesLeft = 0;
|
|
|
|
uint8_t polymode;
|
|
|
|
bool keyon;
|
|
uint8_t ff63 = 0;
|
|
|
|
// RAM from ff00h to ffffh is cleared to zero
|
|
// this is in the startup routine at 0280h
|
|
uint8_t ff1e = 0;
|
|
uint8_t ff34 = 0;
|
|
uint8_t ff4a = 0; // LFO flags
|
|
uint16_t ff4d = 0; // LFO output value
|
|
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
|
|
uint16_t ff65 = 0; // computed VCF bend amount
|
|
uint8_t ff6a = 0;
|
|
uint8_t ff6b = 0;
|
|
uint8_t ff6e = 0; // fractional pitch temp
|
|
uint16_t ff6f = 0; // computed pitch amount
|
|
// uint16_t ff71 = 0; // unsure, to do with pitch
|
|
|
|
// 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
|
|
|
|
// 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
|
|
struct {
|
|
uint8_t lfoRate = 0x30; // lookup value defaults to 0x0200
|
|
uint8_t lfoDelay = 0x00;
|
|
uint8_t vcoLfo = 0x0a;
|
|
uint8_t pwmLfo = 0x30;
|
|
uint8_t noise = 0x00;
|
|
uint8_t vcfFreq = 0x3c; // 0x3f80
|
|
uint8_t vcfReso = 0x00;
|
|
uint8_t vcfEnv = 0x2e;
|
|
uint8_t vcfLfo = 0;
|
|
uint8_t vcfKey = 0x47;
|
|
uint8_t vca = 0x28;
|
|
uint8_t env_a = 0x1b;
|
|
uint8_t env_d = 0x39;
|
|
uint8_t env_s = 0x39; // 0x3f80
|
|
uint8_t env_r = 0x30;
|
|
uint8_t sub = 0x00;
|
|
uint8_t switch1 = 0x1a;
|
|
uint8_t switch2 = 0x18;
|
|
} patchRam;
|
|
|
|
float pitchCV[104];
|
|
float hptmp;
|
|
|
|
void runLFO();
|
|
void lfoDelay();
|
|
};
|