Compare commits

...

6 Commits

Author SHA1 Message Date
Gordon JC Pearce
1c8f451c3a removed a lot of debugging printfs 2024-09-11 23:30:06 +01:00
Gordon JC Pearce
3980a1c966 correct parameter generation 2024-09-11 23:25:41 +01:00
Gordon JC Pearce
620914b500 saneish looking parameters 2024-09-11 21:40:11 +01:00
Gordon JC Pearce
3588c3459b fix labelling 2024-09-11 20:04:34 +01:00
Gordon JC Pearce
561acbc0fb fix uninitialised variable 2024-09-11 19:57:11 +01:00
Gordon JC Pearce
788b94993a basic patch support 2024-09-10 14:57:56 +01:00
8 changed files with 348 additions and 96 deletions

View File

@ -27,7 +27,7 @@
#define DISTRHO_PLUGIN_IS_SYNTH 1
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1
enum Parameters {
paramProg,

View File

@ -18,9 +18,11 @@
#include "chassis.hpp"
#include "patches.hpp"
START_NAMESPACE_DISTRHO
Chassis::Chassis() : Plugin(parameterCount, 0, 0), sampleRate(getSampleRate()) { // one parameter, no programs, no states
Chassis::Chassis() : Plugin(parameterCount, 128, 0), sampleRate(getSampleRate()) { // one parameter, no programs, no states
}
// Initialisation functions
@ -33,6 +35,14 @@ void Chassis::initAudioPort(bool input, uint32_t index, AudioPort &port) {
if (!input && index == 1) port.name = "Right Out";
}
void Chassis::initProgramName(uint32_t index, String &programName) {
programName = patchName[index & 0x7f].c_str();
}
void Chassis::loadProgram(uint32_t index) {
memmove(&s.patchRam, (uint8_t *)patchData + (index * 18), 18);
}
// Processing functions
void Chassis::activate() {
@ -47,7 +57,6 @@ void Chassis::activate() {
void Chassis::deactivate() {
// zero out the outputs, maybe
printf("called deactivate()\n");
// printf("%02x", assign[1]);
}
void Chassis::noteOn(uint8_t note) {
@ -57,10 +66,8 @@ void Chassis::noteOn(uint8_t note) {
vPtr++;
if (vPtr == NUM_VOICES) vPtr = 0;
if (s.voice[vPtr].isFree()) {
// printf("voice %d is free, existing note = %d, note = %d\n", vPtr, s.voice[i].note, note);
// if it's an existing note don't reset
s.voice[vPtr].on(note, s.voice[i].note != note);
// printf("note on %d for voice %d\n", note, vPtr);
break;
}
}
@ -73,23 +80,19 @@ void Chassis::noteOn(uint8_t note) {
}
void Chassis::noteOff(uint8_t note) {
// printf("noteoff %d\n", note);
s.keyon = false;
for (uint32_t i = 0; i < NUM_VOICES; i++) {
if (s.voice[i].note == note && !s.voice[i].isFree()) {
s.voice[i].off();
// printf("note off %d for voice %d\n", note, i);
break;
}
}
}
void Chassis::doMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
// printf("doMidi() handling events from %d to %d\n", lastEvent, timeLimit);
uint32_t i;
if (count == 0) return;
for (i = lastEvent; i < count; i++) {
// printf("doMidi event number %d of %d %02x %02x\n", i, count, ev[i].data[0], ev[i].data[1]);
if (ev[i].frame > timeLimit) break;
switch (ev[i].data[0]) {
case 0x90:
@ -104,20 +107,15 @@ void Chassis::doMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
}
void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {
// if (midiEventCount > 0) printf("\n--------------------\n");
uint32_t framePos = 0;
uint32_t sizeThisTime;
s.framesLeft = frames;
// printf("\n------------\ncalled run() for %d frames\n",frames);
// flatten the left channel to use as temporary storage, since
// the synth engine only generates a mono channel
bzero(outputs[0], sizeof(float) * frames);
bzero(outputs[1], sizeof(float) * frames);
// get any of the last block's worth of MIDI out of the way
lastEvent = 0;
doMidi(midiEvents, midiEventCount, s.blockLeft);
@ -127,7 +125,6 @@ void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEv
s.blockLeft = sampleRate / 238;
doMidi(midiEvents, midiEventCount, framePos + s.blockLeft);
// printf("compute params and reset block size\n");
s.lfoDelay();
s.runLFO();
@ -135,38 +132,32 @@ void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEv
s.voice[i].calcPitch(s);
switch (s.patchRam.switch1 & 0x07) {
case 1:
case 0:
s.voice[i].omega /= 2;
break;
case 4:
case 2:
s.voice[i].omega *= 2;
default:
break;
}
// printf("voice %d note = %02x ff71 = %04x\n",i, s.voice[i].note, s.voice[i].ff71 );
s.voice[i].envelope(s);
s.voice[i].calcFilter(s);
//printf("voice %d vcf level = %04x\n", i, s.voice[i].vcfenv );
}
}
sizeThisTime = (s.framesLeft < s.blockLeft) ? s.framesLeft : s.blockLeft;
// printf("sL = %d bL = %d, calculating %d frames at %d\n", s.framesLeft, s.blockLeft, sizeThisTime, framePos);
// run each synth voice
for (uint8_t i = 0; i < NUM_VOICES; i++) {
s.voice[i].run(s, outputs[0] + framePos, sizeThisTime);
}
framePos += sizeThisTime;
s.framesLeft -= sizeThisTime;
s.blockLeft -= sizeThisTime;
}
// printf("and now run the rest of the process for %d frames\n\n", frames);
// copy left to right
memmove(outputs[1], outputs[0], sizeof(float) * frames);

View File

@ -71,12 +71,12 @@ class Chassis : public Plugin {
protected:
const char *getLabel() const override { return "chassis"; }
const char *getDescription() const override {
return "MIDIVerb emulation, a tribute to Keith Barr";
return "simple polysynth";
}
const char *getMaker() const override { return "Gordonjcp"; }
const char *getLicense() const override { return "ISC"; }
uint32_t getVersion() const override { return d_version(1, 0, 0); }
int64_t getUniqueId() const override { return d_cconst('P', 'f', 'a', 'u'); }
int64_t getUniqueId() const override { return d_cconst('P', 'h', 'e', 'r'); }
// Initialisation
void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
@ -85,8 +85,8 @@ class Chassis : public Plugin {
void setParameterValue(uint32_t index, float value) override;
float getParameterValue(uint32_t index) const override;
// void initProgramName(uint32_t index, String &programName) override;
// void loadProgram(uint32_t index) override;
void initProgramName(uint32_t index, String &programName) override;
void loadProgram(uint32_t index) override;
// Processing
void activate() override;
@ -101,7 +101,7 @@ class Chassis : public Plugin {
double sampleRate;
uint32_t lastEvent;
// Voice voice[NUM_VOICES];
uint8_t vPtr;
uint8_t vPtr = 0;
Synth s;

View File

@ -18,7 +18,7 @@
#include "chassis.hpp"
void Chassis::initParameter(uint32_t index, Parameter &parameter) {
void Chassis::initParameter(uint32_t index, Parameter& parameter) {
switch (index) {
case paramLFORate:
parameter.hints = kParameterIsAutomatable;
@ -26,7 +26,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_lforate";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 57.0f;
parameter.ranges.def = 48.0f;
parameter.midiCC = 3;
break;
@ -36,7 +36,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_lfodelay";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 45.0f;
parameter.ranges.def = 0.0f;
parameter.midiCC = 9;
break;
@ -45,9 +45,22 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.name = "Range";
parameter.symbol = "ch_vcorange";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 4.0f;
parameter.ranges.def = 2.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 12;
parameter.enumValues.count = 3;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[3];
enumValues[0].value = 0.0f;
enumValues[0].label = "16'";
enumValues[1].value = 1.0f;
enumValues[1].label = "8'";
enumValues[2].value = 2.0f;
enumValues[2].label = "4'";
parameter.enumValues.values = enumValues;
}
break;
case paramVCOLFO:
@ -56,7 +69,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_lfo";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.def = 10.0f;
parameter.midiCC = 13;
break;
@ -66,18 +79,29 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_pwm";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 55.0f;
parameter.ranges.def = 48.0f;
parameter.midiCC = 14;
break;
case paramPWMMode:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.name = "LFO/Manual";
parameter.name = "PWM Mode";
parameter.symbol = "ch_pwmmode";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 15;
parameter.enumValues.count = 2;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[2];
enumValues[0].value = 0.0f;
enumValues[0].label = "LFO";
enumValues[1].value = 1.0f;
enumValues[1].label = "MAN";
parameter.enumValues.values = enumValues;
}
break;
case paramSaw:
@ -85,8 +109,8 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.name = "Saw";
parameter.symbol = "ch_saw";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 127.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 17;
break;
@ -95,8 +119,8 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.name = "Square";
parameter.symbol = "ch_sqr";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 127.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 16;
break;
@ -125,7 +149,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.name = "HPF";
parameter.symbol = "ch_hpf";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 4.0f;
parameter.ranges.max = 3.0f;
parameter.ranges.def = 0.0f;
parameter.midiCC = 20;
break;
@ -136,7 +160,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_freq";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.def = 60.0f;
parameter.midiCC = 74;
break;
case paramVCFReso:
@ -149,13 +173,24 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.midiCC = 71;
break;
case paramVCFMode:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.name = "Polarity";
parameter.symbol = "ch_vcfmode";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 21;
parameter.enumValues.count = 2;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[2];
enumValues[0].value = 0.0f;
enumValues[0].label = "POS";
enumValues[1].value = 1.0f;
enumValues[1].label = "INV";
parameter.enumValues.values = enumValues;
}
break;
case paramVCFEnv:
parameter.hints = kParameterIsAutomatable;
@ -163,7 +198,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_vcfenv";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.def = 46.0f;
parameter.midiCC = 22;
break;
case paramVCFLFO:
@ -181,7 +216,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_vcfkey";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.def = 71.0f;
parameter.midiCC = 24;
break;
@ -191,7 +226,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_attack";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 59.0f;
parameter.ranges.def = 27.0f;
parameter.midiCC = 73;
break;
@ -201,7 +236,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_decay";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 32.0f;
parameter.ranges.def = 57.0f;
parameter.midiCC = 75;
break;
@ -211,7 +246,7 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_sustain";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 86.0f;
parameter.ranges.def = 57.0f;
parameter.midiCC = 27;
break;
@ -221,18 +256,28 @@ void Chassis::initParameter(uint32_t index, Parameter &parameter) {
parameter.symbol = "ch_release";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 40.0f;
parameter.ranges.def = 48.0f;
parameter.midiCC = 72;
break;
case paramEnvGate:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.name = "Env / Gate";
parameter.hints = kParameterIsAutomatable | kParameterIsInteger; // | kParameterIsBoolean;
parameter.name = "Env-Gate";
parameter.symbol = "ch_envgate";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
parameter.midiCC = 25;
parameter.enumValues.count = 2;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[2];
enumValues[0].value = 0.0f;
enumValues[0].label = "ENV";
enumValues[1].value = 1.0f;
enumValues[1].label = "GATE";
parameter.enumValues.values = enumValues;
}
break;
case paramVCALevel:
@ -321,16 +366,16 @@ void Chassis::setParameterValue(uint32_t index, float value) {
case paramVCORange: // bits 0-2 of switch 1
// doesn't look great in Carla because of odd behaviour with small integer knobs
s.patchRam.switch1 &= 0xf8;
s.patchRam.switch1 |= (1 << (int)value);
s.patchRam.switch1 |= (1 << (int)(value - 1));
break;
case paramSqr: // bit 3 of switch 1
s.patchRam.switch1 &= 0xf7;
s.patchRam.switch1 |= (value > 63) << 3;
s.patchRam.switch1 |= (value >= 0.5) << 3;
break;
case paramSaw: // bit 4 of switch 1
s.patchRam.switch1 &= 0xef;
s.patchRam.switch1 |= (value > 63) << 4;
s.patchRam.switch1 |= (value >= 0.5) << 4;
break;
// missing chorus switch
@ -338,23 +383,23 @@ void Chassis::setParameterValue(uint32_t index, float value) {
// switch 2 params
case paramPWMMode: // bit 0 of switch 2
s.patchRam.switch2 &= 0xfe;
s.patchRam.switch2 |= (value > 63);
s.patchRam.switch2 |= (value >= 0.5);
break;
case paramVCFMode: // bit 1 of switch 2
s.patchRam.switch2 &= 0xfd;
s.patchRam.switch2 |= (value > 63) << 1;
s.patchRam.switch2 |= (value >= 0.5) << 1;
break;
case paramEnvGate:
s.patchRam.switch2 &= 0xfb;
s.patchRam.switch2 |= (value > 63) << 2;
s.patchRam.switch2 |= (value >= 0.5) << 2;
break;
case paramHPF: // bits 3-4 of switch 2
// doesn't look great in Carla because of odd behaviour with small integer knobs
if (value > 3) value = 3;
s.patchRam.switch2 &= 0xf3;
s.patchRam.switch2 |= (int)value << 2;
s.patchRam.switch2 |= (int)value << 3;
break;
case paramModWheel:
@ -364,15 +409,70 @@ void Chassis::setParameterValue(uint32_t index, float value) {
}
float Chassis::getParameterValue(uint32_t index) const {
// printf("getparametervalue %d\n", index);
switch (index) {
case paramLFORate:
return s.patchRam.lfoRate;
break;
case paramLFODelay:
return s.patchRam.lfoDelay;
break;
case paramVCORange:
// FIXME this needs to be better generally
switch (s.patchRam.switch1 & 0x07) {
case 1:
return 0;
break;
case 4:
return 2;
break;
default:
return 1;
}
break;
case paramVCOLFO:
return s.patchRam.vcoLfo;
break;
case paramPWMLFO:
return s.patchRam.pwmLfo * 1.27f;
break;
case paramPWMMode:
return (s.patchRam.switch2 & 0x01) != 0;
break;
case paramSaw:
return (s.patchRam.switch1 & 0x10) ? 127.0f : 0.0f;
return (s.patchRam.switch1 & 0x10) != 0;
break;
case paramSqr:
return (s.patchRam.switch1 & 0x08) ? 127.0f : 0.0f;
return (s.patchRam.switch1 & 0x08) != 0;
case paramSub:
return s.patchRam.sub;
break;
case paramNoise:
return s.patchRam.noise;
break;
case paramHPF:
return (s.patchRam.switch2 & 0x18) >> 3;
break;
case paramVCFFreq:
return s.patchRam.vcfFreq;
break;
case paramVCFReso:
return s.patchRam.vcfReso;
break;
case paramVCFEnv:
return s.patchRam.vcfEnv;
break;
case paramVCFLFO:
return s.patchRam.vcfLfo;
break;
case paramVCFKey:
return s.patchRam.vcfKey;
break;
case paramVCFMode:
return (s.patchRam.switch2 & 0x02) != 0;
break;
case paramAttack:
return s.patchRam.env_a;
break;
@ -385,6 +485,13 @@ float Chassis::getParameterValue(uint32_t index) const {
case paramRelease:
return s.patchRam.env_r;
break;
case paramEnvGate:
return (s.patchRam.switch2 & 0x04) != 0;
case paramVCALevel:
return s.patchRam.vca;
break;
}
return 0;
}

157
plugin/patches.hpp Normal file
View File

@ -0,0 +1,157 @@
#pragma once
#include <stdint.h>
#include <string>
#include "DistrhoPlugin.hpp"
const std::string patchName[] = {
"Brass Set 1", "Brass Swell", "Trumpet", "Flutes", "Moving Strings", "Brass & Strings", "Choir", "Piano I",
"Organ I", "Organ II", "Combo Organ", "Calliope", "Donald Pluck", "Celeste* (1 oct.up)", "Elect. Piano I",
"Elect. Piano II", "Clock Chimes* (1 oct. up)", "Steel Drums", "Xylophone", "Brass III", "Fanfare", "String III",
"Pizzicato", "High Strings", "Bass clarinet", "English Horn", "Brass Ensemble", "Guitar", "Koto", "Dark Pluck",
"Funky I", "Synth Bass I (unison)", "Lead I", "Lead II", "Lead III", "Funky II", "Synth Bass II", "Funky III",
"Thud Wah", "Going Up", "Piano II", "Clav", "Frontier Organ", "Snare Drum (unison)", "Tom Toms (unison)",
"Timpani (unison)", "Shaker", "Synth Pad", "Sweep I", "Pluck Sweep", "Repeater", "Sweep II", "Pluck Bell",
"Dark Synth Piano", "Sustainer", "Wah Release", "Gong (play low chords)", "Resonance Funk",
"Drum Booms* (1 oct. down)", "Dust Storm", "Rocket Men", "Hand Claps", "FX Sweep", "Caverns", "Strings",
"Violin", "Chorus Vibes", "Organ 1", "Harpsichord 1", "Recorder", "Perc. Pluck", "Noise Sweep", "Space Chimes",
"Nylon Guitar", "Orchestral Pad", "Bright Pluck", "Organ Bell", "Accordion", "FX Rise 1", "FX Rise 2", "Brass",
"Helicopter", "Lute", "Chorus Funk", "Tomita", "FX Sweep 1", "Sharp Reed", "Bass Pluck", "Resonant Rise",
"Harpsichord 2", "Dark Ensemble", "Contact Wah", "Noise Sweep 2", "Glassy Wah", "Phase Ensemble", "Chorused Bell",
"Clav", "Organ 2", "Bassoon", "Auto Release Noise Sweep", "Brass Ensemble", "Ethereal", "Chorus Bell 2",
"Blizzard", "E. Piano with Tremolo", "Clarinet", "Thunder", "Reedy Organ", "Flute / Horn", "Toy Rhodes",
"Surf's Up", "OW Bass", "Piccolo", "Melodic Taps", "Meow Brass", "Violin (high)", "High Bells", "Rolling Wah",
"Ping Bell", "Brassy Organ", "Low Dark Strings", "Piccolo Trumpet", "Cello", "High Strings", "Rocket Men",
"Forbidden Planet", "Froggy", "Owgan"};
const uint8_t patchData[128][18] = {
{0x14, 0x31, 0x00, 0x66, 0x00, 0x23, 0x0d, 0x3a, 0x00, 0x56, 0x6c, 0x03, 0x31, 0x2d, 0x20, 0x00, 0x51, 0x11},
{0x06, 0x30, 0x00, 0x38, 0x00, 0x2b, 0x11, 0x1a, 0x00, 0x54, 0x4b, 0x40, 0x76, 0x26, 0x25, 0x46, 0x52, 0x19},
{0x34, 0x2d, 0x08, 0x66, 0x00, 0x37, 0x22, 0x18, 0x01, 0x3b, 0x7f, 0x05, 0x42, 0x30, 0x10, 0x00, 0x32, 0x09},
{0x3c, 0x2b, 0x01, 0x00, 0x00, 0x37, 0x20, 0x0a, 0x0b, 0x29, 0x7f, 0x17, 0x51, 0x00, 0x12, 0x00, 0x32, 0x01},
{0x3f, 0x00, 0x00, 0x27, 0x00, 0x4d, 0x14, 0x04, 0x00, 0x6f, 0x22, 0x0d, 0x57, 0x58, 0x23, 0x0e, 0x1a, 0x10},
{0x23, 0x00, 0x00, 0x38, 0x00, 0x4c, 0x11, 0x04, 0x00, 0x29, 0x4e, 0x2c, 0x42, 0x35, 0x2c, 0x17, 0x49, 0x18},
{0x3b, 0x0e, 0x0d, 0x19, 0x00, 0x3b, 0x5e, 0x02, 0x00, 0x3e, 0x7f, 0x44, 0x0b, 0x7f, 0x30, 0x00, 0x4a, 0x09},
{0x14, 0x31, 0x00, 0x50, 0x00, 0x41, 0x0c, 0x0a, 0x00, 0x1b, 0x67, 0x00, 0x42, 0x00, 0x1e, 0x56, 0x2a, 0x11},
{0x36, 0x0f, 0x00, 0x35, 0x00, 0x2b, 0x4c, 0x0e, 0x01, 0x7f, 0x64, 0x00, 0x0a, 0x52, 0x00, 0x17, 0x29, 0x1c},
{0x2c, 0x0f, 0x00, 0x35, 0x00, 0x35, 0x4c, 0x0e, 0x01, 0x55, 0x4a, 0x00, 0x0a, 0x52, 0x00, 0x3a, 0x4a, 0x1c},
{0x4b, 0x15, 0x09, 0x39, 0x00, 0x3f, 0x46, 0x04, 0x00, 0x6d, 0x60, 0x00, 0x30, 0x2b, 0x2e, 0x3d, 0x2c, 0x0d},
{0x52, 0x28, 0x0b, 0x00, 0x00, 0x57, 0x1b, 0x11, 0x00, 0x38, 0x59, 0x07, 0x7f, 0x7f, 0x06, 0x30, 0x4a, 0x0b},
{0x4c, 0x15, 0x09, 0x39, 0x00, 0x49, 0x69, 0x0f, 0x00, 0x4e, 0x52, 0x02, 0x05, 0x2b, 0x0a, 0x7f, 0x2c, 0x07},
{0x1c, 0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x36, 0x00, 0x26, 0x60, 0x00, 0x2c, 0x00, 0x51, 0x0f, 0x2c, 0x19},
{0x3b, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1f, 0x3d, 0x06, 0x23, 0x7f, 0x01, 0x55, 0x2b, 0x28, 0x00, 0x29, 0x01},
{0x00, 0x00, 0x00, 0x47, 0x00, 0x32, 0x45, 0x07, 0x00, 0x50, 0x66, 0x00, 0x44, 0x00, 0x16, 0x00, 0x49, 0x11},
{0x3b, 0x00, 0x00, 0x00, 0x16, 0x2c, 0x7f, 0x00, 0x00, 0x7f, 0x68, 0x00, 0x30, 0x00, 0x33, 0x7f, 0x44, 0x1b},
{0x21, 0x35, 0x00, 0x20, 0x09, 0x47, 0x2e, 0x1a, 0x00, 0x7f, 0x7f, 0x00, 0x1a, 0x00, 0x25, 0x21, 0x4a, 0x1b},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x18, 0x36, 0x00, 0x33, 0x7f, 0x00, 0x1d, 0x1d, 0x26, 0x0f, 0x2c, 0x19},
{0x34, 0x14, 0x00, 0x23, 0x00, 0x42, 0x18, 0x0b, 0x00, 0x0c, 0x7f, 0x3a, 0x64, 0x5e, 0x25, 0x16, 0x52, 0x19},
{0x2f, 0x00, 0x00, 0x46, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x43, 0x21, 0x48, 0x68, 0x4b, 0x31, 0x32, 0x59, 0x18},
{0x30, 0x1b, 0x00, 0x66, 0x00, 0x47, 0x0e, 0x00, 0x00, 0x54, 0x49, 0x3f, 0x1f, 0x7f, 0x2d, 0x00, 0x1a, 0x10},
{0x3c, 0x12, 0x00, 0x66, 0x00, 0x42, 0x02, 0x05, 0x00, 0x2a, 0x7f, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x5a, 0x00},
{0x3a, 0x0e, 0x00, 0x66, 0x00, 0x54, 0x08, 0x02, 0x00, 0x47, 0x4d, 0x12, 0x2c, 0x7f, 0x28, 0x00, 0x0c, 0x08},
{0x34, 0x2d, 0x08, 0x00, 0x00, 0x30, 0x24, 0x19, 0x08, 0x3a, 0x68, 0x0b, 0x4b, 0x00, 0x19, 0x00, 0x29, 0x11},
{0x2f, 0x2d, 0x09, 0x66, 0x00, 0x46, 0x30, 0x07, 0x00, 0x1b, 0x7f, 0x08, 0x51, 0x1a, 0x10, 0x00, 0x2a, 0x01},
{0x34, 0x2d, 0x00, 0x66, 0x00, 0x2e, 0x2c, 0x1d, 0x01, 0x3b, 0x67, 0x10, 0x67, 0x61, 0x22, 0x1f, 0x52, 0x11},
{0x56, 0x3a, 0x00, 0x41, 0x00, 0x0c, 0x0f, 0x47, 0x00, 0x1e, 0x60, 0x00, 0x34, 0x36, 0x1f, 0x00, 0x39, 0x11},
{0x5a, 0x1c, 0x00, 0x5e, 0x00, 0x28, 0x3a, 0x1d, 0x00, 0x4b, 0x7f, 0x00, 0x38, 0x00, 0x27, 0x02, 0x4a, 0x01},
{0x1f, 0x00, 0x00, 0x57, 0x00, 0x26, 0x3d, 0x1b, 0x00, 0x47, 0x5a, 0x00, 0x34, 0x0f, 0x3f, 0x61, 0x0a, 0x19},
{0x04, 0x00, 0x00, 0x49, 0x00, 0x1f, 0x17, 0x33, 0x00, 0x29, 0x47, 0x00, 0x1e, 0x24, 0x02, 0x40, 0x59, 0x1d},
{0x3a, 0x10, 0x01, 0x39, 0x32, 0x20, 0x00, 0x42, 0x00, 0x23, 0x4b, 0x00, 0x22, 0x00, 0x24, 0x66, 0x29, 0x19},
{0x48, 0x58, 0x12, 0x00, 0x00, 0x28, 0x61, 0x24, 0x00, 0x34, 0x63, 0x00, 0x2d, 0x49, 0x00, 0x00, 0x2a, 0x1d},
{0x18, 0x58, 0x00, 0x35, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x34, 0x38, 0x01, 0x17, 0x5b, 0x4b, 0x4f, 0x39, 0x14},
{0x56, 0x47, 0x15, 0x66, 0x00, 0x3c, 0x1f, 0x12, 0x01, 0x4c, 0x7f, 0x00, 0x42, 0x30, 0x0b, 0x00, 0x32, 0x15},
{0x04, 0x00, 0x00, 0x30, 0x00, 0x05, 0x17, 0x51, 0x00, 0x29, 0x64, 0x00, 0x1e, 0x27, 0x02, 0x39, 0x4a, 0x15},
{0x5a, 0x15, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x00, 0x4e, 0x00, 0x25, 0x09, 0x16, 0x2d, 0x31, 0x1c},
{0x04, 0x00, 0x00, 0x09, 0x65, 0x26, 0x36, 0x2d, 0x00, 0x0a, 0x4f, 0x00, 0x18, 0x00, 0x02, 0x7f, 0x39, 0x1d},
{0x3e, 0x00, 0x00, 0x66, 0x08, 0x4e, 0x59, 0x22, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x66, 0x2d, 0x20, 0x1a, 0x1a},
{0x00, 0x00, 0x00, 0x64, 0x1c, 0x4f, 0x7f, 0x25, 0x00, 0x41, 0x4b, 0x00, 0x6c, 0x12, 0x7f, 0x00, 0x22, 0x13},
{0x01, 0x00, 0x00, 0x48, 0x00, 0x2f, 0x00, 0x27, 0x00, 0x05, 0x4e, 0x00, 0x62, 0x00, 0x20, 0x73, 0x2a, 0x10},
{0x42, 0x0f, 0x01, 0x66, 0x00, 0x07, 0x0b, 0x56, 0x02, 0x00, 0x78, 0x00, 0x27, 0x30, 0x0e, 0x00, 0x49, 0x15},
{0x4f, 0x0f, 0x03, 0x55, 0x00, 0x45, 0x36, 0x00, 0x00, 0x34, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x1d, 0x2a, 0x1c},
{0x34, 0x1b, 0x00, 0x00, 0x5b, 0x5e, 0x0b, 0x11, 0x00, 0x00, 0x65, 0x00, 0x19, 0x00, 0x1e, 0x40, 0x22, 0x11},
{0x3e, 0x10, 0x08, 0x00, 0x7f, 0x35, 0x04, 0x28, 0x00, 0x15, 0x65, 0x00, 0x1e, 0x0f, 0x28, 0x3a, 0x21, 0x18},
{0x00, 0x00, 0x00, 0x23, 0x7f, 0x19, 0x00, 0x36, 0x00, 0x18, 0x7f, 0x01, 0x38, 0x1a, 0x47, 0x2f, 0x21, 0x11},
{0x15, 0x47, 0x00, 0x3a, 0x7f, 0x59, 0x2d, 0x01, 0x11, 0x50, 0x7f, 0x0a, 0x09, 0x00, 0x00, 0x00, 0x22, 0x01},
{0x38, 0x00, 0x05, 0x2b, 0x00, 0x25, 0x00, 0x54, 0x00, 0x7f, 0x33, 0x00, 0x55, 0x4b, 0x3e, 0x25, 0x0a, 0x18},
{0x4e, 0x00, 0x00, 0x66, 0x1c, 0x73, 0x28, 0x43, 0x00, 0x00, 0x61, 0x00, 0x3f, 0x7f, 0x52, 0x2a, 0x0c, 0x12},
{0x44, 0x30, 0x00, 0x44, 0x00, 0x3c, 0x6f, 0x09, 0x06, 0x62, 0x2d, 0x00, 0x5b, 0x00, 0x4d, 0x7d, 0x1a, 0x08},
{0x4d, 0x14, 0x09, 0x65, 0x00, 0x61, 0x1e, 0x38, 0x00, 0x39, 0x57, 0x0e, 0x00, 0x29, 0x00, 0x2c, 0x4a, 0x17},
{0x58, 0x48, 0x0f, 0x61, 0x00, 0x42, 0x66, 0x44, 0x00, 0x46, 0x65, 0x00, 0x59, 0x35, 0x4e, 0x30, 0x4a, 0x19},
{0x33, 0x00, 0x05, 0x11, 0x00, 0x27, 0x00, 0x31, 0x00, 0x7f, 0x31, 0x00, 0x55, 0x4b, 0x35, 0x31, 0x0c, 0x18},
{0x7f, 0x00, 0x00, 0x00, 0x00, 0x38, 0x56, 0x06, 0x00, 0x47, 0x4f, 0x00, 0x2f, 0x00, 0x32, 0x7f, 0x1a, 0x1a},
{0x47, 0x00, 0x05, 0x2e, 0x00, 0x27, 0x00, 0x54, 0x00, 0x7f, 0x39, 0x00, 0x55, 0x4b, 0x46, 0x31, 0x2a, 0x18},
{0x59, 0x0e, 0x01, 0x19, 0x00, 0x48, 0x58, 0x13, 0x00, 0x42, 0x68, 0x00, 0x54, 0x00, 0x1d, 0x57, 0x0a, 0x13},
{0x7f, 0x00, 0x00, 0x66, 0x38, 0x46, 0x6b, 0x05, 0x00, 0x48, 0x5b, 0x03, 0x30, 0x7f, 0x62, 0x00, 0x49, 0x13},
{0x3b, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x7f, 0x2d, 0x00, 0x59, 0x7f, 0x00, 0x13, 0x00, 0x16, 0x00, 0x21, 0x11},
{0x00, 0x00, 0x00, 0x66, 0x7f, 0x2a, 0x00, 0x22, 0x00, 0x3a, 0x7f, 0x00, 0x24, 0x0f, 0x31, 0x2e, 0x21, 0x19},
{0x00, 0x00, 0x00, 0x00, 0x7f, 0x34, 0x55, 0x00, 0x2c, 0x5e, 0x7f, 0x58, 0x5b, 0x1c, 0x55, 0x00, 0x21, 0x11},
{0x08, 0x20, 0x00, 0x66, 0x61, 0x49, 0x72, 0x08, 0x00, 0x38, 0x7f, 0x00, 0x59, 0x7f, 0x68, 0x00, 0x24, 0x03},
{0x3b, 0x00, 0x00, 0x00, 0x7f, 0x11, 0x58, 0x36, 0x00, 0x37, 0x7f, 0x01, 0x0b, 0x00, 0x08, 0x00, 0x21, 0x05},
{0x7f, 0x41, 0x74, 0x66, 0x7f, 0x47, 0x2c, 0x53, 0x00, 0x5e, 0x7f, 0x00, 0x5e, 0x00, 0x70, 0x7f, 0x29, 0x12},
{0x00, 0x00, 0x00, 0x66, 0x7f, 0x44, 0x76, 0x00, 0x00, 0x45, 0x6b, 0x00, 0x0d, 0x26, 0x2f, 0x00, 0x21, 0x08},
{0x39, 0x2d, 0x00, 0x37, 0x00, 0x55, 0x00, 0x00, 0x00, 0x6c, 0x34, 0x3b, 0x20, 0x56, 0x28, 0x00, 0x1a, 0x18},
{0x42, 0x2d, 0x14, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x78, 0x6e, 0x2b, 0x2d, 0x39, 0x1a, 0x00, 0x32, 0x18},
{0x48, 0x2d, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x3b, 0x00, 0x17, 0x58, 0x00, 0x59, 0x2f, 0x4a, 0x00, 0x4a, 0x19},
{0x2d, 0x2a, 0x00, 0x49, 0x00, 0x3c, 0x48, 0x0e, 0x00, 0x7f, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0a, 0x1d},
{0x17, 0x00, 0x00, 0x36, 0x00, 0x7f, 0x7f, 0x5a, 0x00, 0x56, 0x7d, 0x00, 0x3c, 0x00, 0x1f, 0x23, 0x2c, 0x00},
{0x4e, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x2e, 0x00, 0x7f, 0x7f, 0x05, 0x15, 0x7f, 0x1e, 0x00, 0x2a, 0x11},
{0x3e, 0x26, 0x08, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x49, 0x41, 0x00, 0x10, 0x4e, 0x74, 0x00, 0x4a, 0x19},
{0x7f, 0x00, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x4d, 0x00, 0x68, 0x5c, 0x0e, 0x4e, 0x6c, 0x78, 0x00, 0x21, 0x18},
{0x63, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7f, 0x00, 0x00, 0x4a, 0x55, 0x00, 0x19, 0x00, 0x3c, 0x00, 0x4c, 0x18},
{0x48, 0x2d, 0x00, 0x1d, 0x00, 0x39, 0x00, 0x1a, 0x00, 0x19, 0x73, 0x00, 0x59, 0x00, 0x20, 0x00, 0x2a, 0x01},
{0x16, 0x2d, 0x00, 0x69, 0x00, 0x21, 0x00, 0x37, 0x00, 0x24, 0x00, 0x1d, 0x58, 0x32, 0x34, 0x7f, 0x1a, 0x18},
{0x00, 0x00, 0x00, 0x3a, 0x00, 0x39, 0x00, 0x28, 0x00, 0x56, 0x68, 0x00, 0x19, 0x2a, 0x2c, 0x00, 0x2a, 0x11},
{0x4e, 0x00, 0x06, 0x44, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x7f, 0x3e, 0x00, 0x00, 0x7f, 0x1a, 0x55, 0x5a, 0x19},
{0x00, 0x00, 0x00, 0x40, 0x00, 0x4d, 0x00, 0x0e, 0x00, 0x4a, 0x42, 0x08, 0x0b, 0x6e, 0x09, 0x50, 0x5a, 0x01},
{0x74, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x7f, 0x10, 0x7f, 0x40, 0x00, 0x00, 0x00, 0x7f, 0x54, 0x00, 0x44, 0x1a},
{0x6c, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x7f, 0x50, 0x17, 0x7f, 0x00, 0x00, 0x7f, 0x33, 0x47, 0x00, 0x02, 0x1a},
{0x33, 0x7f, 0x00, 0x49, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x7f, 0x48, 0x03, 0x2c, 0x33, 0x0b, 0x00, 0x52, 0x1c},
{0x6a, 0x00, 0x00, 0x30, 0x00, 0x52, 0x05, 0x5d, 0x7f, 0x00, 0x48, 0x00, 0x00, 0x23, 0x4c, 0x7f, 0x0a, 0x1b},
{0x34, 0x00, 0x02, 0x69, 0x00, 0x1d, 0x00, 0x23, 0x00, 0x56, 0x7f, 0x00, 0x30, 0x22, 0x57, 0x00, 0x2a, 0x19},
{0x4d, 0x5e, 0x00, 0x49, 0x00, 0x2f, 0x22, 0x35, 0x00, 0x41, 0x2a, 0x00, 0x0b, 0x22, 0x00, 0x4f, 0x5a, 0x1d},
{0x4e, 0x00, 0x00, 0x69, 0x00, 0x31, 0x7d, 0x0f, 0x02, 0x7f, 0x39, 0x00, 0x0e, 0x4f, 0x00, 0x00, 0x24, 0x1f},
{0x7f, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x7f, 0x10, 0x4c, 0x40, 0x00, 0x00, 0x00, 0x7f, 0x55, 0x00, 0x44, 0x18},
{0x15, 0x00, 0x00, 0x49, 0x00, 0x21, 0x00, 0x35, 0x00, 0x41, 0x37, 0x02, 0x12, 0x70, 0x00, 0x00, 0x3c, 0x1c},
{0x00, 0x00, 0x00, 0x3c, 0x00, 0x25, 0x1d, 0x1c, 0x00, 0x2b, 0x5c, 0x00, 0x2a, 0x23, 0x00, 0x00, 0x39, 0x18},
{0x34, 0x00, 0x0f, 0x00, 0x00, 0x42, 0x6b, 0x1f, 0x00, 0x49, 0x3e, 0x00, 0x34, 0x27, 0x00, 0x00, 0x11, 0x1e},
{0x00, 0x00, 0x00, 0x69, 0x00, 0x7f, 0x5f, 0x00, 0x00, 0x7f, 0x6b, 0x00, 0x2d, 0x00, 0x00, 0x23, 0x3c, 0x11},
{0x00, 0x00, 0x00, 0x39, 0x00, 0x37, 0x00, 0x00, 0x00, 0x6b, 0x43, 0x15, 0x00, 0x7f, 0x23, 0x4b, 0x5a, 0x1b},
{0x4e, 0x00, 0x00, 0x51, 0x00, 0x3d, 0x65, 0x2e, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x17},
{0x7f, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x53, 0x00, 0x68, 0x74, 0x7f, 0x4f, 0x1a, 0x53, 0x00, 0x44, 0x1a},
{0x00, 0x5e, 0x00, 0x1c, 0x00, 0x18, 0x22, 0x3d, 0x00, 0x41, 0x70, 0x06, 0x12, 0x32, 0x26, 0x00, 0x2a, 0x19},
{0x0b, 0x2d, 0x05, 0x69, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x7f, 0x63, 0x54, 0x2d, 0x39, 0x31, 0x00, 0x0a, 0x18},
{0x00, 0x0b, 0x00, 0x69, 0x00, 0x3b, 0x7f, 0x00, 0x00, 0x7f, 0x3e, 0x00, 0x3e, 0x00, 0x39, 0x65, 0x4c, 0x18},
{0x32, 0x0b, 0x00, 0x5b, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x00, 0x6c, 0x00, 0x2b, 0x37, 0x00, 0x07, 0x29, 0x09},
{0x51, 0x00, 0x00, 0x68, 0x00, 0x36, 0x6a, 0x07, 0x00, 0x7f, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x1d},
{0x54, 0x26, 0x09, 0x5a, 0x00, 0x23, 0x00, 0x2b, 0x09, 0x62, 0x7f, 0x05, 0x7f, 0x6a, 0x02, 0x00, 0x29, 0x01},
{0x7f, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x00, 0x68, 0x6b, 0x00, 0x4f, 0x39, 0x53, 0x00, 0x44, 0x1a},
{0x19, 0x5e, 0x00, 0x49, 0x00, 0x2f, 0x22, 0x23, 0x00, 0x41, 0x27, 0x06, 0x44, 0x43, 0x26, 0x00, 0x5a, 0x18},
{0x45, 0x00, 0x00, 0x69, 0x00, 0x2f, 0x78, 0x00, 0x00, 0x7f, 0x3c, 0x5c, 0x32, 0x7f, 0x37, 0x3b, 0x1a, 0x18},
{0x48, 0x2d, 0x00, 0x1d, 0x00, 0x00, 0x66, 0x3e, 0x00, 0x5a, 0x1e, 0x00, 0x75, 0x00, 0x78, 0x00, 0x5a, 0x19},
{0x01, 0x00, 0x00, 0x69, 0x7f, 0x38, 0x59, 0x07, 0x26, 0x79, 0x7f, 0x4e, 0x62, 0x57, 0x4e, 0x00, 0x24, 0x00},
{0x2c, 0x00, 0x00, 0x15, 0x00, 0x16, 0x00, 0x23, 0x07, 0x6b, 0x67, 0x00, 0x41, 0x3c, 0x62, 0x7f, 0x2c, 0x10},
{0x45, 0x16, 0x09, 0x00, 0x00, 0x23, 0x00, 0x2b, 0x07, 0x62, 0x68, 0x05, 0x7f, 0x6a, 0x07, 0x00, 0x2a, 0x01},
{0x7f, 0x00, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x4d, 0x00, 0x68, 0x6b, 0x00, 0x16, 0x6c, 0x78, 0x00, 0x21, 0x18},
{0x23, 0x12, 0x00, 0x49, 0x00, 0x21, 0x00, 0x35, 0x00, 0x41, 0x45, 0x03, 0x2c, 0x6d, 0x00, 0x00, 0x2a, 0x1c},
{0x22, 0x00, 0x00, 0x3b, 0x00, 0x19, 0x00, 0x2a, 0x00, 0x41, 0x16, 0x15, 0x49, 0x47, 0x30, 0x00, 0x19, 0x18},
{0x1e, 0x2d, 0x7f, 0x00, 0x00, 0x3a, 0x7f, 0x00, 0x00, 0x7f, 0x6b, 0x00, 0x59, 0x00, 0x27, 0x00, 0x24, 0x00},
{0x01, 0x00, 0x00, 0x69, 0x7f, 0x54, 0x0b, 0x00, 0x31, 0x36, 0x4b, 0x21, 0x61, 0x7f, 0x79, 0x00, 0x24, 0x0a},
{0x32, 0x00, 0x00, 0x32, 0x00, 0x3f, 0x54, 0x41, 0x00, 0x7f, 0x46, 0x7f, 0x00, 0x6b, 0x00, 0x2f, 0x39, 0x1f},
{0x46, 0x1c, 0x00, 0x0e, 0x00, 0x04, 0x00, 0x3f, 0x10, 0x62, 0x57, 0x10, 0x67, 0x6a, 0x15, 0x00, 0x3c, 0x09},
{0x63, 0x00, 0x00, 0x00, 0x7f, 0x48, 0x70, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x41, 0x00},
{0x33, 0x7f, 0x00, 0x49, 0x00, 0x2d, 0x64, 0x23, 0x00, 0x41, 0x54, 0x04, 0x5a, 0x00, 0x1b, 0x00, 0x32, 0x1c},
{0x47, 0x2d, 0x16, 0x00, 0x00, 0x59, 0x00, 0x00, 0x03, 0x78, 0x55, 0x2b, 0x2d, 0x39, 0x1a, 0x00, 0x34, 0x18},
{0x1e, 0x2d, 0x7f, 0x00, 0x00, 0x4c, 0x7f, 0x00, 0x00, 0x7f, 0x6f, 0x00, 0x16, 0x34, 0x3b, 0x00, 0x24, 0x00},
{0x24, 0x00, 0x00, 0x69, 0x00, 0x3c, 0x09, 0x00, 0x7f, 0x00, 0x4d, 0x22, 0x37, 0x7f, 0x69, 0x00, 0x2a, 0x18},
{0x00, 0x0b, 0x00, 0x68, 0x00, 0x4c, 0x7f, 0x00, 0x00, 0x7f, 0x53, 0x00, 0x17, 0x17, 0x39, 0x00, 0x4c, 0x18},
{0x10, 0x00, 0x00, 0x44, 0x00, 0x08, 0x00, 0x57, 0x00, 0x34, 0x0e, 0x00, 0x24, 0x6d, 0x00, 0x38, 0x59, 0x18},
{0x15, 0x2d, 0x05, 0x51, 0x00, 0x47, 0x00, 0x00, 0x00, 0x67, 0x28, 0x53, 0x17, 0x6d, 0x2a, 0x00, 0x19, 0x18},
{0x33, 0x7f, 0x00, 0x49, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x7f, 0x61, 0x03, 0x2c, 0x33, 0x0b, 0x00, 0x32, 0x1c},
{0x39, 0x2d, 0x15, 0x00, 0x00, 0x4b, 0x00, 0x03, 0x01, 0x2d, 0x6d, 0x30, 0x41, 0x5a, 0x22, 0x00, 0x31, 0x18},
{0x50, 0x00, 0x0a, 0x46, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x47, 0x30, 0x1b, 0x39, 0x39, 0x29, 0x00, 0x1c, 0x18},
{0x6c, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x7f, 0x50, 0x3f, 0x7f, 0x00, 0x00, 0x7f, 0x33, 0x59, 0x00, 0x02, 0x1a},
{0x32, 0x0b, 0x00, 0x2c, 0x00, 0x1d, 0x04, 0x58, 0x05, 0x5f, 0x4f, 0x00, 0x30, 0x17, 0x2a, 0x09, 0x4c, 0x01},
{0x4e, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7f, 0x2b, 0x00, 0x7f, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x29, 0x17},
{0x32, 0x00, 0x00, 0x2d, 0x00, 0x26, 0x54, 0x20, 0x00, 0x7f, 0x65, 0x00, 0x31, 0x37, 0x00, 0x38, 0x39, 0x19}};

View File

@ -36,20 +36,17 @@ static inline float poly3blep1(float t) {
void Voice::run(Synth &s, float *buffer, uint32_t samples) {
float y, out, t;
// 325, because it needs PW to be from 0 to 0.5
// but really the control range is limited from 0 to 100
// there's a resistor on the panel board to sprag the range
float pw = s.ff4f / 32768.0f;
float fb, res = s.patchRam.vcfReso / 28.0f; // guess
//float cut = s.patchRam.vcfFreq / 400.0f; // guess
float cut = 248.0f * (powf(2,(vcfenv-0x1880)/1143.0f));
float cut = 248.0f * (powf(2, (vcfenv - 0x1880) / 1143.0f));
// now radians
cut = 0.25 * 6.2832 * cut / 48000.0f;
// now correct
cut = cut/(1+cut);
cut = cut / (1 + cut);
float sqr = (s.patchRam.switch1 & 0x08) ? 0.63 : 0; //? 0.175 : 0;
float saw = (s.patchRam.switch1 & 0x10) ? 0.8 : 0; //? 0.220 : 0;
@ -103,7 +100,7 @@ void Voice::run(Synth &s, float *buffer, uint32_t samples) {
out = y;
// widthDelay = pw;
//out *= 0.5;
out *= 0.707;
for (uint8_t ovs = 0; ovs < 4; ovs++) {
fb = b4;
@ -118,11 +115,11 @@ void Voice::run(Synth &s, float *buffer, uint32_t samples) {
b4 = ((b3 - b4) * cut) + b4;
}
vr58c106 += ((vcaEnv - vr58c106) * 0.0075);
vr58c106 += ((vcaEnv - vr58c106) * 0.005);
lastpw = pw;
out = b4 * (0.2);
out = b4 * (0.25);
buffer[i] += (gain * b4 * vr58c106);
buffer[i] += (gain * out * vr58c106);
}
}

View File

@ -112,24 +112,24 @@ class Synth {
// the comments indicate what the defaults are set to
// in the routine at 02c2h, in case they're important
struct {
uint8_t lfoRate = 57; // lookup value defaults to 0x0200
uint8_t lfoDelay = 45;
uint8_t vcoLfo = 0;
uint8_t pwmLfo = 55;
uint8_t noise = 0;
uint8_t vcfFreq = 85; // 0x3f80
uint8_t vcfReso = 0;
uint8_t vcfEnv = 0;
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 = 108;
uint8_t vca = 52;
uint8_t env_a = 59;
uint8_t env_d = 32;
uint8_t env_s = 86; // 0x3f80
uint8_t env_r = 40;
uint8_t sub = 0;
uint8_t switch1 = 26;
uint8_t switch2 = 24;
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];

View File

@ -329,7 +329,7 @@ h04ac: // pitch too high
void Voice::calcFilter(Synth &s) {
// 04d5
uint16_t a, bc, ea, hl, tos;
uint16_t a, bc, ea, tos;
goto h04d5;