Compare commits

..

2 Commits

Author SHA1 Message Date
Gordon JC Pearce b6044f67f5 corrected chorus button colours 2025-12-23 16:58:37 +00:00
Gordon JC Pearce e98b87e200 model b artwork (still needs slider caps done) 2025-12-23 13:22:14 +00:00
18 changed files with 36546 additions and 15733 deletions

View File

@ -1,43 +0,0 @@
name: build
on: [push, pull_request]
jobs:
linux:
strategy:
matrix:
target: [linux-arm64, linux-armhf, linux-i686, linux-riscv64, linux-x86_64]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: distrho/dpf-makefile-action@v1
with:
target: ${{ matrix.target }}
macos:
strategy:
matrix:
target: [macos-intel, macos-universal]
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: distrho/dpf-makefile-action@v1
with:
target: ${{ matrix.target }}
windows:
strategy:
matrix:
target: [win32, win64]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: distrho/dpf-makefile-action@v1
with:
target: ${{ matrix.target }}

View File

@ -23,15 +23,6 @@
#define DISTRHO_PLUGIN_NAME "peacock-8"
#define DISTRHO_PLUGIN_URI "https://gjcp.net/plugins/peacock"
#define DISTRHO_PLUGIN_CLAP_ID "net.gjcp.peacock"
#define DISTRHO_PLUGIN_CLAP_FEATURES "instrument","synthesizer","stereo"
#define DISTRHO_PLUGIN_BRAND_ID GJCP
#define DISTRHO_PLUGIN_UNIQUE_ID Pfau
#define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:InstrumentPlugin"
#define DISTRHO_PLUGIN_VST_CATEGORY "Fx|Instrument"
#define DISTRHO_PLUGIN_NUM_INPUTS 0
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
#define DISTRHO_PLUGIN_IS_SYNTH 1
@ -72,14 +63,10 @@
pSustain,
pRelease,
pChorusMode,
pVcoBend,
pVcfBend,
pModDepth,
pChorus,
parameterCount
};
#endif
#endif

View File

