lfo, partial sub
This commit is contained in:
parent
81904ead80
commit
a06266892e
@ -38,7 +38,6 @@ void AlphaOsc::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
|||||||
void AlphaOsc::activate() {
|
void AlphaOsc::activate() {
|
||||||
// calculate filter coefficients and stuff
|
// calculate filter coefficients and stuff
|
||||||
printf("called activate()\n");
|
printf("called activate()\n");
|
||||||
omega = (1 << 31) / sampleRate * 130;
|
|
||||||
lfoOmega = (1 << 31) / sampleRate * 3.51;
|
lfoOmega = (1 << 31) / sampleRate * 3.51;
|
||||||
omega = (130 / sampleRate) * (1 << 23);
|
omega = (130 / sampleRate) * (1 << 23);
|
||||||
}
|
}
|
||||||
@ -57,16 +56,23 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
uint16_t i;
|
uint16_t i;
|
||||||
uint32_t osc;
|
uint32_t osc;
|
||||||
uint8_t lfo;
|
uint8_t lfo;
|
||||||
float saw, sqr, sub, wave;
|
float saw, sqr, sub;
|
||||||
float oct1, oct3, pwg;
|
float oct1, oct3, pwg;
|
||||||
|
float sub1, sub2;
|
||||||
|
|
||||||
float out, in;
|
float out, in;
|
||||||
|
|
||||||
|
// steeply "logarithmic" curve similar to the Juno 106 LFO rate curve
|
||||||
|
// goes from about 0.1Hz to about 60Hz because this "feels about right"
|
||||||
|
// totally unscientific
|
||||||
|
lfoOmega = (0.1 + (pwmrate / (1 + (1 - pwmrate) * 4.75)*60)) / sampleRate * (1<<23);
|
||||||
|
omega = (130 / sampleRate) * (1 << 23);
|
||||||
|
|
||||||
// calculate an entire block of samples
|
// calculate an entire block of samples
|
||||||
|
|
||||||
for (i = 0; i < frames; i++) {
|
for (i = 0; i < frames; i++) {
|
||||||
// increment phase of saw counter
|
// increment phase of saw counter
|
||||||
// phase is a 32-bit counter because we're on a PC and we can afford to be profligate with silicon
|
// phase is a 24-bit counter because we're on a PC and we can afford to be profligate with silicon
|
||||||
// the actual Alpha Juno oscillators might well have been 8-bit for reasons loosely explained in the README
|
// the actual Alpha Juno oscillators might well have been 8-bit for reasons loosely explained in the README
|
||||||
|
|
||||||
phase += omega;
|
phase += omega;
|
||||||
@ -78,10 +84,10 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
osc = phase >> 14;
|
osc = phase >> 14;
|
||||||
|
|
||||||
// LFO is 7-bit triangle
|
// LFO is 7-bit triangle
|
||||||
lfo = (lfoPhase >> 24) & 0x7f;
|
lfo = (lfoPhase >> 16) & 0x7f;
|
||||||
lfo = (lfoPhase & 0x80000000) ? lfo : 127 - lfo;
|
lfo = (lfoPhase & 0x00800000) ? lfo : 127 - lfo;
|
||||||
|
|
||||||
pw = 0;
|
pw = lfo * pwmdepth;
|
||||||
|
|
||||||
// the oscillator outputs in the chip are probably digital signals
|
// the oscillator outputs in the chip are probably digital signals
|
||||||
// with the saw being the 8-bit outputs of the counter
|
// with the saw being the 8-bit outputs of the counter
|
||||||
@ -95,13 +101,40 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
sqr = (float)(osc & 0x80) != 0;
|
sqr = (float)(osc & 0x80) != 0;
|
||||||
oct1 = (float)(osc & 0x40) != 0;
|
oct1 = (float)(osc & 0x40) != 0;
|
||||||
oct3 = (float)(osc & 0x10) != 0;
|
oct3 = (float)(osc & 0x10) != 0;
|
||||||
|
sub1 = (float)(osc & 0x40) != 0;
|
||||||
|
sub2 = (float)(osc & 0x10) != 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// pulse width gate
|
// pulse width gate
|
||||||
// lower seven bits of the saw osc, compared with PW setting
|
// lower seven bits of the saw osc, compared with PW setting
|
||||||
pw = lfo*0.5;
|
|
||||||
pwg = (float)((osc & 0x7f) >= pw) != 0;
|
pwg = (float)((osc & 0x7f) >= pw) != 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// calculate the oscillator output
|
// calculate the oscillator output
|
||||||
|
|
||||||
|
switch (submode) {
|
||||||
|
case 0:
|
||||||
|
sub = sub1;
|
||||||
|
break; // one octave down
|
||||||
|
case 1:
|
||||||
|
sub = sub1 * sqr;
|
||||||
|
break; // saw is fine, do nothing
|
||||||
|
case 2:
|
||||||
|
saw *= oct1; // pulsed
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
saw *= pwg; // pwm
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
saw *= oct3; // oct3 pulse
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
saw *= oct1 * oct3; // both pulse
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sqrmode) {
|
switch (sqrmode) {
|
||||||
case 0:
|
case 0:
|
||||||
case 4:
|
case 4:
|
||||||
@ -137,6 +170,9 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// mix the signals, probably done with some resistors in the chip
|
// mix the signals, probably done with some resistors in the chip
|
||||||
in = (saw * 0.8) + (sqr * 0.63); // scaled similarly to Juno 106
|
in = (saw * 0.8) + (sqr * 0.63); // scaled similarly to Juno 106
|
||||||
|
|
||||||
|
@ -27,10 +27,11 @@ class AlphaOsc : public Plugin {
|
|||||||
enum Parameters {
|
enum Parameters {
|
||||||
pSqrMode,
|
pSqrMode,
|
||||||
pSawMode,
|
pSawMode,
|
||||||
//pSubMode,
|
pSubMode,
|
||||||
|
pSubLevel,
|
||||||
|
|
||||||
//pLFORate,
|
pPWMRate,
|
||||||
//pLFODepth,
|
pPWMDepth,
|
||||||
|
|
||||||
parameterCount
|
parameterCount
|
||||||
};
|
};
|
||||||
@ -59,7 +60,6 @@ class AlphaOsc : public Plugin {
|
|||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
void run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) override;
|
void run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double sampleRate;
|
double sampleRate;
|
||||||
uint32_t omega, lfoOmega;
|
uint32_t omega, lfoOmega;
|
||||||
@ -67,9 +67,10 @@ class AlphaOsc : public Plugin {
|
|||||||
|
|
||||||
uint8_t pw;
|
uint8_t pw;
|
||||||
|
|
||||||
|
float pwmrate, pwmdepth, sublevel;
|
||||||
uint8_t sqrmode, sawmode, submode;
|
uint8_t sqrmode, sawmode, submode;
|
||||||
|
|
||||||
float hpfx, hpfy;
|
float hpfx = 0, hpfy = 0;
|
||||||
|
|
||||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AlphaOsc);
|
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AlphaOsc);
|
||||||
};
|
};
|
||||||
|
@ -74,6 +74,61 @@ void AlphaOsc::initParameter(uint32_t index, Parameter& parameter) {
|
|||||||
parameter.enumValues.values = enumValues;
|
parameter.enumValues.values = enumValues;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case pSubMode:
|
||||||
|
// set up Sub slider
|
||||||
|
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
||||||
|
parameter.name = "Sub";
|
||||||
|
parameter.symbol = "ao_sub";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.max = 5.0f;
|
||||||
|
parameter.ranges.def = 1.0f;
|
||||||
|
parameter.enumValues.count = 6;
|
||||||
|
parameter.enumValues.restrictedMode = true;
|
||||||
|
{
|
||||||
|
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[6];
|
||||||
|
enumValues[0].value = 0;
|
||||||
|
enumValues[0].label = "-1 oct";
|
||||||
|
enumValues[1].value = 1;
|
||||||
|
enumValues[1].label = "-1 oct 25%";
|
||||||
|
enumValues[2].value = 2;
|
||||||
|
enumValues[2].label = "-1 oct + 2 oct";
|
||||||
|
enumValues[3].value = 3;
|
||||||
|
enumValues[3].label = "-1 oct + 3 oct";
|
||||||
|
enumValues[3].value = 4;
|
||||||
|
enumValues[3].label = "-2 oct";
|
||||||
|
enumValues[3].value = 5;
|
||||||
|
enumValues[3].label = "-2 oct 25%";
|
||||||
|
parameter.enumValues.values = enumValues;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case pSubLevel:
|
||||||
|
// set up Sub slider
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
parameter.name = "Sub Level";
|
||||||
|
parameter.symbol = "ao_sublev";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.max = 1.0f;
|
||||||
|
parameter.ranges.def = 0.0f;
|
||||||
|
break;
|
||||||
|
case pPWMRate:
|
||||||
|
// set up PWM Rate slider
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
parameter.name = "PWM Rate";
|
||||||
|
parameter.symbol = "ao_pwmrate";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.max = 1.0f;
|
||||||
|
parameter.ranges.def = 0.5f;
|
||||||
|
break;
|
||||||
|
case pPWMDepth:
|
||||||
|
// set up PWM Depth slider
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
parameter.name = "PWM Depth";
|
||||||
|
parameter.symbol = "ao_pwmdepth";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.max = 1.0f;
|
||||||
|
parameter.ranges.def = 0.5f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +140,18 @@ void AlphaOsc::setParameterValue(uint32_t index, float value) {
|
|||||||
case pSawMode:
|
case pSawMode:
|
||||||
sawmode = value;
|
sawmode = value;
|
||||||
break;
|
break;
|
||||||
|
case pSubMode:
|
||||||
|
submode = value;
|
||||||
|
break;
|
||||||
|
case pSubLevel:
|
||||||
|
sublevel = value;
|
||||||
|
break;
|
||||||
|
case pPWMDepth:
|
||||||
|
pwmdepth = value;
|
||||||
|
break;
|
||||||
|
case pPWMRate:
|
||||||
|
pwmrate = value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// we don't need to handle a default condition
|
// we don't need to handle a default condition
|
||||||
// if there's a parameter left unhandled, it's probably
|
// if there's a parameter left unhandled, it's probably
|
||||||
|
Loading…
Reference in New Issue
Block a user