Compare commits
No commits in common. "main" and "voice" have entirely different histories.
@ -11,9 +11,7 @@ NAME = peacock
|
|||||||
|
|
||||||
FILES_DSP = \
|
FILES_DSP = \
|
||||||
peacock.cpp \
|
peacock.cpp \
|
||||||
controls.cpp \
|
|
||||||
ic1.cpp \
|
ic1.cpp \
|
||||||
oscillator.cpp \
|
|
||||||
ic29.cpp
|
ic29.cpp
|
||||||
|
|
||||||
include ../dpf/Makefile.plugins.mk
|
include ../dpf/Makefile.plugins.mk
|
||||||
|
@ -1,313 +0,0 @@
|
|||||||
/*
|
|
||||||
Peacock-8 VA polysynth
|
|
||||||
|
|
||||||
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "peacock.hpp"
|
|
||||||
|
|
||||||
void Peacock::initParameter(uint32_t index, Parameter& parameter) {
|
|
||||||
switch (index) {
|
|
||||||
case p_lfoRate:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "LFO Rate";
|
|
||||||
parameter.symbol = "pfau_lforate";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 48.0f;
|
|
||||||
parameter.midiCC = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_lfoDelay:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "LFO Delay";
|
|
||||||
parameter.symbol = "pfau_lfodelay";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 9;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_vcoRange:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
|
||||||
parameter.name = "Range";
|
|
||||||
parameter.symbol = "pfau_vcorange";
|
|
||||||
parameter.ranges.min = 0.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 p_vcoLfoMod:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "LFO";
|
|
||||||
parameter.symbol = "pfau_lfo";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 10.0f;
|
|
||||||
parameter.midiCC = 13;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_pwmLfoMod:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "PWM";
|
|
||||||
parameter.symbol = "pfau_pwm";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 48.0f;
|
|
||||||
parameter.midiCC = 14;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_pwmMode:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
|
|
||||||
parameter.name = "PWM Mode";
|
|
||||||
parameter.symbol = "pfau_pwmmode";
|
|
||||||
parameter.ranges.min = 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 p_sawOn:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
|
|
||||||
parameter.name = "Saw";
|
|
||||||
parameter.symbol = "pfau_saw";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 1.0f;
|
|
||||||
parameter.ranges.def = 1.0f;
|
|
||||||
parameter.midiCC = 17;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_sqrOn:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsBoolean;
|
|
||||||
parameter.name = "Square";
|
|
||||||
parameter.symbol = "pfau_sqr";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 1.0f;
|
|
||||||
parameter.ranges.def = 1.0f;
|
|
||||||
parameter.midiCC = 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_subLevel:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Sub Osc";
|
|
||||||
parameter.symbol = "pfau_sub";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 18;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_noiseLevel:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Noise";
|
|
||||||
parameter.symbol = "pfau_noise";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 19;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_hpfMode:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
|
||||||
parameter.name = "HPF";
|
|
||||||
parameter.symbol = "pfau_hpf";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 3.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 20;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_vcfCutoff:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Freq";
|
|
||||||
parameter.symbol = "pfau_freq";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 60.0f;
|
|
||||||
parameter.midiCC = 74;
|
|
||||||
break;
|
|
||||||
case p_vcfReso:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Res";
|
|
||||||
parameter.symbol = "pfau_reso";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 71;
|
|
||||||
break;
|
|
||||||
case p_vcfEnvPol:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
|
||||||
parameter.name = "Polarity";
|
|
||||||
parameter.symbol = "pfau_vcfmode";
|
|
||||||
parameter.ranges.min = 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 p_vcfEnvMod:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Env";
|
|
||||||
parameter.symbol = "pfau_vcfenvmod";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 46.0f;
|
|
||||||
parameter.midiCC = 22;
|
|
||||||
break;
|
|
||||||
case p_vcfLFoMod:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "LFO";
|
|
||||||
parameter.symbol = "pfau_vcflfomod";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 23;
|
|
||||||
break;
|
|
||||||
case p_vcfKeyTrk:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Kybd";
|
|
||||||
parameter.symbol = "pfau_vcfkeymod";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 71.0f;
|
|
||||||
parameter.midiCC = 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_attack:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Attack";
|
|
||||||
parameter.symbol = "pfau_attack";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 27.0f;
|
|
||||||
parameter.midiCC = 73;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_decay:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Decay";
|
|
||||||
parameter.symbol = "pfau_decay";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 57.0f;
|
|
||||||
parameter.midiCC = 75;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_sustain:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Sustain";
|
|
||||||
parameter.symbol = "pfau_sustain";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 57.0f;
|
|
||||||
parameter.midiCC = 27;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_release:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "Release";
|
|
||||||
parameter.symbol = "pfau_release";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 48.0f;
|
|
||||||
parameter.midiCC = 72;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_vcaEnvGate:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger; // | kParameterIsBoolean;
|
|
||||||
parameter.name = "Gate";
|
|
||||||
parameter.symbol = "pfau_envgate";
|
|
||||||
parameter.ranges.min = 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 p_vcaLevel:
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
parameter.name = "VCA Level";
|
|
||||||
parameter.symbol = "pfau_vcalevel";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 40.0f;
|
|
||||||
parameter.midiCC = 26;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case p_modWheel:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsHidden;
|
|
||||||
parameter.name = "Mod wheel";
|
|
||||||
parameter.symbol = "pfau_modwheel";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 1;
|
|
||||||
break;
|
|
||||||
case p_holdPedal:
|
|
||||||
parameter.hints = kParameterIsAutomatable | kParameterIsHidden;
|
|
||||||
parameter.name = "Hold Pedal";
|
|
||||||
parameter.symbol = "pfau_holdpedal";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.max = 127.0f;
|
|
||||||
parameter.ranges.def = 0.0f;
|
|
||||||
parameter.midiCC = 64;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// chorus, porta, bend range, key mode still to do
|
|
||||||
}
|
|
101
plugin/ic29.cpp
101
plugin/ic29.cpp
@ -18,18 +18,14 @@
|
|||||||
|
|
||||||
#include "ic29.hpp"
|
#include "ic29.hpp"
|
||||||
|
|
||||||
#include "ic29tables.hpp"
|
|
||||||
|
|
||||||
Synth ic29;
|
Synth ic29;
|
||||||
|
|
||||||
Synth::Synth() {
|
Synth::Synth() {
|
||||||
d_debug("initialising synth\n");
|
d_debug("initialising synth\n");
|
||||||
envAtk = 0x00;
|
envAtk = 0x007f;
|
||||||
envDcy = 0x1f;
|
envDcy = envRls = 0xfe90;
|
||||||
envStn = 0x00;
|
envStn = 0x1fff;
|
||||||
envRls = 0x1f;
|
|
||||||
portaCoeff = 0x0;
|
portaCoeff = 0x0;
|
||||||
lfo.speed = 0x06;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::buildTables(double sampleRate) {
|
void Synth::buildTables(double sampleRate) {
|
||||||
@ -45,21 +41,6 @@ void Synth::run() {
|
|||||||
// handle a "loop" worth of envelopes, pitch calculations, etc
|
// handle a "loop" worth of envelopes, pitch calculations, etc
|
||||||
// callled once every 4.3ms block of samples
|
// callled once every 4.3ms block of samples
|
||||||
|
|
||||||
ic29.lfo.run();
|
|
||||||
|
|
||||||
masterPitch = 0x1818;
|
|
||||||
|
|
||||||
// need to calculate VCF "base" setting
|
|
||||||
// need to calculate PWM
|
|
||||||
// various on/off switches
|
|
||||||
|
|
||||||
// PWM is bit 0 sw2, 0 = fixed 1 = lfo
|
|
||||||
// 0 sets EA to 0x3fff, 1 adds
|
|
||||||
uint16_t pwmVal = 0x2000 - ic29.lfo.lfoOut;
|
|
||||||
if (0) pwmVal = 0x3fff;
|
|
||||||
|
|
||||||
ic29.pwm = pwmVal / 40960.0f * (1); // 0.5 is knob val
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
||||||
ic29.voices[i].update();
|
ic29.voices[i].update();
|
||||||
}
|
}
|
||||||
@ -77,32 +58,14 @@ void Synth::voiceOff(uint8_t voice) {
|
|||||||
ic29.voices[voice].off();
|
ic29.voices[voice].off();
|
||||||
}
|
}
|
||||||
|
|
||||||
LFO::LFO() {
|
void Synth::basePitch() {
|
||||||
lfoOut = 0;
|
uint16_t pitch = 0x1818;
|
||||||
phase = 0;
|
|
||||||
|
|
||||||
// phase is where we are in the LFO delay cycle
|
pitch += lfoPitch;
|
||||||
// the delay envelope sets the depth of pitch and VCF modulation
|
pitch += bendPitch;
|
||||||
// running normally the amplitude is maxed out, and when the first
|
// tuning too but that's zero by default;
|
||||||
// key is struck the holdoff timer and envelope will be reset to zero
|
|
||||||
delayPhase = LFO_RUN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LFO::run() {
|
masterPitch = pitch;
|
||||||
// slightly different from the real synth code which does not use signed
|
|
||||||
// variables, since the CPU doesn't support them
|
|
||||||
|
|
||||||
lfoOut += phase ? lfoRateTable[speed] : -lfoRateTable[speed];
|
|
||||||
if (lfoOut > 0x1fff) {
|
|
||||||
lfoOut = 0x1fff;
|
|
||||||
phase = 0;
|
|
||||||
}
|
|
||||||
if (lfoOut < -0x1fff) {
|
|
||||||
lfoOut = -0x1fff;
|
|
||||||
phase = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// printf("lfoOut=%04x\n", lfoOut);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Envelope::Envelope() {
|
Envelope::Envelope() {
|
||||||
@ -111,24 +74,25 @@ Envelope::Envelope() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Envelope::run() {
|
void Envelope::run() {
|
||||||
uint16_t tempStn = ic29.envStn << 7;
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case ENV_ATK:
|
case ENV_ATK:
|
||||||
level += atkTable[ic29.envAtk];
|
level += ic29.envAtk;
|
||||||
if (level > 0x3fff) {
|
if (level > 0x3fff) {
|
||||||
level = 0x3fff;
|
level = 0x3fff;
|
||||||
phase = ENV_DCY;
|
phase = ENV_DCY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ENV_DCY:
|
case ENV_DCY:
|
||||||
if (level > tempStn) {
|
if (level > ic29.envStn) {
|
||||||
level = (((level - tempStn) * dcyTable[ic29.envDcy]) >> 16) + tempStn;
|
level -= ic29.envStn;
|
||||||
|
level = (level * ic29.envDcy) >> 16;
|
||||||
|
level += ic29.envStn;
|
||||||
} else {
|
} else {
|
||||||
level = tempStn;
|
level = ic29.envStn;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ENV_RLS:
|
case ENV_RLS:
|
||||||
level = (level * dcyTable[ic29.envRls]) >> 16;
|
level = (level * ic29.envRls) >> 16;
|
||||||
break;
|
break;
|
||||||
case ENV_IDLE:
|
case ENV_IDLE:
|
||||||
default:
|
default:
|
||||||
@ -137,26 +101,18 @@ void Envelope::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Voice::Voice() {
|
Voice::Voice() {
|
||||||
subosc = .1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::calcPitch() {
|
void Voice::calcPitch() {
|
||||||
uint16_t target = note << 8;
|
uint16_t target = note << 8;
|
||||||
|
|
||||||
// Portamento is a linear change of pitch - it'll take twice as long
|
|
||||||
// to jump two octaves as it takes to jump one
|
|
||||||
// By comparison "glide" is like an RC filter, for example in the TB303
|
|
||||||
// This is implemented here by adding on a step value until you pass
|
|
||||||
// the desired final pitch. Once that happens the value is clamped to the
|
|
||||||
// desired pitch.
|
|
||||||
|
|
||||||
if (ic29.portaCoeff != 0) {
|
if (ic29.portaCoeff != 0) {
|
||||||
// portamento up
|
// porta up
|
||||||
if (pitch < target) {
|
if (pitch < target) {
|
||||||
pitch += ic29.portaCoeff;
|
pitch += ic29.portaCoeff;
|
||||||
if (pitch > target) pitch = target;
|
if (pitch > target) pitch = target;
|
||||||
}
|
}
|
||||||
// portamento down
|
// porta down
|
||||||
if (pitch > target) {
|
if (pitch > target) {
|
||||||
pitch -= ic29.portaCoeff;
|
pitch -= ic29.portaCoeff;
|
||||||
if (pitch < target) pitch = target;
|
if (pitch < target) pitch = target;
|
||||||
@ -165,17 +121,17 @@ void Voice::calcPitch() {
|
|||||||
pitch = target;
|
pitch = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
pitch += ic29.masterPitch;
|
pitch += 0x1818; //ic29.masterPitch;
|
||||||
|
|
||||||
if (pitch < 0x3000) pitch = 0x3000; // lowest note
|
if (pitch < 0x3000) pitch = 0x3000; // lowest note
|
||||||
if (pitch > 0x9700) pitch = 0x6700; // highest note
|
if (pitch > 0x9700) pitch = 0x6700; // highest note
|
||||||
|
|
||||||
pitch -= 0x3000;
|
pitch -= 0x3000;
|
||||||
|
//pitch &= 0xff00;
|
||||||
|
|
||||||
// interpolate between the two table values
|
|
||||||
double o1 = ic29.pitchTable[pitch >> 8];
|
double o1 = ic29.pitchTable[pitch >> 8];
|
||||||
double o2 = ic29.pitchTable[(pitch >> 8) + 1];
|
double o2 = ic29.pitchTable[(pitch >> 8) + 1];
|
||||||
double frac = (pitch & 0xff) / 256.0f;
|
double frac = (pitch & 0xff) / 255.0;
|
||||||
|
|
||||||
omega = ((o2 - o1) * frac) + o1;
|
omega = ((o2 - o1) * frac) + o1;
|
||||||
}
|
}
|
||||||
@ -184,20 +140,29 @@ void Voice::update() {
|
|||||||
// calculate the once-per-block values
|
// calculate the once-per-block values
|
||||||
env.run();
|
env.run();
|
||||||
calcPitch();
|
calcPitch();
|
||||||
pw = 0.5 - ic29.pwm;
|
|
||||||
// do filter values
|
// do filter values
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::on(uint8_t key) {
|
void Voice::on(uint8_t key) {
|
||||||
voiceState = V_ON;
|
voiceState = V_ON;
|
||||||
note = key;
|
note = key;
|
||||||
env.on(); // FIXME move to synth update code
|
env.on();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::off() {
|
void Voice::off() {
|
||||||
// sustain - I need to rethink this bit FIXME
|
// I need to rethink this bit FIXME
|
||||||
voiceState = V_OFF;
|
voiceState = V_OFF;
|
||||||
if (!ic29.sustained) {
|
if (!ic29.sustained) {
|
||||||
env.off();
|
env.off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Voice::run(float *buffer, uint32_t samples) {
|
||||||
|
float gain = env.level / 16384.0;
|
||||||
|
gain *= 0.125;
|
||||||
|
for (uint32_t i = 0; i < samples; i++) {
|
||||||
|
phase += omega;
|
||||||
|
if (phase > 1.0f) phase -= 1.0f;
|
||||||
|
buffer[i] += phase * gain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,24 +20,6 @@
|
|||||||
|
|
||||||
#include "peacock.hpp"
|
#include "peacock.hpp"
|
||||||
|
|
||||||
class LFO {
|
|
||||||
public:
|
|
||||||
LFO();
|
|
||||||
void run();
|
|
||||||
int16_t lfoOut;
|
|
||||||
uint8_t speed;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t
|
|
||||||
phase;
|
|
||||||
uint16_t holdoff;
|
|
||||||
uint16_t envelope;
|
|
||||||
enum { LFO_RUN,
|
|
||||||
LFO_HOLDOFF,
|
|
||||||
LFO_RAMP } delayPhase;
|
|
||||||
static const uint16_t lfoRateTable[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
class Envelope {
|
class Envelope {
|
||||||
public:
|
public:
|
||||||
Envelope();
|
Envelope();
|
||||||
@ -63,8 +45,6 @@ class Envelope {
|
|||||||
ENV_RLS,
|
ENV_RLS,
|
||||||
ENV_IDLE
|
ENV_IDLE
|
||||||
} phase;
|
} phase;
|
||||||
static const uint16_t atkTable[128];
|
|
||||||
static const uint16_t dcyTable[128];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Voice {
|
class Voice {
|
||||||
@ -79,10 +59,6 @@ class Voice {
|
|||||||
private:
|
private:
|
||||||
Envelope env; // calculated envelope value
|
Envelope env; // calculated envelope value
|
||||||
uint16_t pitch = 0x1818; // calculated pitch value with porta and master pitch etc
|
uint16_t pitch = 0x1818; // calculated pitch value with porta and master pitch etc
|
||||||
float delay; // delay slot for polyblep
|
|
||||||
bool pulseStage;
|
|
||||||
float pw, lastpw, pwrc;
|
|
||||||
float subosc = -1;
|
|
||||||
float phase = 0, omega = 0;
|
float phase = 0, omega = 0;
|
||||||
enum { V_DONE,
|
enum { V_DONE,
|
||||||
V_OFF,
|
V_OFF,
|
||||||
@ -117,10 +93,9 @@ class Synth {
|
|||||||
int16_t lfoPitch;
|
int16_t lfoPitch;
|
||||||
int16_t bendPitch;
|
int16_t bendPitch;
|
||||||
Voice voices[NUM_VOICES];
|
Voice voices[NUM_VOICES];
|
||||||
LFO lfo;
|
|
||||||
|
|
||||||
float pwm;
|
|
||||||
|
|
||||||
|
void runLfo();
|
||||||
|
void basePitch();
|
||||||
};
|
};
|
||||||
|
|
||||||
// global
|
// global
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
Chassis polysynth framework
|
|
||||||
|
|
||||||
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ic29.hpp"
|
|
||||||
|
|
||||||
const uint16_t Envelope::atkTable[128] = {
|
|
||||||
0x4000, 0x2000, 0x1000, 0x0aaa, 0x0800, 0x0666, 0x0555, 0x0492, 0x0400,
|
|
||||||
0x038e, 0x0333, 0x02e9, 0x02ab, 0x0276, 0x0249, 0x0222, 0x0200, 0x01e2,
|
|
||||||
0x01c7, 0x01af, 0x0199, 0x0186, 0x0174, 0x0164, 0x0155, 0x0148, 0x013b,
|
|
||||||
0x012f, 0x0124, 0x011a, 0x0111, 0x0108, 0x0100, 0x00f8, 0x00f1, 0x00ea,
|
|
||||||
0x00e4, 0x00dd, 0x00d8, 0x00d2, 0x00cd, 0x00c8, 0x00c3, 0x00bf, 0x00ba,
|
|
||||||
0x00b6, 0x00b2, 0x00ae, 0x00ab, 0x00a7, 0x00a4, 0x00a1, 0x009e, 0x009b,
|
|
||||||
0x0098, 0x0095, 0x0092, 0x0090, 0x008d, 0x008b, 0x0089, 0x0086, 0x0084,
|
|
||||||
0x0082, 0x007f, 0x007d, 0x007a, 0x0077, 0x0074, 0x0072, 0x006f, 0x006c,
|
|
||||||
0x0069, 0x0067, 0x0064, 0x0061, 0x005e, 0x005c, 0x0059, 0x0056, 0x0053,
|
|
||||||
0x0050, 0x004e, 0x004b, 0x0048, 0x0045, 0x0042, 0x0040, 0x003f, 0x003d,
|
|
||||||
0x003c, 0x003a, 0x0039, 0x0037, 0x0036, 0x0034, 0x0033, 0x0031, 0x0030,
|
|
||||||
0x002e, 0x002d, 0x002b, 0x002a, 0x0028, 0x0027, 0x0025, 0x0024, 0x0022,
|
|
||||||
0x0021, 0x0021, 0x0020, 0x0020, 0x001f, 0x001f, 0x001e, 0x001e, 0x001d,
|
|
||||||
0x001d, 0x001c, 0x001c, 0x001b, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017,
|
|
||||||
0x0016, 0x0015};
|
|
||||||
|
|
||||||
const uint16_t Envelope::dcyTable[128] = {
|
|
||||||
0x1000, 0x3000, 0x5000, 0x7000, 0x9000, 0xa000, 0xa800, 0xb000, 0xb800,
|
|
||||||
0xc000, 0xc800, 0xd000, 0xd800, 0xe000, 0xe800, 0xf000, 0xf080, 0xf100,
|
|
||||||
0xf180, 0xf200, 0xf280, 0xf300, 0xf380, 0xf400, 0xf480, 0xf500, 0xf580,
|
|
||||||
0xf600, 0xf680, 0xf700, 0xf780, 0xf800, 0xf880, 0xf900, 0xf980, 0xfa00,
|
|
||||||
0xfa80, 0xfb00, 0xfb80, 0xfc00, 0xfc80, 0xfd00, 0xfd80, 0xfe00, 0xfe0c,
|
|
||||||
0xfe18, 0xfe24, 0xfe30, 0xfe3c, 0xfe48, 0xfe54, 0xfe60, 0xfe6c, 0xfe78,
|
|
||||||
0xfe84, 0xfe90, 0xfe9c, 0xfea8, 0xfeb4, 0xfec0, 0xfecc, 0xfed8, 0xfee4,
|
|
||||||
0xfef0, 0xfefc, 0xff08, 0xff0c, 0xff10, 0xff14, 0xff18, 0xff1c, 0xff20,
|
|
||||||
0xff24, 0xff28, 0xff2c, 0xff30, 0xff34, 0xff38, 0xff3c, 0xff40, 0xff44,
|
|
||||||
0xff48, 0xff4c, 0xff50, 0xff54, 0xff58, 0xff5c, 0xff60, 0xff64, 0xff68,
|
|
||||||
0xff6c, 0xff70, 0xff74, 0xff78, 0xff7c, 0xff80, 0xff84, 0xff88, 0xff8c,
|
|
||||||
0xff90, 0xff94, 0xff98, 0xff9c, 0xffa0, 0xffa4, 0xffa8, 0xffac, 0xffb0,
|
|
||||||
0xffb4, 0xffb8, 0xffbc, 0xffc0, 0xffc4, 0xffc8, 0xffcc, 0xffd0, 0xffd4,
|
|
||||||
0xffd8, 0xffdc, 0xffe0, 0xffe4, 0xffe8, 0xffec, 0xfff0, 0xfff1, 0xfff2,
|
|
||||||
0xfff3, 0xfff4};
|
|
||||||
|
|
||||||
extern const uint8_t lfoDepthTable[128] = {
|
|
||||||
0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
|
||||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
|
|
||||||
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
|
|
||||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
|
|
||||||
0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
|
||||||
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c,
|
|
||||||
0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64,
|
|
||||||
0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c,
|
|
||||||
0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c, 0xa0, 0xa4, 0xa8, 0xac,
|
|
||||||
0xb0, 0xb4, 0xb8, 0xbc, 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
|
|
||||||
0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf8, 0xff, 0xff};
|
|
||||||
|
|
||||||
const uint16_t LFO::lfoRateTable[128] = {
|
|
||||||
0x0005, 0x000f, 0x0019, 0x0028, 0x0037, 0x0046, 0x0050, 0x005a, 0x0064,
|
|
||||||
0x006e, 0x0078, 0x0082, 0x008c, 0x0096, 0x00a0, 0x00aa, 0x00b4, 0x00be,
|
|
||||||
0x00c8, 0x00d2, 0x00dc, 0x00e6, 0x00f0, 0x00fa, 0x0104, 0x010e, 0x0118,
|
|
||||||
0x0122, 0x012c, 0x0136, 0x0140, 0x014a, 0x0154, 0x015e, 0x0168, 0x0172,
|
|
||||||
0x017c, 0x0186, 0x0190, 0x019a, 0x01a4, 0x01ae, 0x01b8, 0x01c2, 0x01cc,
|
|
||||||
0x01d6, 0x01e0, 0x01ea, 0x01f4, 0x01fe, 0x0208, 0x0212, 0x021c, 0x0226,
|
|
||||||
0x0230, 0x023a, 0x0244, 0x024e, 0x0258, 0x0262, 0x026c, 0x0276, 0x0280,
|
|
||||||
0x028a, 0x029a, 0x02aa, 0x02ba, 0x02ca, 0x02da, 0x02ea, 0x02fa, 0x030a,
|
|
||||||
0x031a, 0x032a, 0x033a, 0x034a, 0x035a, 0x036a, 0x037a, 0x038a, 0x039a,
|
|
||||||
0x03aa, 0x03ba, 0x03ca, 0x03da, 0x03ea, 0x03fa, 0x040a, 0x041a, 0x042a,
|
|
||||||
0x043a, 0x044a, 0x045a, 0x046a, 0x047a, 0x048a, 0x04be, 0x04f2, 0x0526,
|
|
||||||
0x055a, 0x058e, 0x05c2, 0x05f6, 0x062c, 0x0672, 0x06b8, 0x0708, 0x0758,
|
|
||||||
0x07a8, 0x07f8, 0x085c, 0x08c0, 0x0924, 0x0988, 0x09ec, 0x0a50, 0x0ab4,
|
|
||||||
0x0b18, 0x0b7c, 0x0be0, 0x0c58, 0x0cd0, 0x0d48, 0x0dde, 0x0e74, 0x0f0a,
|
|
||||||
0x0fa0, 0x1000};
|
|
||||||
|
|
||||||
extern const uint16_t lfoDelayTable[8] = {
|
|
||||||
0xffff, 0x0419, 0x020c, 0x015e, 0x0100, 0x0100, 0x0100, 0x0100};
|
|
||||||
|
|
||||||
extern const uint8_t portaTable[128] = {
|
|
||||||
0x00, 0xff, 0xf7, 0xef, 0xe7, 0xdf, 0xd7, 0xcf,
|
|
||||||
0xc7, 0xbf, 0xb7, 0xaf, 0xa7, 0x9f, 0x97, 0x8f,
|
|
||||||
0x87, 0x7f, 0x77, 0x6f, 0x67, 0x5f, 0x57, 0x4f,
|
|
||||||
0x47, 0x3f, 0x3d, 0x3b, 0x39, 0x37, 0x35, 0x33,
|
|
||||||
0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23,
|
|
||||||
0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13,
|
|
||||||
0x12, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f,
|
|
||||||
0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
|
|
||||||
0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a,
|
|
||||||
0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07,
|
|
||||||
0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
|
|
||||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
||||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02,
|
|
||||||
0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
Peacock-8 VA polysynth
|
|
||||||
|
|
||||||
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ic29.hpp"
|
|
||||||
|
|
||||||
static inline float poly3blep0(float t) {
|
|
||||||
float t2 = t * t;
|
|
||||||
return 2 * (t * t2 - 0.5f * t2 * t2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float poly3blep1(float t) {
|
|
||||||
return -poly3blep0(1 - t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Voice::run(float *buffer, uint32_t samples) {
|
|
||||||
// generate a full block of samples for the oscillator
|
|
||||||
|
|
||||||
float y, out, t;
|
|
||||||
float saw = 0;
|
|
||||||
float gain = env.level / 16384.0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this uses an adaptation of Mystran's Polyblep oscillator
|
|
||||||
for (uint32_t i = 0; i < samples; i++) {
|
|
||||||
y = delay;
|
|
||||||
delay = 0;
|
|
||||||
phase += omega;
|
|
||||||
|
|
||||||
pwrc = ((pw - pwrc) *.01 ) + pwrc;
|
|
||||||
|
|
||||||
// this is the clever bit
|
|
||||||
while (true) {
|
|
||||||
if (!pulseStage) {
|
|
||||||
if (phase < pwrc) break; // it's not time for the PWM output to step
|
|
||||||
t = (phase - pwrc) / (lastpw - pwrc + omega); // calculate fractional sample allowing for PW amount
|
|
||||||
y -= 0.63 * poly3blep0(t); // magic numbers observed on oscilloscope from real synth
|
|
||||||
delay -= 0.63 * poly3blep1(t);
|
|
||||||
pulseStage = true;
|
|
||||||
}
|
|
||||||
if (pulseStage) {
|
|
||||||
if (phase < 1) break; // it's not time to reset the saw
|
|
||||||
t = (phase - 1) / omega;
|
|
||||||
y += poly3blep0(t) * (0.8 * saw + 0.63 - subosc);
|
|
||||||
delay += poly3blep1(t) * (0.8 * saw + 0.63 - subosc);
|
|
||||||
pulseStage = 0;
|
|
||||||
phase -= 1;
|
|
||||||
subosc = -subosc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delay += saw * (0.8 - (1.6 * phase)); // magic numbers observed on oscilloscope from real synth
|
|
||||||
delay += (0.63 - (pw * 1.26)) + (pulseStage ? -0.63f : 0.63f); // add in the scaled pulsewidth to restore DC level
|
|
||||||
// the DC correction is important because the hardware synth is AC-coupled effectively high-passing
|
|
||||||
// the signal at about 10Hz or so, preventing any PWM rumble from leaking through!
|
|
||||||
delay += subosc;
|
|
||||||
|
|
||||||
out = y * 0.15;
|
|
||||||
lastpw = pwrc;
|
|
||||||
buffer[i] += out * gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -28,8 +28,6 @@ Peacock::Peacock() : Plugin(paramCount, 0, 0), sampleRate(getSampleRate()) {
|
|||||||
ic29.buildTables(getSampleRate());
|
ic29.buildTables(getSampleRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Peacock::runMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
|
void Peacock::runMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
|
||||||
// handle MIDI events, starting at lastEvent and continuing until timeLimit
|
// handle MIDI events, starting at lastEvent and continuing until timeLimit
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -43,15 +41,6 @@ void Peacock::runMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
|
|||||||
lastEvent = i;
|
lastEvent = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Peacock::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
|
||||||
port.groupId = kPortGroupStereo;
|
|
||||||
Plugin::initAudioPort(input, index, port);
|
|
||||||
|
|
||||||
if (!input && index == 0) port.name = "Left Out";
|
|
||||||
if (!input && index == 1) port.name = "Right Out";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Peacock::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {
|
void Peacock::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {
|
||||||
// calculate an entire jack period's worth of samples
|
// calculate an entire jack period's worth of samples
|
||||||
// harder than it sounds because for short jack periods there may be many
|
// harder than it sounds because for short jack periods there may be many
|
||||||
|
@ -28,32 +28,6 @@ START_NAMESPACE_DISTRHO
|
|||||||
class Peacock : public Plugin {
|
class Peacock : public Plugin {
|
||||||
public:
|
public:
|
||||||
enum Parameters {
|
enum Parameters {
|
||||||
p_lfoRate,
|
|
||||||
p_lfoDelay,
|
|
||||||
p_vcoRange, // 16'/8'/4'
|
|
||||||
p_vcoLfoMod,
|
|
||||||
p_pwmLfoMod,
|
|
||||||
p_pwmMode, // LFO/Fixed
|
|
||||||
p_sawOn,
|
|
||||||
p_sqrOn,
|
|
||||||
p_subLevel,
|
|
||||||
p_noiseLevel,
|
|
||||||
p_hpfMode, // 0 = bass boost, 1 = flat, 2 = 170Hz, 3 = 350Hz
|
|
||||||
p_vcfCutoff,
|
|
||||||
p_vcfReso,
|
|
||||||
p_vcfEnvPol, // positive / inverted
|
|
||||||
p_vcfEnvMod,
|
|
||||||
p_vcfLFoMod,
|
|
||||||
p_vcfKeyTrk,
|
|
||||||
p_vcaEnvGate, // env or gate
|
|
||||||
p_vcaLevel,
|
|
||||||
p_attack,
|
|
||||||
p_decay,
|
|
||||||
p_sustain,
|
|
||||||
p_release,
|
|
||||||
p_chorus, // 0, 1, 2
|
|
||||||
p_modWheel,
|
|
||||||
p_holdPedal,
|
|
||||||
paramCount
|
paramCount
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,6 +35,7 @@ class Peacock : public Plugin {
|
|||||||
float sampleRate;
|
float sampleRate;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const char *getLabel() const override { return "peacock-8"; }
|
const char *getLabel() const override { return "peacock-8"; }
|
||||||
const char *getDescription() const override {
|
const char *getDescription() const override {
|
||||||
return "simple polysynth";
|
return "simple polysynth";
|
||||||
@ -71,8 +46,8 @@ class Peacock : public Plugin {
|
|||||||
int64_t getUniqueId() const override { return d_cconst('P', 'f', 'a', 'u'); }
|
int64_t getUniqueId() const override { return d_cconst('P', 'f', 'a', 'u'); }
|
||||||
|
|
||||||
// Initialisation
|
// Initialisation
|
||||||
void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
|
// void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
|
||||||
void initParameter(uint32_t index, Parameter ¶meter) override;
|
// void initParameter(uint32_t index, Parameter ¶meter) override;
|
||||||
|
|
||||||
// void setParameterValue(uint32_t index, float value) override;
|
// void setParameterValue(uint32_t index, float value) override;
|
||||||
// float getParameterValue(uint32_t index) const override;
|
// float getParameterValue(uint32_t index) const override;
|
||||||
|
Loading…
Reference in New Issue
Block a user