@ -21,10 +21,11 @@ FILES_DSP = \
FILES_UI = \
orangebutton.cpp \
whitebutton.cpp \
panel.cpp \
slider.cpp \
slideswitch.cpp \
artwork.cpp \
modelb.cpp \
ui.cpp
UI_TYPE = generic
@ -34,8 +35,7 @@ include ../dpf/Makefile.plugins.mk
SKIP_NATIVE_AUDIO_FALLBACK = true
# omitting LV2 for the moment until I figure out cross-compiling
TARGETS += jack vst2 vst3 clap
TARGETS += jack lv2_sep
all: $(TARGETS)

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,13 @@ namespace Artwork {
extern const char *orngBtnUp;
extern const char *orngBtnDn;
const unsigned int orngBtnSize = 41 * 30 * 4;
const unsigned int orngBtnWidth = 41;
const unsigned int orngBtnHeight = 30;
extern const char *whiteBtnUp;
extern const char *whiteBtnDn;
const unsigned int whiteBtnSize = 41 * 30 * 4;
const unsigned int whiteBtnWidth = 41;
const unsigned int whiteBtnHeight = 30;
extern const char *ledOnData;

View File

@ -43,12 +43,7 @@ Assigner::Assigner() {
}
void Assigner::handleMidi(MidiEvent* ev) {
uint8_t status = ev->data[0];
//printf("called with event %04x (%02x): %02x %02x %02x\n", ev->frame, ev->size, ev->data[0], ev->data[1], ev->data[2]);
if (ev->size > 3) return; // sysex bug
switch (status & 0xf0) {
case 0x80:
noteOff(ev->data[1]);
@ -61,11 +56,9 @@ void Assigner::handleMidi(MidiEvent* ev) {
break;
case 0xb0:
switch (ev->data[1]) {
case 0x01: // modwheel
printf("mod wheel %02x\n", ev->data[2]);
m->modWheel = ev->data[2];
// handle the following
// CC 64 - sustain // FIXME sustain not implemented
// CC 1 - modwheel
// CC 64 - sustain
// possibly JU-06 CC values
default:
break;
@ -73,8 +66,7 @@ void Assigner::handleMidi(MidiEvent* ev) {
break; // nothing to do here except in special cases where we don't expect the host to pass on controls
case 0xc0: // program change
break;
case 0xe0: // pitch bend
m->bend = ((ev->data[1] + (ev->data[2]<<7))>>5)-0x100;
case 0xe0: // pitch bend;
break;
case 0xf0: // sysex
break;
@ -118,10 +110,6 @@ 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];
@ -149,6 +137,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, i);
d_debug("send voice on %3d to voice %d", note, v);
voice[v].on(note);
}

View File

@ -27,7 +27,6 @@ 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

@ -19,8 +19,8 @@
#include "chorus.hpp"
#include <math.h>
#include <stdio.h>
#include <string.h>
Chorus::Chorus() {
lpfOut1 = new float[bufferSize];
lpfOut2 = new float[bufferSize];
@ -29,8 +29,7 @@ Chorus::Chorus() {
lfoPhase = 1;
lfoSpeed = 6.283 * 10.7 / sampleRate; // plainly silly value to show if it hasn't been set
gainTC = 1 - exp(-M_PI * 10 / sampleRate); // 1/10th of a second declick
bbdTC = 1 - exp(-M_PI * 60 / sampleRate); // hpf into BBD
gainTC = 1 - exp(-6.283 * 10 / sampleRate);
// not quite Butterworth but you'd never hear the difference
// these are calculated from the real-world component values
@ -59,7 +58,7 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
// run highpass / bass boost and stereo chorus effect for one full block
float s0 = 0, s1 = 0;
float dly1, frac, flt;
float lfoMod, dly1, frac, flt;
uint16_t tap, delay;
for (uint32_t i = 0; i < frames; i++) {
@ -76,14 +75,11 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
hpDelay = flt;
input[i] += (flt * hpGain);
flt = ((input[i] - bbdRC) * bbdTC) + bbdRC;
bbdRC = flt;
ram[delayptr] = input[i] - flt;
ram[delayptr] = input[i];
// delays in milliseconds
#define BASE 0.0035
#define AMT 0.002
#define BASE 0.005
#define AMT 0.00175
dly1 = (BASE + (AMT * lfoPhase)) * sampleRate;
delay = (int)dly1;
@ -106,6 +102,7 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
delayptr++;
delayptr &= 0x3ff;
}
postFilter1l->runSVF(lpfOut1, lpfOut1, frames);
postFilter2l->runSVF(lpfOut1, lpfOut1, frames);
postFilter1r->runSVF(lpfOut2, lpfOut2, frames);
@ -114,6 +111,7 @@ void Chorus::run(float* input, float** outputs, uint32_t frames) {
for (uint32_t i = 0; i < frames; i++) {
float y = input[i];
gainRC = (gain - gainRC) * gainTC + gainRC;
outputs[0][i] = y + (gainRC * lpfOut1[i]);
outputs[1][i] = y + (gainRC * lpfOut2[i]);
}
@ -127,11 +125,11 @@ void Chorus::setHpf(uint8_t mode) {
// k = 1-exp(-2pi * Fc * sampleRate)
switch (mode) {
case 0x00:
hpCut = 1 - exp(-M_PI * 720 / sampleRate);
hpCut = 1 - exp(-6.283 * 720 / sampleRate);
hpGain = -1;
break;
case 0x08:
hpCut = 1 - exp(-M_PI * 225 / sampleRate);
hpCut = 1 - exp(-6.283 * 225 / sampleRate);
hpGain = -1;
break;
case 0x10:
@ -140,7 +138,7 @@ void Chorus::setHpf(uint8_t mode) {
break;
case 0x18:
hpCut = 1 - exp(-6.283 * 85 / sampleRate);
hpGain = 1.0;
hpGain = 1.707;
break;
}
}
@ -149,16 +147,15 @@ void Chorus::setChorus(uint8_t mode) {
// switch chorus mode
switch (mode) {
case 0x60:
case 0x20:
gain = 0;
break;
case 0x40:
gain = 1.2;
lfoSpeed = M_PI * 0.525 / sampleRate;
lfoSpeed = 6.283 * 0.5 / sampleRate;
break;
case 0x00:
gain = 1.2;
lfoSpeed = M_PI * 0.85 / sampleRate;
lfoSpeed = 6.283 * 0.9 / sampleRate;
break;
}
}

View File

@ -46,8 +46,6 @@ class Chorus {
float gainRC = 0;
float gainTC = 0;
float bbdRC=0, bbdTC=0;
uint16_t delayptr = 0;

20575
plugin/modelb.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,14 +25,13 @@
Module::Module() {
// cutoff frequencies for various RC networks
vcaTC = 1 - exp(-M_PI * 159 / sampleRate); // VCA and VCF 10k/0.1u time constant
subTC = 1 - exp(-M_PI * 15 / sampleRate); // Main VCA and Sub Level 1k + 10u time constant
pwmTC = 1 - exp(-M_PI * 40 / sampleRate); // integrator with 100k/0.047u time constant
vcaTC = 1 - exp(-6.283 * 159 / sampleRate); // VCA and VCF 10k/0.1u time constant
subTC = 1 - exp(-6.283 * 15 / sampleRate); // Main VCA and Sub Level 1k + 10u time constant
pwmTC = 1 - exp(-6.283 * 40 / sampleRate); // integrator with 100k/0.047u time constant
vcaBuf = new float[bufferSize];
subBuf = new float[bufferSize];
pwmBuf = new float[bufferSize];
noiseBuf = new float[bufferSize];
}
Module::~Module() {
@ -41,115 +40,59 @@ Module::~Module() {
delete subBuf;
delete pwmBuf;
}
void Module::genNoise() {
for (uint32_t i = 0; i < bufferSize; i++) {
noiseRNG *= 0x8088405;
noiseRNG++;
noiseBuf[i] = 1 - (noiseRNG & 0xffff) / 32768.0f;
}
}
void Module::lfoRampOn() {
lfoDelayState = 1;
lfoDelayTimer = 0;
lfoDelay = 0;
}
void Module::runLFO() {
if (lfoDelayState == 1) {
lfoDelayTimer += attackTable[patchRam.lfoDelay];
if (lfoDelayTimer > 0x3fff) lfoDelayState = 2;
}
if ((lfoDelayState == 2)) {
lfoDelay += lfoDelayTable[patchRam.lfoDelay >> 4];
}
if (lfoDelay > 0xff) {
lfoDelayState = 0;
lfoDelay = 0xff;
}
lfoRate = lfoRateTable[patchRam.lfoRate]; // FIXME move to parameters
lfoPhase += (lfoState & 0x01) ? -lfoRate : lfoRate;
if (lfoPhase > 0x1fff) {
lfoPhase = 0x1fff;
lfoState++;
}
if (lfoPhase < 0x0000) {
lfoPhase = 0x0000;
lfoState++;
}
lfo = (lfoState & 0x02) ? -lfoPhase : lfoPhase;
pw = (lfoState & 0x02) ? lfoPhase + 0x2000 : 0x2000 - lfoPhase; // PW LFO is unipolar
pw = (patchRam.switch2 & 0x01) ? 0x3fff : pw; // either LFO or "all on"
pw = 0x3fff - ((pw * (int)(patchRam.pwmLfo*0.9125)) >> 7); // FIXME tidy up this bit
}
void Module::run(Voice* voices, uint32_t blockSize) {
// run updates for module board
int16_t lfoToVco = 0, lfoToVcf = 0;
// 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
master = powf(2, (patchRam.vca / 31.75 - 4.0f)) * 0.1;
square = (patchRam.switch1 & 0x08) ? 0.63 : 0;
saw = (patchRam.switch1 & 0x10) ? 0.8 : 0;
sub = patchRam.sub / 127.0f;
lfoPhase += lfoRateTable[patchRam.lfoRate];
square = (patchRam.switch1 & 0x08) ? 1 : 0;
saw = (patchRam.switch1 & 0x10) ? 1 : 0;
sub = (patchRam.sub / 127.0f) * 1.4;
res = patchRam.vcfReso / 127.0;
noise = (patchRam.noise / 127.0);
res = patchRam.vcfReso / 127.0 * 5;
noise = patchRam.noise / 127.0;
// FIXME the exp in these is expensive, don't call it all the time
chorus->setChorus(patchRam.switch1 & 0x60);
chorus->setHpf(patchRam.switch2 & 0x18);
runLFO();
if (lfoPhase & 0x4000)
lfo = 0x1fff - (lfoPhase & 0x3fff);
else
lfo = (lfoPhase & 0x3fff) - 0x1fff;
// FIXME represent PW as int until we calculate the block?
pw = 0.5 - ((0x2000 + lfo) * patchRam.pwmLfo) / (32768.0f * 128);
pw = (patchRam.switch2 & 0x01) ? 0.5 - (patchRam.pwmLfo / 256.0f) : pw;
float master = powf(2, (patchRam.vca / 31.75 - 4.0f));
float sub = patchRam.sub/ 127.0f;
// calculate "smoothed" parameters
// these are single outputs with heavy RC smoothing
for (uint32_t i = 0; i < blockSize; i++) {
vcaRC = (master - vcaRC) * subTC + vcaRC;
pwmRC = ((pw / 32768.0f) - pwmRC) * pwmTC + pwmRC;
pwmRC = (pw - pwmRC) * pwmTC + pwmRC;
subRC = (sub - subRC) * vcaTC + subRC;
vcaBuf[i] = vcaRC;
pwmBuf[i] = pwmRC;
subBuf[i] = subRC;
if (bufPtr < bufferSize) bufPtr++;
}
lfoToVco = (lfoDepthTable[patchRam.vcoLfo] * lfoDelay) >> 8; // lookup table is 0-255
lfoToVco += ((int)(modWheel * modDepth));
int16_t vcf = (patchRam.vcfEnv << 7) * ((patchRam.switch2 & 0x02) ? -1 : 1);
if (lfoToVco > 0xff) lfoToVco = 0xff;
lfoToVco = (lfo * lfoToVco) >> 11; // 8 for normalisation plus three additional DSLR EA
int16_t pitchBase = 0x1818;
pitchBase += (lfo * lfoDepthTable[patchRam.vcoLfo]) >> 9;
lfoToVcf = (patchRam.vcfLfo * lfoDelay) >> 7; // value is 0-127
lfoToVcf = (lfo * lfoToVcf) >> 9; // 8 for normalisation plus one additional DSLR EA
int16_t pitchBase = 0x1818, vcfBase = 0;
pitchBase += lfoToVco;
pitchBase += vcoBendDepth * bend;
vcfBase = (patchRam.vcfFreq << 7);
vcfBase += lfoToVcf;
vcfBase += vcfBendDepth * bend;
if (vcfBase > 0x3fff) vcfBase = 0x3fff;
if (vcfBase < 0x0000) vcfBase = 0x0000;
// per-voice calculations
for (uint32_t i = 0; i < NUM_VOICES; i++) {
// run one step of the envelope
// maybe move all this into voice.cpp FIXME
Voice* v = &voices[i];
switch (v->envPhase) {
case 0: // release phase FIXME use an enum I guess
@ -168,30 +111,21 @@ void Module::run(Voice* voices, uint32_t blockSize) {
}
// pitch
uint16_t pitch = pitchBase + (v->note << 8);
int8_t semi = pitch >> 8;
semi -= 36;
// FIXME clean this all up a bit
int16_t pitch = pitchBase + (v->note << 8);
int16_t semi = pitch >> 8;
float frac = (pitch & 0xff) / 256.0;
if (semi < 0) {
semi = 0;
frac = 0;
}
if (semi >= 103) {
semi = 103;
frac = 0;
};
float p1 = pitchTable[semi], p2 = pitchTable[semi + 1];
int16_t px = ((p2 - p1) * frac + p1); // interpolated pitch from table
// octave divider
float p1 = pitchTable[semi], p2 = pitchTable[semi + 1];
int16_t px = ((p2 - p1) * frac + p1);
px *= (patchRam.switch1 & 0x07);
v->omega = px / sampleRate; // FIXME recalculate table using proper scaler
v->omega = px / (sampleRate * 4.0f); // fixme use proper scaler
// per voice we need to calculate the key follow amount and envelope amount
v->vcfCut = vcfBase + (((v->env * patchRam.vcfEnv) >> 7) * ((patchRam.switch2 & 0x02) ? -1 : 1));
v->vcfCut += (int)((v->note - 60) * (patchRam.vcfKey << 1) * 0.375);
v->vcfCut = (patchRam.vcfFreq << 7) + ((vcf * v->env) >> 14);
v->vcfCut += (int)(v->note * (patchRam.vcfKey << 1) * 0.375);
if (v->vcfCut > 0x3fff) v->vcfCut = 0x3fff;
if (v->vcfCut < 0) v->vcfCut = 0;

View File

@ -33,39 +33,40 @@ class Module {
Module();
~Module();
void genNoise();
void lfoRampOn();
void run(Voice* voices, uint32_t blockLeft);
float res = 0;
// precomputed values for all voices
float pw; //, saw, square, sub;
// "internal state" values for patch parameters
uint16_t a, d, s, r;
int16_t lfo;
uint32_t lfoPhase;
float saw = 0, square = 0, sub = 0, noise = 0;
float saw = 0, square = 0, sub = 0, noise = 0, master = 0;
int16_t bend = 0, modWheel=0;
float vcoBendDepth = 4, vcfBendDepth=1.5, modDepth=.5;
struct {
uint8_t lfoRate = 0x1f;
uint8_t lfoRate = 0x18;
uint8_t lfoDelay = 0x00;
uint8_t vcoLfo = 0x00;
uint8_t pwmLfo = 0x3c;
uint8_t pwmLfo = 0x60;
uint8_t noise = 0x00;
uint8_t vcfFreq = 0x25; // 1c; // 0x3f80
uint8_t vcfReso = 0x1d;
uint8_t vcfEnv = 0x1c; // 4e;
uint8_t vcfLfo = 0x00;
uint8_t vcfKey = 0x2b; // 47;
uint8_t vca = 0x5c;
uint8_t vcfFreq = 0x30; // 1c; // 0x3f80
uint8_t vcfReso = 0x00;
uint8_t vcfEnv = 0x40; // 4e;
uint8_t vcfLfo = 0;
uint8_t vcfKey = 0x7f; // 47;
uint8_t vca = 0x28;
uint8_t env_a = 0x00;
uint8_t env_d = 0x2a;
uint8_t env_s = 0x23; // 0x3f80
uint8_t env_r = 0x00;
uint8_t env_d = 0x39;
uint8_t env_s = 0x30; // 0x3f80
uint8_t env_r = 0x30;
uint8_t sub = 0x40;
uint8_t switch1 = 0x19;
uint8_t switch1 = 0x59;
uint8_t switch2 = 0x18;
} patchRam;
Chorus* chorus;
float vcaTC;
@ -74,25 +75,13 @@ class Module {
float* vcaBuf;
float* subBuf;
float* pwmBuf;
float* noiseBuf;
private:
void runLFO();
// precalculated coefficients for RC networks
float pwmTC = 0, subTC = 0, mVcaTC = 0;
float pwmRC = 0, subRC = 0, vcaRC = 0;
int16_t lfo, pw;
int16_t lfoPhase;
uint8_t lfoState = 0;
uint16_t lfoRate;
uint32_t noiseRNG = 1;
uint16_t lfoDelay = 0;
uint8_t lfoDelayState = 0;
uint16_t lfoDelayTimer = 0;
// controls
};
class Voice {
@ -102,7 +91,7 @@ class Voice {
Voice();
void on(uint8_t midiNote);
void off();
void run(Module* m, float* buffer, uint32_t framePos, uint32_t samples);
void run(Module* m, float* buffer, uint32_t samples);
private:
float omega = 0, theta = 0; // phase increment and angle FIXME better names
@ -110,16 +99,16 @@ class Voice {
uint8_t pulseStage = 1; // pulse wave phase
float subosc = 1; // sub oscillator flipflop output
uint8_t envPhase = 0; // current running state of envelope
int16_t env = 0; // calculated envelope amount
int16_t vcfCut; // calculated cutoff to filter
int16_t vcaEnv; // calculated level to VCA (env/gate)
float vcaRC = 0, vcfRC = 0; // RC circuit state values
uint8_t envPhase = 0;
int16_t env = 0; // output amplitude
int16_t vcfCut;
int16_t vcaEnv;
float vcaRC = 0, vcfRC = 0;
uint8_t note = 0;
// filter
float y0 = 0, y1 = 0, y2 = 0, y3 = 0;
float b1 = 0, b2 = 0, b3 = 0, b4 = 0;
};
#endif

View File

@ -23,7 +23,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pLFORate:
parameter.hints = kParameterIsAutomatable;
parameter.name = "LFO Rate";
parameter.symbol = "pfau_lforate";
parameter.symbol = "ch_lforate";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 48.0f;
@ -33,7 +33,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pLFODelay:
parameter.hints = kParameterIsAutomatable;
parameter.name = "LFO Delay";
parameter.symbol = "pfau_lfodelay";
parameter.symbol = "ch_lfodelay";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
@ -43,7 +43,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pVCORange:
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.name = "Range";
parameter.symbol = "pfau_vcorange";
parameter.symbol = "ch_vcorange";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 1.0f;
@ -60,12 +60,13 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
enumValues[2].label = "4'";
parameter.enumValues.values = enumValues;
}
break;
case pLFODepth:
parameter.hints = kParameterIsAutomatable;
parameter.name = "LFO";
parameter.symbol = "pfau_lfo";
parameter.symbol = "ch_lfo";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 10.0f;
@ -75,7 +76,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pPWMDepth:
parameter.hints = kParameterIsAutomatable;
parameter.name = "PWM";
parameter.symbol = "pfau_pwm";
parameter.symbol = "ch_pwm";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 48.0f;
@ -85,7 +86,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pPWMMode:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.name = "PWM Mode";
parameter.symbol = "pfau_pwmmode";
parameter.symbol = "ch_pwmmode";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
@ -106,7 +107,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pSaw:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.name = "Saw";
parameter.symbol = "pfau_saw";
parameter.symbol = "ch_saw";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
@ -116,7 +117,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pSqr:
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
parameter.name = "Square";
parameter.symbol = "pfau_sqr";
parameter.symbol = "ch_sqr";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 1.0f;
@ -126,7 +127,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pSubLevel:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Sub Osc";
parameter.symbol = "pfau_sub";
parameter.symbol = "ch_sub";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
@ -136,7 +137,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pNoiseLevel:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Noise";
parameter.symbol = "pfau_noise";
parameter.symbol = "ch_noise";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
@ -146,7 +147,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pHPF:
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.name = "HPF";
parameter.symbol = "pfau_hpf";
parameter.symbol = "ch_hpf";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 3.9f;
parameter.ranges.def = 0.0f;
@ -156,7 +157,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pCutoff:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Freq";
parameter.symbol = "pfau_freq";
parameter.symbol = "ch_freq";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 60.0f;
@ -165,7 +166,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pRes:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Res";
parameter.symbol = "pfau_reso";
parameter.symbol = "ch_reso";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
@ -174,7 +175,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pVCFPol:
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.name = "Polarity";
parameter.symbol = "pfau_vcfmode";
parameter.symbol = "ch_vcfmode";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
@ -194,7 +195,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pEnv:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Env";
parameter.symbol = "pfau_vcfenv";
parameter.symbol = "ch_vcfenv";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 46.0f;
@ -203,7 +204,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pLfo:
parameter.hints = kParameterIsAutomatable;
parameter.name = "LFO";
parameter.symbol = "pfau_vcflfo";
parameter.symbol = "ch_vcflfo";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
@ -212,7 +213,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pKyb:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Kybd";
parameter.symbol = "pfau_vcfkey";
parameter.symbol = "ch_vcfkey";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 71.0f;
@ -222,7 +223,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pAttack:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Attack";
parameter.symbol = "pfau_attack";
parameter.symbol = "ch_attack";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 27.0f;
@ -232,7 +233,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pDecay:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Decay";
parameter.symbol = "pfau_decay";
parameter.symbol = "ch_decay";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 57.0f;
@ -242,7 +243,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pSustain:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Sustain";
parameter.symbol = "pfau_sustain";
parameter.symbol = "ch_sustain";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 57.0f;
@ -252,7 +253,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pRelease:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Release";
parameter.symbol = "pfau_release";
parameter.symbol = "ch_release";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 48.0f;
@ -262,7 +263,7 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pEnvGate:
parameter.hints = kParameterIsAutomatable | kParameterIsInteger; // | kParameterIsBoolean;
parameter.name = "Env-Gate";
parameter.symbol = "pfau_envgate";
parameter.symbol = "ch_envgate";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 1.0f;
parameter.ranges.def = 0.0f;
@ -282,62 +283,25 @@ void Peacock::initParameter(uint32_t index, Parameter& parameter) {
case pVCALevel:
parameter.hints = kParameterIsAutomatable;
parameter.name = "VCA Level";
parameter.symbol = "pfau_vcalevel";
parameter.symbol = "ch_vcalevel";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 40.0f;
parameter.midiCC = 26;
break;
case pChorusMode:
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.name = "Chorus";
parameter.symbol = "pfau_chorus";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 2.0f;
parameter.ranges.def = 0.0f;
parameter.midiCC = 93;
parameter.enumValues.count = 3;
parameter.enumValues.restrictedMode = true;
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[3];
enumValues[0].value = 0.0f;
enumValues[0].label = "Off";
enumValues[1].value = 1.0f;
enumValues[1].label = "Slow";
enumValues[2].value = 2.0f;
enumValues[2].label = "Fast";
parameter.enumValues.values = enumValues;
}
break;
case pVcoBend:
parameter.hints = kParameterIsAutomatable;
parameter.name = "VCO Bend";
parameter.symbol = "pfau_vcobend";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 12.0f;
parameter.ranges.def = 4.0f;
break;
case pVcfBend:
parameter.hints = kParameterIsAutomatable;
parameter.name = "VCF Bend";
parameter.symbol = "pfau_vcfbend";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 42.0f;
parameter.ranges.def = 4.0f;
break;
case pModDepth:
parameter.hints = kParameterIsAutomatable;
parameter.name = "Mod Depth";
parameter.symbol = "pfau_moddepth";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 4.0f;
parameter.ranges.def = 0.5f;
break;
/*
case pModWheel:
parameter.hints = kParameterIsAutomatable | kParameterIsHidden;
parameter.name = "Mod wheel";
parameter.symbol = "ch_modwheel";
parameter.ranges.min = 0.0f;
parameter.ranges.max = 127.0f;
parameter.ranges.def = 0.0f;
parameter.midiCC = 1;
break;
*/
}
// chorus, porta, bend range, key mode still to do
}
void Peacock::setParameterValue(uint32_t index, float value) {
@ -357,7 +321,7 @@ void Peacock::setParameterValue(uint32_t index, float value) {
m->patchRam.vcoLfo = value;
break;
case pPWMDepth:
m->patchRam.pwmLfo = value;
m->patchRam.pwmLfo = value / 1.27;
break;
case pSubLevel:
m->patchRam.sub = value;
@ -415,8 +379,9 @@ void Peacock::setParameterValue(uint32_t index, float value) {
m->patchRam.switch1 |= (value >= 0.5) << 4;
break;
case pChorusMode:
case pChorus:
m->patchRam.switch1 &= 0x9f;
switch ((int)value) {
case 0:
m->patchRam.switch1 |= 0x60; // both off
@ -450,15 +415,10 @@ void Peacock::setParameterValue(uint32_t index, float value) {
m->patchRam.switch2 &= 0xe7;
m->patchRam.switch2 |= (3 - (int)value) << 3;
break;
case pVcoBend:
m->vcoBendDepth = value;
break;
case pVcfBend:
m->vcfBendDepth = value / 2.66f;
break;
case pModDepth:
m->modDepth = value;
break;
/*
case pModWheel:
//s.ff64 = (int)value << 1;
break;*/
}
}
@ -487,7 +447,7 @@ float Peacock::getParameterValue(uint32_t index) const {
return m->patchRam.vcoLfo;
break;
case pPWMDepth:
return m->patchRam.pwmLfo;
return m->patchRam.pwmLfo * 1.27f;
break;
case pPWMMode:
@ -546,7 +506,8 @@ float Peacock::getParameterValue(uint32_t index) const {
case pVCALevel:
return m->patchRam.vca;
break;
case pChorusMode:
case pChorus:
switch (m->patchRam.switch1 & 0x60) {
case 0x60:
return 0;
@ -557,16 +518,8 @@ float Peacock::getParameterValue(uint32_t index) const {
default:
break;
}
break;
case pVcoBend:
return m->vcoBendDepth;
break;
case pVcfBend:
return m->vcfBendDepth * 2.66f;
break;
case pModDepth:
return m->modDepth;
break;
}
return 0;
}

View File

@ -28,12 +28,10 @@ Peacock::Peacock() : Plugin(parameterCount, 0, 0) {
sampleRate = getSampleRate();
bufferSize = getBufferSize();
chorus = new Chorus();
m = new Module();
ic1 = new Assigner;
ic1->voice = voice;
ic1->m = m;
m->chorus = chorus;
}
@ -71,27 +69,27 @@ void Peacock::run(const float**, float** outputs, uint32_t frames, const MidiEve
memset(outputs[0], 0, frames * sizeof(float));
memset(outputs[1], 0, frames * sizeof(float));
m->genNoise();
// if there were any events that happen between now and the end of this block, process them
lastEvent = 0;
m->bufPtr = 0; // reset the output buffer pointer
m->bufPtr = 0;
runMidi(midiEvents, midiEventCount, blockLeft);
while (framePos < frames) {
if (blockLeft == 0) {
// no more samples to calculate in this update period
blockLeft = sampleRate / 233.5; // update rate in Hz, measured
blockLeft = sampleRate / 238; // update rate in Hz
runMidi(midiEvents, midiEventCount, framePos + blockLeft);
m->run(voice, blockLeft);
}
// how many frames to do? Are we about to run off an update block
sizeThisTime = (framesLeft < blockLeft) ? framesLeft : blockLeft;
m->run(voice, sizeThisTime);
// now run all the voices for this chunk of samples
for (uint32_t i = 0; i < NUM_VOICES; i++) {
voice[i].run(m, outputs[0], framePos, sizeThisTime);
voice[i].run(m, outputs[0] + framePos, sizeThisTime);
}
framePos += sizeThisTime;
@ -100,7 +98,7 @@ void Peacock::run(const float**, float** outputs, uint32_t frames, const MidiEve
}
// now we've assembled a full chunk of audio
// memcpy(outputs[0], m->vcaBuf, sizeof(float)* frames);
//memcpy(outputs[0], m->vcaBuf, sizeof(float)* frames);
chorus->run(outputs[0], outputs, frames);
}

View File

@ -89,19 +89,19 @@ uint16_t lfoDelayTable[8] = {
0xffff, 0x0419, 0x020c, 0x015e, 0x0100, 0x0100, 0x0100, 0x0100};
float pitchTable[104] = {
8.123, 8.607, 9.122, 9.664, 10.240, 10.850, 11.497, 12.183,
12.908, 13.678, 14.492, 15.355, 16.268, 17.236, 18.265, 19.351,
20.504, 21.723, 23.019, 24.389, 25.841, 27.382, 29.011, 30.733,
32.561, 34.497, 36.555, 38.730, 41.034, 43.474, 46.066, 48.804,
51.712, 54.795, 58.052, 61.493, 65.147, 69.023, 73.142, 77.495,
82.102, 86.987, 92.166, 97.637, 103.455, 109.625, 116.144, 123.001,
130.310, 138.083, 146.327, 155.039, 164.258, 174.034, 184.366, 195.312,
206.954, 219.298, 232.342, 246.063, 260.688, 276.243, 292.740, 310.174,
328.515, 348.189, 368.732, 390.625, 413.907, 438.596, 464.684, 492.126,
521.376, 552.486, 585.480, 620.347, 657.030, 696.379, 737.463, 781.250,
827.815, 877.193, 929.368, 984.252, 1043.841, 1106.195, 1170.960, 1240.695,
1315.789, 1392.758, 1474.926, 1562.500, 1655.629, 1754.386, 1858.736, 1968.504,
2083.333, 2212.389, 2347.418, 2487.562, 2631.579, 2793.296, 2958.580, 3125.000,
32.494, 34.430, 36.486, 38.658, 40.962, 43.399, 45.990, 48.731,
51.633, 54.711, 57.969, 61.419, 65.072, 68.944, 73.059, 77.405,
82.014, 86.892, 92.077, 97.556, 103.365, 109.529, 116.043, 122.933,
130.242, 137.988, 146.220, 154.919, 164.136, 173.898, 184.264, 195.217,
206.847, 219.178, 232.207, 245.972, 260.586, 276.091, 292.569, 309.981,
328.407, 347.947, 368.664, 390.549, 413.822, 438.500, 464.576, 492.005,
521.241, 552.334, 585.309, 620.155, 657.030, 696.136, 737.463, 781.250,
827.815, 877.193, 929.368, 984.252, 1042.753, 1104.972, 1170.960, 1240.695,
1314.060, 1392.758, 1474.926, 1562.500, 1655.629, 1754.386, 1858.736, 1968.504,
2085.506, 2209.945, 2341.920, 2481.390, 2628.121, 2785.515, 2949.853, 3125.000,
3311.258, 3508.772, 3717.472, 3937.008, 4175.365, 4424.779, 4683.841, 4962.779,
5263.158, 5571.031, 5899.705, 6250.000, 6622.517, 7017.544, 7434.944, 7874.016,
8333.333, 8849.558, 9389.671, 9950.249, 10526.316, 11173.184, 11834.320, 12500.000
};
#endif

View File

@ -46,59 +46,56 @@ DistrhoUIPeacock::DistrhoUIPeacock() : UI(Art::backgroundWidth, Art::backgroundH
fImgLedOn(Art::ledOnData, Art::ledWidth, Art::ledHeight, kImageFormatRGBA)
{
Image orangeSlider(Art::orangeData, Art::sliderWidth, Art::sliderHeight, kImageFormatRGBA);
Image greenSlider(Art::greenData, Art::sliderWidth, Art::sliderHeight, kImageFormatRGBA);
Image blueSlider(Art::blueData, Art::sliderWidth, Art::sliderHeight, kImageFormatRGBA);
Image whiteSlider(Art::whiteData, Art::sliderWidth, Art::sliderHeight, kImageFormatRGBA);
Image whiteSlider(Art::whiteData, Art::sliderWidth, Art::sliderHeight, kImageFormatRGBA);
Image switchSlider(Art::switchData, Art::switchWidth, Art::switchHeight, kImageFormatRGBA);
xSliderLFORate = new ImageSlider(this, orangeSlider);
xSliderLFORate = new ImageSlider(this, whiteSlider);
prepSlider(xSliderLFORate, pLFORate, 46, 72);
xSliderLFORate->setCallback(this);
xSliderLFODelay = new ImageSlider(this, orangeSlider);
xSliderLFODelay = new ImageSlider(this, whiteSlider);
prepSlider(xSliderLFODelay, pLFODelay, 84, 72);
xSliderLFODelay->setCallback(this);
xSliderLFODepth = new ImageSlider(this, greenSlider);
xSliderLFODepth = new ImageSlider(this, whiteSlider);
prepSlider(xSliderLFODepth, pLFODepth, 290, 72);
xSliderLFODepth->setCallback(this);
xSliderPWMDepth = new ImageSlider(this, greenSlider);
xSliderPWMDepth = new ImageSlider(this, whiteSlider);
prepSlider(xSliderPWMDepth, pPWMDepth, 329, 72);
xSliderPWMDepth->setCallback(this);
xSliderSubLevel = new ImageSlider(this, greenSlider);
xSliderSubLevel = new ImageSlider(this, whiteSlider);
prepSlider(xSliderSubLevel, pSubLevel, 510, 72);
xSliderSubLevel->setCallback(this);
xSliderNoiseLevel = new ImageSlider(this, greenSlider);
xSliderNoiseLevel = new ImageSlider(this, whiteSlider);
prepSlider(xSliderNoiseLevel, pNoiseLevel, 551, 72);
xSliderNoiseLevel->setCallback(this);
xSliderHPF = new ImageSlider(this, blueSlider);
xSliderHPF = new ImageSlider(this, whiteSlider);
prepSlider(xSliderHPF, pHPF, 618, 72);
xSliderHPF->setStep(1);
xSliderHPF->setRange(0, 3);
xSliderHPF->setCallback(this);
xSliderCutoff = new ImageSlider(this, blueSlider);
xSliderCutoff = new ImageSlider(this, whiteSlider);
prepSlider(xSliderCutoff, pCutoff, 26, 261);
xSliderCutoff->setCallback(this);
xSliderRes = new ImageSlider(this, blueSlider);
xSliderRes = new ImageSlider(this, whiteSlider);
prepSlider(xSliderRes, pRes, 65, 261);
xSliderRes->setCallback(this);
xSliderEnv = new ImageSlider(this, blueSlider);
xSliderEnv = new ImageSlider(this, whiteSlider);
prepSlider(xSliderEnv, pEnv, 149, 261);
xSliderEnv->setCallback(this);
xSliderLfo = new ImageSlider(this, blueSlider);
xSliderLfo = new ImageSlider(this, whiteSlider);
prepSlider(xSliderLfo, pLfo, 189, 261);
xSliderLfo->setCallback(this);
xSliderKyb = new ImageSlider(this, blueSlider);
xSliderKyb = new ImageSlider(this, whiteSlider);
prepSlider(xSliderKyb, pKyb, 228, 261);
xSliderKyb->setCallback(this);
@ -134,47 +131,47 @@ DistrhoUIPeacock::DistrhoUIPeacock() : UI(Art::backgroundWidth, Art::backgroundH
prepSwitch(xSwitchVCA, pEnvGate, 283, 292);
xSwitchVCA->setCallback(this);
xBtn16ft = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtn16ft = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtn16ft->setAbsolutePos(149, 104);
xBtn16ft->setId(btn16);
xBtn16ft->setCallback(this);
xBtn8ft = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtn8ft = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtn8ft->setAbsolutePos(190, 104);
xBtn8ft->setId(btn8);
xBtn8ft->setCallback(this);
xBtn4ft = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtn4ft = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtn4ft->setAbsolutePos(231, 104);
xBtn4ft->setId(btn4);
xBtn4ft->setCallback(this);
// waveform
xBtnPls = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtnPls = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtnPls->setAbsolutePos(414, 104);
xBtnPls->setId(btnPls);
xBtnPls->setCallback(this);
xBtnSaw = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtnSaw = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtnSaw->setAbsolutePos(455, 104);
xBtnSaw->setId(btnSaw);
xBtnSaw->setCallback(this);
// Chorus
xBtnCh0 = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtnCh0 = new ImageButton(this, Image(Art::whiteBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::whiteBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtnCh0->setAbsolutePos(562, 293);
xBtnCh0->setId(btnCh0);
xBtnCh0->setCallback(this);
xBtnCh1 = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtnCh1 = new ImageButton(this, Image(Art::orngBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtnCh1->setAbsolutePos(603, 293);
xBtnCh1->setId(btnCh1);
xBtnCh1->setCallback(this);
xBtnCh2 = new ImageButton(this, Image(Art::orngBtnUp, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::orngBtnWidth, Art::orngBtnHeight, kImageFormatRGBA));
xBtnCh2 = new ImageButton(this, Image(Art::orngBtnUp, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA),
Image(Art::orngBtnDn, Art::whiteBtnWidth, Art::whiteBtnHeight, kImageFormatRGBA));
xBtnCh2->setAbsolutePos(644, 293);
xBtnCh2->setId(btnCh2);
xBtnCh2->setCallback(this);
@ -258,20 +255,17 @@ void DistrhoUIPeacock::parameterChanged(uint32_t index, float value) {
sw1 &= 0xf8; // mask
if (value > 2) value = 2;
sw1 |= (1 << (int)value);
repaint();
break;
case pSqr:
sw1 &= 0xf7;
sw1 |= ((value >= 0.5)) << 3;
repaint();
break;
case pSaw:
sw1 &= 0xef;
sw1 |= (value > 0.5) << 4;
repaint();
break;
case pChorusMode:
case pChorus:
sw1 &= 0x9f;
// 60, 40, 00
switch ((int)value) {
@ -285,8 +279,6 @@ void DistrhoUIPeacock::parameterChanged(uint32_t index, float value) {
sw1 |= 0x00;
break;
}
repaint();
break;
}
}
@ -330,21 +322,20 @@ void DistrhoUIPeacock::imageButtonClicked(ImageButton* imgBtn, int) {
break;
case btnCh0:
sw1 = (sw1 & 0x9f) | 0x20;
setParameterValue(pChorusMode, 0);
setParameterValue(pChorus, 0);
break;
case btnCh1:
sw1 = (sw1 & 0x9f) | 0x40;
setParameterValue(pChorusMode, 1);
setParameterValue(pChorus, 1);
break;
case btnCh2:
sw1 = (sw1 & 0x9f);
setParameterValue(pChorusMode, 2);
setParameterValue(pChorus, 2);
break;
default:
break;
}
repaint();
}
void DistrhoUIPeacock::onDisplay() {

View File

@ -40,9 +40,11 @@ Voice::Voice() {
}
void Voice::on(uint8_t midiNote) {
while (midiNote < 24) midiNote += 12; // limit lowest note to C1
while (midiNote > 108) midiNote -= 12; // limit highest note to C8
note = midiNote;
// omega = 261.63 * powf(2, (note - 60) / 12.0f) / 48000.0f;
if (midiNote > 24)
note = midiNote - 24;
else
note = 24;
envPhase = 1;
}
@ -50,19 +52,17 @@ void Voice::off() {
envPhase = 0;
}
void Voice::run(Module* m, float* buffer, uint32_t framePos, uint32_t samples) {
void Voice::run(Module* m, float* buffer, uint32_t samples) {
// carry out per-voice calculations for each block of samples
float out, t, fb;
// FIXME incorrect
// calculate cutoff frequency
float cut = 261.0f * (powf(2, (vcfCut - 0x1880) / 1143.0f)); // FIXME explain magic numbers
cut = M_PI * cut / sampleRate;
cut = cut / (1 + cut); // correct tuning warp
if (cut > 0.7) cut = 0.7;
float cut = 248.0f * (powf(2, (vcfCut - 0x1880) / 1143.0f));
cut = 0.25 * 6.2832 * cut / 48000.0f; // FIXME hardcoded values
cut = cut / (1 + cut); // correct tuning warp
float r = 6 * m->res;
float amp = vcaEnv / 32768.0f;
float amp = vcaEnv / 4096.0f;
for (uint32_t i = 0; i < samples; i++) {
out = delay;
@ -94,31 +94,36 @@ void Voice::run(Module* m, float* buffer, uint32_t framePos, uint32_t samples) {
}
}
// FIXME DC offset removal
delay += m->saw * (1 - (2 * theta));
delay += m->square * ((pulseStage ? -1.f : 1.f) - m->pwmBuf[i] + 0.5);
delay += m->subBuf[i] * subosc;
out += m->noise * m->noiseBuf[i + framePos];
delay += m->subBuf[i] * subosc ;
out += m->noise * (0.8 - 1.6 * (rand() & 0xffff) / 65536.0);
out *= 0.5;
// same time constant for both VCF and VCF RC circuits
vcfRC = (cut - vcfRC) * m->vcaTC + vcfRC;
for (uint8_t ovs = 0; ovs < 2; ovs++) {
fb = y3;
for (uint8_t ovs = 0; ovs < 4; ovs++) {
fb = b4;
// hard clip
fb = ((out * 0.5) - fb) * r;
if (fb > 6) fb = 6;
if (fb < -6) fb = -6;
fb = ((out * 0.5) - fb) * m->res;
if (fb > 4) fb = 4;
if (fb < -4) fb = -4;
// fb = 1.5 * fb - 0.5 * fb * fb * fb;
//
y0 = ((out + fb - y0) * vcfRC) + y0;
y1 = ((y0 - y1) * vcfRC) + y1;
y2 = ((y1 - y2) * vcfRC) + y2;
y3 = ((y2 - y3) * vcfRC) + y3;
b1 = ((out + fb - b1) * vcfRC) + b1;
b2 = ((b1 - b2) * vcfRC) + b2;
b3 = ((b2 - b3) * vcfRC) + b3;
b4 = ((b3 - b4) * vcfRC) + b4;
}
vcaRC = (amp - vcaRC) * m->vcaTC + vcaRC;
buffer[framePos + i] += m->vcaBuf[i] * vcaRC * y3;
vcaRC = (amp - vcaRC) * m->vcaTC + vcaRC;
buffer[i] += 0.09367 * m->vcaBuf[i] * vcaRC * b4;
lastpw = m->pwmBuf[i];
}
// buffer[0] += 1; // buzzing noise to test
// buffer[0] += 1;
}

446
plugin/whitebutton.cpp Normal file
View File

@ -0,0 +1,446 @@
/*
Peacock-8 VA polysynth
Copyright 2025 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.
*/
#include "artwork.hpp"
static const char tempWhiteUp[] = {
"VOF\377ri^\377|rf\377xnb\377|rf\377yoc\377{qe\377xnb\377|rf\377zpd\377}s"
"g\377yoc\377xnb\377|rf\377{qe\377\177th\377xnb\377zpd\377xnb\377yoc\377|"
"rf\377{qe\377{qe\377{qe\377yoc\377xnb\377}sg\377xnb\377xnb\377{qe\377|rf"
"\377xnb\377vl`\377yoc\377\177th\377}sg\377{qe\377xnb\377uk_\377\003\003\003\000\003"
"\003\003\000\205{m\377\301\273\263\377\264\255\244\377\264\255\244\377\263\254"
"\243\377\264\255\244\377\264\255\244\377\263\253\242\377\263\254\243\377"
"\263\254\243\377\264\255\244\377\263\254\243\377\263\254\243\377\265\256"
"\245\377\266\257\246\377\264\255\244\377\263\253\242\377\264\255\244\377"
"\264\255\244\377\262\252\240\377\263\254\243\377\264\255\244\377\264\255"
"\244\377\265\256\245\377\264\255\244\377\262\252\240\377\264\255\244\377"
"\263\253\242\377\264\255\244\377\263\254\243\377\263\254\243\377\264\255"
"\244\377\264\255\244\377\264\255\244\377\262\252\240\377\264\255\244\377"
"\264\255\244\377\226\213~\377\214\201r\377uk_\062\003\003\003\000\202xj\377\266\257"
"\246\377\241\230\215\377\240\226\212\377\241\230\215\377\240\226\212\377"
"\243\232\217\377\241\230\215\377\240\226\212\377\241\230\215\377\244\233"
"\220\377\237\225\211\377\241\230\215\377\241\230\215\377\240\226\212\377"
"\237\225\211\377\241\230\215\377\235\223\207\377\241\227\214\377\240\226"
"\212\377\241\227\214\377\237\225\211\377\242\231\216\377\241\230\215\377"
"\240\226\212\377\237\225\211\377\241\230\215\377\241\230\215\377\241\230"
"\215\377\241\230\215\377\240\226\212\377\237\225\211\377\240\226\212\377"
"\241\230\215\377\243\232\217\377\240\226\212\377\241\227\214\377\233\221"
"\205\377\220\206x\377\\UL\374\062.)\226\202xj\377\263\253\242\377\233\221"
"\205\377\225\213}\377\225\213}\377\232\220\204\377\223\211{\377\223\211{"
"\377\234\222\206\377\222\210z\377\226\213~\377\226\213~\377\224\212|\377"
"\230\216\202\377\232\220\204\377\230\215\201\377\224\212|\377\230\215\201"
"\377\223\211{\377\232\220\204\377\226\213~\377\223\211{\377\227\214\177\377"
"\222\210z\377\232\220\204\377\233\221\205\377\231\217\203\377\220\206x\377"
"\234\222\206\377\224\212|\377\230\216\202\377\224\212|\377\224\212|\377\230"
"\216\202\377\224\212|\377\224\212|\377\233\221\205\377\230\215\201\377\202"
"xj\377TMD\377\062.)Q\200uh\377\262\252\240\377\224\212|\377\230\216\202\377"
"\217\205w\377\224\212|\377\226\213~\377\227\214\177\377\230\216\202\377\230"
"\216\202\377\223\211{\377\230\215\201\377\230\216\202\377\223\211{\377\230"
"\216\202\377\220\206x\377\225\213}\377\224\212|\377\224\212|\377\230\216"
"\202\377\223\211{\377\230\215\201\377\232\220\204\377\231\217\203\377\221"
"\207y\377\225\213}\377\230\216\202\377\223\211{\377\225\213}\377\227\214"
"\177\377\223\211{\377\230\216\202\377\227\214\177\377\227\214\177\377\225"
"\213}\377\222\210z\377\227\214\177\377\230\216\202\377}sg\377QKC\377*&\""
"\273\201vi\377\264\255\244\377\234\222\206\377\230\215\201\377\224\212|\377"
"\232\220\204\377\226\213~\377\227\214\177\377\231\217\203\377\222\210z\377"
"\223\211{\377\226\213~\377\230\216\202\377\217\205w\377\224\212|\377\232"
"\220\204\377\232\220\204\377\230\215\201\377\224\212|\377\225\213}\377\222"
"\210z\377\230\216\202\377\222\210z\377\230\216\202\377\227\214\177\377\230"
"\216\202\377\232\220\204\377\226\213~\377\226\213~\377\225\213}\377\221\207"
"y\377\230\216\202\377\226\213~\377\220\206x\377\221\207y\377\232\220\204"
"\377\224\212|\377\230\215\201\377\200uh\377OIA\377*&\"\350\202xj\377\263"
"\253\242\377\234\222\206\377\227\214\177\377\220\206x\377\224\212|\377\233"
"\221\205\377\230\215\201\377\230\215\201\377\231\217\203\377\233\221\205"
"\377\225\213}\377\224\212|\377\233\221\205\377\230\216\202\377\227\214\177"
"\377\230\215\201\377\223\211{\377\226\213~\377\226\213~\377\230\215\201\377"
"\232\220\204\377\231\217\203\377\230\215\201\377\227\214\177\377\227\214"
"\177\377\230\216\202\377\230\216\202\377\226\213~\377\233\221\205\377\226"
"\213~\377\226\213~\377\231\217\203\377\233\221\205\377\230\215\201\377\217"
"\205w\377\234\222\206\377\233\221\205\377}sg\377PJB\377*&\"\350\202xj\377"
"\263\254\243\377\237\225\211\377\226\213~\377\222\210z\377\227\214\177\377"
"\230\216\202\377\230\215\201\377\234\222\206\377\231\217\203\377\227\214"
"\177\377\222\210z\377\223\211{\377\222\210z\377\227\214\177\377\230\215\201"
"\377\226\213~\377\230\215\201\377\223\211{\377\224\212|\377\226\213~\377"
"\223\211{\377\226\213~\377\224\212|\377\222\210z\377\230\215\201\377\223"
"\211{\377\230\215\201\377\233\221\205\377\231\217\203\377\227\214\177\377"
"\220\206x\377\233\221\205\377\233\221\205\377\227\214\177\377\230\216\202"
"\377\233\221\205\377\222\210z\377\206|n\377OIA\377*&\"\350\202xj\377\263"
"\253\242\377\235\223\207\377\224\212|\377\221\207y\377\222\210z\377\224\212"
"|\377\220\206x\377\223\211{\377\232\220\204\377\231\217\203\377\230\215\201"
"\377\231\217\203\377\225\213}\377\220\206x\377\232\220\204\377\227\214\177"
"\377\220\206x\377\224\212|\377\223\211{\377\233\221\205\377\227\214\177\377"
"\224\212|\377\226\213~\377\226\213~\377\225\213}\377\227\214\177\377\230"
"\215\201\377\223\211{\377\232\220\204\377\225\213}\377\224\212|\377\230\215"
"\201\377\230\215\201\377\230\215\201\377\226\213~\377\230\215\201\377\230"
"\215\201\377\201vi\377TMD\377*&\"\350\203yk\377\263\253\242\377\232\220\204"
"\377\233\221\205\377\231\217\203\377\230\216\202\377\223\211{\377\230\215"
"\201\377\226\213~\377\224\212|\377\227\214\177\377\222\210z\377\230\215\201"
"\377\230\216\202\377\226\213~\377\224\212|\377\230\215\201\377\224\212|\377"
"\222\210z\377\230\215\201\377\224\212|\377\233\221\205\377\230\216\202\377"
"\224\212|\377\222\210z\377\230\216\202\377\234\222\206\377\226\213~\377\225"
"\213}\377\227\214\177\377\230\216\202\377\223\211{\377\227\214\177\377\226"
"\213~\377\232\220\204\377\232\220\204\377\224\212|\377\230\215\201\377\202"
"xj\377QKC\377*&\"\350\202xj\377\264\255\244\377\230\215\201\377\217\205w"
"\377\224\212|\377\224\212|\377\226\213~\377\230\216\202\377\226\213~\377"
"\223\211{\377\226\213~\377\227\214\177\377\232\220\204\377\226\213~\377\227"
"\214\177\377\223\211{\377\222\210z\377\232\220\204\377\226\213~\377\220\206"
"x\377\221\207y\377\222\210z\377\233\221\205\377\230\215\201\377\227\214\177"
"\377\222\210z\377\232\220\204\377\226\213~\377\234\222\206\377\222\210z\377"
"\231\217\203\377\234\222\206\377\230\215\201\377\230\216\202\377\222\210"
"z\377\226\213~\377\226\213~\377\227\214\177\377\201vi\377QKC\377*&\"\350"
"\202xj\377\263\253\242\377\224\212|\377\226\213~\377\232\220\204\377\224"
"\212|\377\226\213~\377\220\206x\377\230\216\202\377\221\207y\377\222\210"
"z\377\223\211{\377\227\214\177\377\231\217\203\377\230\215\201\377\223\211"
"{\377\232\220\204\377\224\212|\377\230\216\202\377\230\215\201\377\230\216"
"\202\377\223\211{\377\230\215\201\377\231\217\203\377\221\207y\377\223\211"
"{\377\225\213}\377\221\207y\377\222\210z\377\230\215\201\377\231\217\203"
"\377\226\213~\377\232\220\204\377\231\217\203\377\226\213~\377\233\221\205"
"\377\227\214\177\377\223\211{\377\212\177q\377QKC\377*&\"\350\201vi\377\262"
"\252\240\377\231\217\203\377\232\220\204\377\230\215\201\377\225\213}\377"
"\224\212|\377\230\216\202\377\226\213~\377\223\211{\377\226\213~\377\230"
"\215\201\377\226\213~\377\221\207y\377\217\205w\377\231\217\203\377\221\207"
"y\377\230\215\201\377\227\214\177\377\233\221\205\377\220\206x\377\224\212"
"|\377\227\214\177\377\224\212|\377\230\215\201\377\227\214\177\377\232\220"
"\204\377\224\212|\377\223\211{\377\230\215\201\377\223\211{\377\226\213~"
"\377\220\206x\377\227\214\177\377\226\213~\377\232\220\204\377\230\215\201"
"\377\230\215\201\377\205{m\377VOF\377*&\"\350\177th\377\260\250\236\377\224"
"\212|\377\224\212|\377\223\211{\377\222\210z\377\223\211{\377\223\211{\377"
"\232\220\204\377\227\214\177\377\226\213~\377\227\214\177\377\230\215\201"
"\377\230\215\201\377\227\214\177\377\227\214\177\377\233\221\205\377\230"
"\216\202\377\223\211{\377\222\210z\377\225\213}\377\223\211{\377\220\206"
"x\377\224\212|\377\222\210z\377\234\222\206\377\230\215\201\377\223\211{"
"\377\222\210z\377\234\222\206\377\223\211{\377\224\212|\377\230\215\201\377"
"\221\207y\377\225\213}\377\221\207y\377\223\211{\377\230\216\202\377\205"
"{m\377SLD\377*&\"\350\200uh\377\261\251\237\377\226\213~\377\224\212|\377"
"\224\212|\377\230\215\201\377\230\215\201\377\223\211{\377\230\215\201\377"
"\227\214\177\377\230\216\202\377\231\217\203\377\223\211{\377\234\222\206"
"\377\230\215\201\377\230\215\201\377\220\206x\377\230\216\202\377\224\212"
"|\377\227\214\177\377\222\210z\377\222\210z\377\230\215\201\377\226\213~"
"\377\230\215\201\377\230\215\201\377\223\211{\377\230\215\201\377\230\215"
"\201\377\233\221\205\377\234\222\206\377\230\216\202\377\230\216\202\377"
"\227\214\177\377\230\216\202\377\220\206x\377\223\211{\377\230\216\202\377"
"}sg\377SLD\377*&\"\350\177th\377\261\251\237\377\231\217\203\377\221\207"
"y\377\227\214\177\377\224\212|\377\225\213}\377\223\211{\377\232\220\204"
"\377\224\212|\377\231\217\203\377\232\220\204\377\230\216\202\377\230\215"
"\201\377\227\214\177\377\230\216\202\377\230\215\201\377\227\214\177\377"
"\225\213}\377\231\217\203\377\223\211{\377\222\210z\377\222\210z\377\224"
"\212|\377\224\212|\377\224\212|\377\230\215\201\377\230\215\201\377\227\214"
"\177\377\226\213~\377\230\215\201\377\225\213}\377\222\210z\377\230\215\201"
"\377\224\212|\377\223\211{\377\230\215\201\377\230\215\201\377\203yk\377"
"OIA\377*&\"\350\200uh\377\257\247\235\377\233\221\205\377\232\220\204\377"
"\222\210z\377\230\216\202\377\224\212|\377\230\215\201\377\226\213~\377\224"
"\212|\377\222\210z\377\230\215\201\377\230\216\202\377\227\214\177\377\230"
"\216\202\377\230\215\201\377\221\207y\377\223\211{\377\230\215\201\377\224"
"\212|\377\223\211{\377\227\214\177\377\230\215\201\377\230\215\201\377\227"
"\214\177\377\222\210z\377\227\214\177\377\230\215\201\377\224\212|\377\233"
"\221\205\377\226\213~\377\223\211{\377\230\216\202\377\230\215\201\377\232"
"\220\204\377\225\213}\377\233\221\205\377\223\211{\377\205{m\377QKC\377*"
"&\"\350\177th\377\262\252\240\377\225\213}\377\221\207y\377\230\215\201\377"
"\224\212|\377\231\217\203\377\231\217\203\377\224\212|\377\230\215\201\377"
"\231\217\203\377\224\212|\377\230\215\201\377\232\220\204\377\227\214\177"
"\377\230\216\202\377\230\215\201\377\227\214\177\377\231\217\203\377\227"
"\214\177\377\227\214\177\377\221\207y\377\232\220\204\377\230\215\201\377"
"\226\213~\377\223\211{\377\226\213~\377\227\214\177\377\227\214\177\377\226"
"\213~\377\227\214\177\377\230\216\202\377\225\213}\377\225\213}\377\223\211"
"{\377\232\220\204\377\227\214\177\377\223\211{\377\205{m\377SLD\377*&\"\350"
"\177th\377\261\251\237\377\230\216\202\377\226\213~\377\230\215\201\377\226"
"\213~\377\217\205w\377\226\213~\377\230\215\201\377\230\215\201\377\224\212"
"|\377\221\207y\377\232\220\204\377\230\215\201\377\223\211{\377\230\215\201"
"\377\231\217\203\377\230\216\202\377\231\217\203\377\227\214\177\377\223"
"\211{\377\227\214\177\377\230\215\201\377\226\213~\377\223\211{\377\230\216"
"\202\377\230\215\201\377\232\220\204\377\227\214\177\377\230\215\201\377"
"\224\212|\377\230\215\201\377\226\213~\377\231\217\203\377\225\213}\377\231"
"\217\203\377\222\210z\377\231\217\203\377\206|n\377SLD\377*&\"\350\177th"
"\377\264\255\244\377\233\221\205\377\227\214\177\377\231\217\203\377\222"
"\210z\377\224\212|\377\226\213~\377\226\213~\377\226\213~\377\230\215\201"
"\377\224\212|\377\230\216\202\377\233\221\205\377\226\213~\377\223\211{\377"
"\227\214\177\377\221\207y\377\232\220\204\377\226\213~\377\230\216\202\377"
"\230\215\201\377\226\213~\377\232\220\204\377\222\210z\377\223\211{\377\230"
"\215\201\377\224\212|\377\227\214\177\377\224\212|\377\227\214\177\377\227"
"\214\177\377\226\213~\377\224\212|\377\226\213~\377\227\214\177\377\230\215"
"\201\377\231\217\203\377\205{m\377TMD\377*&\"\350\201vi\377\263\253\242\377"
"\222\210z\377\223\211{\377\227\214\177\377\220\206x\377\230\215\201\377\226"
"\213~\377\234\222\206\377\226\213~\377\233\221\205\377\225\213}\377\227\214"
"\177\377\224\212|\377\224\212|\377\223\211{\377\233\221\205\377\227\214\177"
"\377\225\213}\377\223\211{\377\227\214\177\377\221\207y\377\223\211{\377"
"\230\215\201\377\230\216\202\377\230\215\201\377\227\214\177\377\217\205"
"w\377\226\213~\377\230\216\202\377\230\216\202\377\223\211{\377\226\213~"
"\377\221\207y\377\232\220\204\377\223\211{\377\231\217\203\377\230\216\202"
"\377\201vi\377SLD\377*&\"\350\177th\377\261\251\237\377\230\216\202\377\225"
"\213}\377\231\217\203\377\221\207y\377\232\220\204\377\230\215\201\377\224"
"\212|\377\234\222\206\377\224\212|\377\226\213~\377\230\216\202\377\223\211"
"{\377\230\215\201\377\220\206x\377\232\220\204\377\223\211{\377\225\213}"
"\377\224\212|\377\227\214\177\377\225\213}\377\231\217\203\377\223\211{\377"
"\234\222\206\377\223\211{\377\226\213~\377\230\215\201\377\230\216\202\377"
"\230\215\201\377\225\213}\377\224\212|\377\222\210z\377\223\211{\377\223"
"\211{\377\220\206x\377\226\213~\377\234\222\206\377\202xj\377PJB\377*&\""
"\350\200uh\377\261\251\237\377\234\222\206\377\230\215\201\377\230\215\201"
"\377\230\216\202\377\226\213~\377\226\213~\377\230\216\202\377\233\221\205"
"\377\232\220\204\377\231\217\203\377\227\214\177\377\227\214\177\377\226"
"\213~\377\223\211{\377\230\215\201\377\230\216\202\377\227\214\177\377\230"
"\216\202\377\232\220\204\377\231\217\203\377\232\220\204\377\220\206x\377"
"\234\222\206\377\221\207y\377\230\216\202\377\223\211{\377\221\207y\377\223"
"\211{\377\223\211{\377\231\217\203\377\220\206x\377\224\212|\377\230\215"
"\201\377\230\215\201\377\224\212|\377\232\220\204\377\202xj\377QKC\377*&"
"\"\350\202xj\377\261\251\237\377\226\213~\377\235\223\207\377\230\215\201"
"\377\230\216\202\377\223\211{\377\222\210z\377\230\215\201\377\222\210z\377"
"\230\215\201\377\231\217\203\377\223\211{\377\225\213}\377\223\211{\377\226"
"\213~\377\232\220\204\377\231\217\203\377\220\206x\377\230\216\202\377\221"
"\207y\377\226\213~\377\230\215\201\377\230\216\202\377\230\215\201\377\224"
"\212|\377\227\214\177\377\230\215\201\377\235\223\207\377\226\213~\377\226"
"\213~\377\231\217\203\377\227\214\177\377\220\206x\377\230\216\202\377\222"
"\210z\377\224\212|\377\233\221\205\377\201vi\377QKC\377*&\"\350\177th\377"
"\261\251\237\377\236\224\210\377\223\211{\377\230\215\201\377\230\215\201"
"\377\225\213}\377\227\214\177\377\225\213}\377\230\216\202\377\230\215\201"
"\377\223\211{\377\230\216\202\377\235\223\207\377\230\215\201\377\230\216"
"\202\377\230\216\202\377\231\217\203\377\223\211{\377\224\212|\377\226\213"
"~\377\230\215\201\377\232\220\204\377\230\215\201\377\230\216\202\377\226"
"\213~\377\222\210z\377\223\211{\377\231\217\203\377\232\220\204\377\230\216"
"\202\377\230\216\202\377\235\223\207\377\230\216\202\377\223\211{\377\223"
"\211{\377\230\216\202\377\231\217\203\377\203yk\377QKC\377*&\"\350\222\210"
"z\377\301\273\263\377\235\223\207\377\221\207y\377\233\221\205\377\232\220"
"\204\377\230\215\201\377\226\213~\377\230\215\201\377\233\221\205\377\223"
"\211{\377\224\212|\377\227\214\177\377\233\221\205\377\234\222\206\377\230"
"\215\201\377\232\220\204\377\232\220\204\377\227\214\177\377\230\216\202"
"\377\232\220\204\377\230\216\202\377\227\214\177\377\225\213}\377\233\221"
"\205\377\231\217\203\377\230\215\201\377\223\211{\377\233\221\205\377\230"
"\215\201\377\225\213}\377\230\215\201\377\230\215\201\377\230\216\202\377"
"\232\220\204\377\234\222\206\377\234\222\206\377\222\210z\377\204zl\377Q"
"KC\377*&\"\350WPG\377of[\377\177th\377tj_\377ri^\377tj_\377tj_\377of[\377"
"neZ\377jaV\377ri^\377of[\377lcX\377of[\377uk_\377\177th\377xnb\377xnb\377"
"{qe\377ri^\377of[\377of[\377tj_\377yoc\377zpd\377|rf\377yoc\377|rf\377zp"
"d\377}sg\377{qe\377|rf\377xnb\377yoc\377xnb\377\177th\377}sg\377uk_\377p"
"g\\\377SLD\377*&\"\350\237\225\211\025HB;\377@;\064\377PJB\377TMD\377QKC\377"
"PJB\377QKC\377PJB\377OIA\377OIA\377PJB\377OIA\377OIA\377OIA\377OIA\377OI"
"A\377OIA\377OIA\377MG?\377NH@\377NH@\377OIA\377NH@\377NH@\377MG?\377LF>\377"
"LF>\377MG?\377LF>\377MG?\377MG?\377MG?\377MG?\377MG?\377NH@\377MG?\377OI"
"A\377HB;\377=\070\062\377*&\"\350\003\003\003\000OIA\377\067\063-\377\066\062,\377C>\067"
"\377E@\071\377C>\067\377C>\067\377D?\070\377C>\067\377C>\067\377C>\067\377C>\067"
"\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377A<\065"
"\377B=\066\377B=\066\377C>\067\377B=\066\377B=\066\377A<\065\377A<\065\377A<\065"
"\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377B=\066"
"\377A<\065\377@;\064\377\060-(\377*&\"\362\003\003\003\000:\066\060\271\064\060*\377=\070"
"\062\377?:\063\377E@\071\377C>\067\377C>\067\377D?\070\377C>\067\377C>\067\377C>"
"\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>\067\377C>"
"\067\377A<\065\377B=\066\377B=\066\377C>\067\377B=\066\377B=\066\377A<\065\377A<"
"\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<\065\377A<"
"\065\377B=\066\377A<\065\377C>\067\377:\066\060\377*&\"\370",
};
static const char tempWhiteDn[] = {
"\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000"
"\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000"
"\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000"
"\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000"
"\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\003\003\003\000\060,'&\060,'\331\060,'\235\060,'\235"
"\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235"
"\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235"
"\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235"
"\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235\060,'\235"
"\060,'\235\060,'\235\003\003\003\000\003\003\003\000\003\003\003\000PIA\377LF>\377qh\\\377meZ\377q"
"h\\\377nfZ\377pg[\377ldY\377qh\\\377of[\377ri^\377nfZ\377meY\377qh\\\377"
"pg\\\377sj^\377meY\377of[\377ldY\377neZ\377qh\\\377pg\\\377pg[\377pg[\377"
"nfZ\377meY\377ri]\377meZ\377ldY\377pg[\377qh\\\377meY\377kcX\377neZ\377s"
"j^\377ri^\377pg[\377meY\377qh\\\360\003\003\003\000\003\003\003\000KF>\377?:\064\377f^S\377"
"mdY\377lcX\377mdY\377mdY\377lcX\377lcX\377lcX\377mdY\377lcX\377lcX\377ne"
"Z\377neZ\377mdY\377lcX\377mdY\377mdY\377kbX\377lcX\377mdY\377mdY\377neZ\377"
"mdY\377kbX\377mdY\377lcX\377mdY\377lcX\377lcX\377mdY\377mdY\377mdY\377kb"
"X\377mdY\377mdY\377XQH\375SMD\313\060,'+\060,'\000JD=\377g_T\377\223\210{\377"
"\222\207y\377\224\211|\377\222\207y\377\225\213~\377\224\211|\377\221\207"
"y\377\223\211{\377\226\214\177\377\221\206x\377\223\211{\377\224\211|\377"
"\222\207y\377\221\206x\377\224\211|\377\220\205w\377\223\210{\377\222\207"
"y\377\223\210{\377\221\206x\377\225\212}\377\224\211|\377\222\207y\377\221"
"\206x\377\224\211|\377\223\211{\377\224\211|\377\224\211|\377\222\207y\377"
"\221\206x\377\222\207y\377\224\211|\377\225\213~\377\222\207y\377\223\210"
"{\377\215\202t\377\202xj\360\060,'\036\060,'\000JD=\377sj^\377\227\215\200\377"
"\220\206x\377\220\206x\377\226\214\177\377\217\204v\377\217\204v\377\230"
"\216\201\377\216\204u\377\221\207y\377\221\207y\377\217\205w\377\224\212"
"|\377\226\214\177\377\223\211{\377\220\205w\377\223\211{\377\217\204v\377"
"\226\214\177\377\221\207y\377\217\204v\377\222\210z\377\216\203u\377\226"
"\214\177\377\227\215\200\377\225\213}\377\214\201s\377\230\216\201\377\220"
"\205w\377\224\212|\377\220\205w\377\220\205w\377\224\212|\377\220\205w\377"
"\220\205w\377\227\215\200\377\223\211{\377~tg\377)&!\262\003\003\003\000JD<\377s"
"j^\377\217\205w\377\224\212}\377\213\200r\377\217\205w\377\221\207y\377\222"
"\210z\377\224\212}\377\224\212|\377\217\204v\377\223\211{\377\224\212|\377"
"\217\204v\377\224\212|\377\214\201s\377\221\206y\377\220\205w\377\217\205"
"w\377\224\212}\377\217\204v\377\223\211{\377\226\214\177\377\225\213}\377"
"\215\202t\377\220\206x\377\224\212|\377\217\204v\377\220\206x\377\222\210"
"z\377\217\204v\377\224\212|\377\222\210z\377\222\210z\377\220\206x\377\216"
"\203u\377\222\210z\377\224\212}\377zpc\377)&!\262\003\003\003\000JD<\377ul`\377\230"
"\216\202\377\223\211{\377\217\205w\377\226\214\177\377\221\207y\377\222\210"
"z\377\225\213~\377\216\203u\377\217\204v\377\221\207y\377\224\212|\377\213"
"\200r\377\217\205w\377\226\214\177\377\226\214\177\377\223\211{\377\217\205"
"w\377\220\206x\377\216\203u\377\224\212}\377\216\204u\377\224\212|\377\222"
"\210z\377\224\212}\377\226\214\177\377\221\207y\377\221\207y\377\221\206"
"y\377\215\202t\377\224\212}\377\221\207y\377\214\201s\377\215\202t\377\226"
"\214\177\377\217\205w\377\223\211{\377|re\377)&!\262\003\003\003\000JD=\377sj^\377"
"\230\216\201\377\222\210z\377\214\201s\377\217\205w\377\227\215\200\377\223"
"\211{\377\223\211{\377\225\213~\377\227\215\200\377\220\206x\377\217\205"
"w\377\227\215\200\377\224\212|\377\222\210z\377\223\211{\377\217\204v\377"
"\221\207y\377\221\207y\377\223\211{\377\226\214\177\377\225\213~\377\223"
"\211{\377\222\210z\377\222\210z\377\224\212|\377\224\212}\377\221\207y\377"
"\227\215\200\377\221\207y\377\221\207y\377\225\213~\377\227\215\200\377\223"
"\211{\377\213\200r\377\230\216\201\377\227\215\200\377ypc\377)&!\262\003\003"
"\003\000JD=\377tk_\377\233\221\205\377\221\207y\377\216\204u\377\222\210z\377"
"\224\212|\377\223\211{\377\230\216\201\377\225\213~\377\222\210z\377\216"
"\204u\377\217\204v\377\216\203u\377\222\210z\377\223\211{\377\221\207y\377"
"\223\211{\377\217\204v\377\220\205w\377\221\207y\377\217\204v\377\221\207"
"y\377\220\205w\377\216\203u\377\223\211{\377\217\204v\377\223\211{\377\227"
"\215\200\377\225\213~\377\222\210z\377\214\201s\377\227\215\200\377\227\215"
"\200\377\222\210z\377\224\212}\377\227\215\200\377\216\203u\377\201wj\377"
")&!\262\003\003\003\000JD=\377sj^\377\231\217\203\377\220\205w\377\215\202t\377\216"
"\204u\377\220\205w\377\214\201s\377\217\204v\377\226\214\177\377\225\213"
"~\377\223\211{\377\225\213~\377\220\206x\377\214\201s\377\226\214\177\377"
"\222\210z\377\214\201s\377\217\205w\377\217\204v\377\227\215\200\377\222"
"\210z\377\220\205w\377\221\207y\377\221\207y\377\220\206x\377\222\210z\377"
"\223\211{\377\217\204v\377\226\214\177\377\221\206y\377\217\205w\377\223"
"\211{\377\223\211{\377\223\211{\377\221\207y\377\223\211{\377\223\211{\377"
"}sf\377)&!\262\003\003\003\000JD=\377sj^\377\226\214\177\377\227\215\200\377\225"
"\213~\377\224\212}\377\217\204v\377\223\211{\377\221\207y\377\217\205w\377"
"\222\210z\377\216\203u\377\223\211{\377\224\212}\377\221\207y\377\217\205"
"w\377\223\211{\377\217\205w\377\216\204u\377\223\211{\377\217\205w\377\227"
"\215\200\377\224\212}\377\217\205w\377\216\203u\377\224\212}\377\230\216"
"\201\377\221\207y\377\220\206x\377\222\210z\377\224\212|\377\217\204v\377"
"\222\210z\377\221\207y\377\226\214\177\377\226\214\177\377\220\205w\377\223"
"\211{\377~tg\377)&!\262\003\003\003\000JD=\377ul`\377\223\211{\377\213\200r\377\217"
"\205w\377\217\205w\377\221\207y\377\224\212}\377\221\207y\377\217\204v\377"
"\221\207y\377\222\210z\377\226\214\177\377\221\207y\377\222\210z\377\217"
"\204v\377\216\203u\377\226\214\177\377\221\207y\377\214\201s\377\215\202"
"t\377\216\203u\377\227\215\200\377\223\211{\377\222\210z\377\216\204u\377"
"\226\214\177\377\221\207y\377\230\216\202\377\216\204u\377\225\213~\377\230"
"\216\201\377\223\211{\377\224\212}\377\216\203u\377\221\207y\377\221\207"
"y\377\222\210z\377}sf\377)&!\262\003\003\003\000JD=\377sj^\377\220\205w\377\221\207"
"y\377\226\214\177\377\220\205w\377\221\207y\377\214\201s\377\224\212}\377"
"\215\202t\377\216\204u\377\217\204v\377\222\210z\377\225\213~\377\223\211"
"{\377\217\204v\377\226\214\177\377\217\205w\377\224\212|\377\223\211{\377"
"\224\212}\377\217\204v\377\223\211{\377\225\213~\377\215\202t\377\217\204"
"v\377\220\206x\377\215\202t\377\216\203u\377\223\211{\377\225\213~\377\221"
"\207y\377\226\214\177\377\225\213~\377\221\207y\377\227\215\200\377\222\210"
"z\377\217\204v\377\205{m\377)&!\262\003\003\003\000JD<\377sj^\377\225\213~\377\226"
"\214\177\377\223\211{\377\220\206x\377\217\205w\377\224\212|\377\221\207"
"y\377\217\204v\377\221\207y\377\223\211{\377\221\207y\377\215\202t\377\213"
"\200r\377\225\213~\377\215\202t\377\223\211{\377\222\210z\377\227\215\200"
"\377\214\201s\377\217\205w\377\222\210z\377\217\205w\377\223\211{\377\222"
"\210z\377\226\214\177\377\220\205w\377\217\204v\377\223\211{\377\217\204"
"v\377\221\207y\377\214\201s\377\222\210z\377\221\207y\377\226\214\177\377"
"\223\211{\377\223\211{\377\201vi\377)&!\262\003\003\003\000JD<\377qh\\\377\220\205"
"w\377\220\205w\377\217\204v\377\216\203u\377\217\204v\377\217\204v\377\226"
"\214\177\377\222\210z\377\221\207y\377\222\210z\377\223\211{\377\223\211"
"{\377\222\210z\377\222\210z\377\227\215\200\377\224\212}\377\217\204v\377"
"\216\204u\377\220\206x\377\217\204v\377\214\201s\377\220\205w\377\216\203"
"u\377\230\216\201\377\223\211{\377\217\204v\377\216\204u\377\230\216\201"
"\377\217\204v\377\217\205w\377\223\211{\377\215\202t\377\221\206y\377\215"
"\202t\377\217\204v\377\224\212|\377\200vi\377)&!\262\003\003\003\000JD<\377ri]\377"
"\221\207y\377\217\205w\377\217\205w\377\223\211{\377\223\211{\377\217\204"
"v\377\223\211{\377\222\210z\377\224\212}\377\225\213~\377\217\204v\377\230"
"\216\201\377\223\211{\377\223\211{\377\214\201s\377\224\212|\377\220\205"
"w\377\222\210z\377\216\204u\377\216\203u\377\223\211{\377\221\207y\377\223"
"\211{\377\223\211{\377\217\204v\377\223\211{\377\223\211{\377\227\215\200"
"\377\230\216\201\377\224\212}\377\224\212|\377\222\210z\377\224\212}\377"
"\214\201s\377\217\204v\377\224\212}\377zpc\377)&!\262\003\003\003\000JD<\377ri]\377"
"\225\213~\377\215\202t\377\222\210z\377\217\205w\377\220\206x\377\217\204"
"v\377\226\214\177\377\220\205w\377\225\213~\377\226\214\177\377\224\212}"
"\377\223\211{\377\222\210z\377\224\212|\377\223\211{\377\222\210z\377\220"
"\206x\377\225\213~\377\217\204v\377\216\204u\377\216\203u\377\220\205w\377"
"\217\205w\377\220\205x\377\223\211{\377\223\211{\377\222\210z\377\221\207"
"y\377\223\211{\377\220\206x\377\216\204u\377\223\211{\377\217\205w\377\217"
"\204v\377\223\211{\377\223\211{\377~tg\377)&!\262\003\003\003\000JD<\377pg\\\377"
"\227\215\200\377\226\214\177\377\216\204u\377\224\212}\377\220\205w\377\223"
"\211{\377\221\207y\377\217\205w\377\216\204u\377\223\211{\377\224\212}\377"
"\222\210z\377\224\212}\377\223\211{\377\215\202t\377\217\204v\377\223\211"
"{\377\220\205x\377\217\204v\377\222\210z\377\223\211{\377\223\211{\377\222"
"\210z\377\216\204u\377\222\210z\377\223\211{\377\220\205w\377\227\215\200"
"\377\221\207y\377\217\204v\377\224\212|\377\223\211{\377\226\214\177\377"
"\221\206y\377\227\215\200\377\217\204v\377\201vi\377)&!\262\003\003\003\000JD<\377"
"sj^\377\220\206x\377\215\202t\377\223\211{\377\217\205w\377\225\213~\377"
"\225\213~\377\220\205w\377\223\211{\377\225\213~\377\217\205w\377\223\211"
"{\377\226\214\177\377\222\210z\377\224\212}\377\223\211{\377\222\210z\377"
"\225\213~\377\222\210z\377\222\210z\377\216\203t\377\226\214\177\377\223"
"\211{\377\221\207y\377\217\204v\377\221\207y\377\222\210z\377\222\210z\377"
"\221\207y\377\222\210z\377\224\212|\377\220\206x\377\220\206x\377\217\204"
"v\377\226\214\177\377\222\210z\377\217\204v\377\200vi\377)&!\262\003\003\003\000"
"JD<\377ri]\377\224\212|\377\221\207y\377\223\211{\377\221\207y\377\213\200"
"r\377\221\207y\377\223\211{\377\223\211{\377\220\205w\377\215\202t\377\226"
"\214\177\377\223\211{\377\217\204v\377\223\211{\377\225\213~\377\224\212"
"|\377\225\213~\377\222\210z\377\217\204v\377\222\210z\377\223\211{\377\221"
"\207y\377\217\204v\377\224\212|\377\223\211{\377\226\214\177\377\222\210"
"z\377\223\211{\377\217\205w\377\223\211{\377\221\207y\377\225\213~\377\220"
"\206x\377\225\213~\377\216\204u\377\225\213~\377\202wj\377)&!\262\003\003\003\000"
"JD<\377uk`\377\227\215\200\377\222\210z\377\225\213~\377\216\204u\377\220"
"\205w\377\221\207y\377\221\207y\377\221\207y\377\223\211{\377\220\205w\377"
"\224\212|\377\227\215\200\377\221\207y\377\217\204v\377\222\210z\377\215"
"\202t\377\226\214\177\377\221\207y\377\224\212|\377\223\211{\377\221\207"
"y\377\226\214\177\377\216\203u\377\217\204v\377\223\211{\377\220\205w\377"
"\222\210z\377\220\205w\377\222\210z\377\222\210z\377\221\207y\377\217\205"
"w\377\221\207y\377\222\210z\377\223\211{\377\225\213}\377\200vi\377)&!\262"
"\003\003\003\000JD<\377sj^\377\216\204u\377\217\204v\377\222\210z\377\214\201s\377"
"\223\211{\377\221\207y\377\230\216\202\377\221\207y\377\227\215\200\377\220"
"\206x\377\222\210z\377\217\205w\377\220\205w\377\217\204v\377\227\215\200"
"\377\222\210z\377\220\206x\377\217\204v\377\222\210z\377\215\202t\377\217"
"\204v\377\223\211{\377\224\212|\377\223\211{\377\222\210z\377\213\200r\377"
"\221\207y\377\224\212|\377\224\212|\377\217\204v\377\221\207y\377\215\202"
"t\377\226\214\177\377\217\204v\377\225\213~\377\224\212}\377|re\377)&!\262"
"\003\003\003\000JD<\377ri]\377\224\212|\377\221\206y\377\225\213~\377\215\202t\377"
"\226\214\177\377\223\211{\377\217\205w\377\230\216\201\377\220\205w\377\221"
"\207y\377\224\212}\377\217\204v\377\223\211{\377\214\201s\377\226\214\177"
"\377\217\204v\377\220\206x\377\220\205w\377\222\210z\377\220\206x\377\225"
"\213~\377\217\204v\377\230\216\201\377\217\204v\377\221\207y\377\223\211"
"{\377\224\212}\377\223\211{\377\220\206x\377\220\205w\377\216\203u\377\217"
"\204v\377\217\204v\377\214\201s\377\221\207y\377\230\216\201\377~tg\377)"
"&!\262\003\003\003\000JD<\377ri]\377\230\216\201\377\223\211{\377\223\211{\377\224"
"\212}\377\221\207y\377\221\207y\377\224\212}\377\227\215\200\377\226\214"
"\177\377\225\213~\377\222\210z\377\222\210z\377\221\207y\377\217\204v\377"
"\223\211{\377\224\212}\377\222\210z\377\224\212|\377\226\214\177\377\225"
"\213~\377\226\214\177\377\214\201s\377\230\216\201\377\215\202t\377\224\212"
"|\377\217\204v\377\215\202t\377\217\204v\377\217\204v\377\225\213~\377\214"
"\201s\377\220\205w\377\223\211{\377\223\211{\377\220\205w\377\226\214\177"
"\377~tg\377)&!\262\003\003\003\000JD=\377ri]\377\221\207y\377\231\217\202\377\223"
"\211{\377\224\212|\377\217\204v\377\216\203u\377\223\211{\377\216\203u\377"
"\223\211{\377\225\213~\377\217\204v\377\220\206x\377\217\204v\377\221\207"
"y\377\226\214\177\377\225\213~\377\214\201s\377\224\212|\377\215\202t\377"
"\221\207y\377\223\211{\377\224\212}\377\223\211{\377\220\205w\377\222\210"
"z\377\223\211{\377\231\217\202\377\221\207y\377\221\207y\377\225\213~\377"
"\222\210z\377\214\201s\377\224\212|\377\216\203u\377\217\205w\377\227\215"
"\200\377}sf\377)&!\262\003\003\003\000JD<\377^WM\377\232\221\204\377\217\204v\377"
"\223\211{\377\223\211{\377\220\206x\377\222\210z\377\221\206y\377\224\212"
"}\377\223\211{\377\217\204v\377\224\212|\377\231\217\202\377\223\211{\377"
"\224\212}\377\224\212}\377\225\213}\377\217\204v\377\220\205w\377\221\207"
"y\377\223\211{\377\226\214\177\377\223\211{\377\224\212}\377\221\207y\377"
"\216\203u\377\217\204v\377\225\213}\377\226\214\177\377\224\212}\377\224"
"\212}\377\231\217\202\377\224\212|\377\217\204v\377\217\204v\377\224\212"
"|\377\225\213}\377~tg\377)&!\262\003\003\003\000<\067\061\377\060,'\377\231\217\203"
"\377\215\202t\377\227\215\200\377\226\214\177\377\223\211{\377\221\207y\377"
"\223\211{\377\227\215\200\377\217\204v\377\217\205w\377\222\210z\377\227"
"\215\200\377\230\216\201\377\223\211{\377\226\214\177\377\226\214\177\377"
"\222\210z\377\224\212}\377\226\214\177\377\224\212}\377\222\210z\377\221"
"\206y\377\227\215\200\377\225\213~\377\223\211{\377\217\204v\377\227\215"
"\200\377\223\211{\377\220\206x\377\223\211{\377\223\211{\377\224\212|\377"
"\226\214\177\377\230\216\201\377\230\216\201\377\216\203u\377\177uh\377)"
"&!\262\003\003\003\000PJA\377NG@\377{qd\377pg[\377of[\377pg[\377pg\\\377kcX\377j"
"bW\377f^T\377of[\377kcX\377i`V\377kcX\377qh\\\377{qd\377uk_\377sj^\377wm"
"a\377of[\377lcX\377kcX\377pg[\377vl`\377vl`\377xob\377ul`\377xnb\377vl`\377"
"ypc\377wna\377xob\377uk_\377ul`\377uk_\377zqd\377ypc\377qh\\\377ldY\377)"
"&!\262\003\003\003\000D?\070\177\066\062,\377=\071\062\377NG?\377PJB\377NH@\377NG@\377"
"OIA\377NG?\377MF?\377MG?\377NG?\377MG?\377MG?\377MG?\377MF?\377MF?\377MG"
"?\377MG?\377JD=\377KF>\377KF>\377MG?\377LF>\377KF>\377JD=\377JD<\377JD<\377"
"JD=\377JD<\377JD=\377JD=\377JD=\377JD=\377JD=\377KF>\377JD=\377MG?\377E@"
"\071\377)&!\324\003\003\003\000",
};
const char* Artwork::whiteBtnUp = (const char*)tempWhiteUp;
const char* Artwork::whiteBtnDn = (const char*)tempWhiteDn;