not totally happy with the mixing but saw and square are now switchable
This commit is contained in:
parent
0973fc4eeb
commit
b913e9bb9c
@ -23,7 +23,7 @@
|
||||
#define DISTRHO_PLUGIN_URI "https://gjcp.net/plugins/alphaosc"
|
||||
|
||||
#define DISTRHO_PLUGIN_NUM_INPUTS 0
|
||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
|
||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 1
|
||||
#define DISTRHO_PLUGIN_IS_SYNTH 1
|
||||
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
NAME = alphaosc
|
||||
|
||||
FILES_DSP = \
|
||||
parameters.cpp \
|
||||
alphaosc.cpp
|
||||
|
||||
|
||||
|
@ -38,6 +38,9 @@ void AlphaOsc::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
||||
void AlphaOsc::activate() {
|
||||
// calculate filter coefficients and stuff
|
||||
printf("called activate()\n");
|
||||
omega = (1 << 31) / sampleRate * 130;
|
||||
lfoOmega = (1 << 31) / sampleRate * 3.51;
|
||||
omega = (130 / sampleRate) * (1 << 23);
|
||||
}
|
||||
|
||||
void AlphaOsc::deactivate() {
|
||||
@ -50,6 +53,107 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
||||
// cast unused parameters to void for now to stop the compiler complaining
|
||||
(void)midiEventCount;
|
||||
(void)midiEvents;
|
||||
|
||||
uint16_t i;
|
||||
uint32_t osc;
|
||||
uint8_t lfo;
|
||||
float saw, sqr, sub, wave;
|
||||
float oct1, oct3, pwg;
|
||||
|
||||
float out, in;
|
||||
|
||||
// calculate an entire block of samples
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
// 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
|
||||
// the actual Alpha Juno oscillators might well have been 8-bit for reasons loosely explained in the README
|
||||
|
||||
phase += omega;
|
||||
lfoPhase += lfoOmega;
|
||||
|
||||
// now osc is a ten-bit counter, to give room for the sub osc outputs
|
||||
// square output will be bit 7 of osc, 25% will be bit 7 & bit 6
|
||||
// PWM square will be bit 7 & comparator, with the PWM being compared against bits 0-6
|
||||
osc = phase >> 14;
|
||||
|
||||
// LFO is 7-bit triangle
|
||||
lfo = (lfoPhase >> 24) & 0x7f;
|
||||
lfo = (lfoPhase & 0x80000000) ? lfo : 127 - lfo;
|
||||
|
||||
pw = 0;
|
||||
|
||||
// the oscillator outputs in the chip are probably digital signals
|
||||
// with the saw being the 8-bit outputs of the counter
|
||||
// the square and sub signals picked off the counter bits
|
||||
// and a couple of flipflops to generate the sub osc signals
|
||||
|
||||
// 8-bit saw scaled
|
||||
saw = (osc & 0xff) / 256.0f;
|
||||
|
||||
// square scaled to 0-1, along with one and three octaves up
|
||||
sqr = (float)(osc & 0x80) != 0;
|
||||
oct1 = (float)(osc & 0x40) != 0;
|
||||
oct3 = (float)(osc & 0x10) != 0;
|
||||
|
||||
// pulse width gate
|
||||
// lower seven bits of the saw osc, compared with PW setting
|
||||
pw = lfo*0.5;
|
||||
pwg = (float)((osc & 0x7f) >= pw) != 0;
|
||||
|
||||
// calculate the oscillator output
|
||||
in = wave = 0;
|
||||
switch (sqrmode) {
|
||||
case 0:
|
||||
case 4:
|
||||
wave = 0;
|
||||
break; // oscillator is off
|
||||
case 1:
|
||||
wave = sqr;
|
||||
break;
|
||||
case 2:
|
||||
wave = sqr * oct1; // 25% pulse
|
||||
break;
|
||||
case 3:
|
||||
wave = sqr * pwg; // pwm
|
||||
break;
|
||||
}
|
||||
|
||||
in += (wave * 0.63); // scaled similarly to Juno 106
|
||||
|
||||
switch (sawmode) {
|
||||
case 0:
|
||||
wave = 0;
|
||||
break; // oscillator is off
|
||||
case 1:
|
||||
wave = saw;
|
||||
break;
|
||||
case 2:
|
||||
wave = saw * oct1; // pulsed
|
||||
break;
|
||||
case 3:
|
||||
wave = saw * pwg; // pwm
|
||||
break;
|
||||
case 4:
|
||||
wave = saw * oct3; // oct3 pulse
|
||||
break;
|
||||
case 5:
|
||||
wave = saw * oct1 * oct3; // both pulse
|
||||
break;
|
||||
}
|
||||
|
||||
in += (wave * 0.8); // scaled similarly to Juno 106
|
||||
|
||||
// DC removal highpass filter
|
||||
// this is very approximately 6Hz at 44.1kHz and 48kHz
|
||||
// honestly it doesn't matter all that much if it's wrong at higher sample rates
|
||||
out = in - hpfx + .99915 * hpfy;
|
||||
hpfx = in;
|
||||
hpfy = out;
|
||||
|
||||
outputs[0][i] = out;
|
||||
}
|
||||
// printf("%f %f\n", sqr, saw);
|
||||
}
|
||||
|
||||
// create the plugin
|
||||
|
@ -25,8 +25,12 @@ START_NAMESPACE_DISTRHO
|
||||
class AlphaOsc : public Plugin {
|
||||
public:
|
||||
enum Parameters {
|
||||
paramLFORate,
|
||||
paramLFODelay,
|
||||
pSqrMode,
|
||||
pSawMode,
|
||||
//pSubMode,
|
||||
|
||||
//pLFORate,
|
||||
//pLFODepth,
|
||||
|
||||
parameterCount
|
||||
};
|
||||
@ -45,10 +49,10 @@ class AlphaOsc : public Plugin {
|
||||
|
||||
// Initialisation
|
||||
void initAudioPort(bool input, uint32_t index, AudioPort &port) override;
|
||||
//void initParameter(uint32_t index, Parameter ¶meter) override;
|
||||
|
||||
//void setParameterValue(uint32_t index, float value) override;
|
||||
//float getParameterValue(uint32_t index) const override;
|
||||
void initParameter(uint32_t index, Parameter ¶meter) override;
|
||||
void setParameterValue(uint32_t index, float value) override;
|
||||
float getParameterValue(uint32_t index) const override;
|
||||
|
||||
// Processing
|
||||
void activate() override;
|
||||
@ -58,11 +62,16 @@ class AlphaOsc : public Plugin {
|
||||
|
||||
private:
|
||||
double sampleRate;
|
||||
uint32_t omega;
|
||||
uint32_t phase;
|
||||
uint32_t omega, lfoOmega;
|
||||
uint32_t phase, lfoPhase;
|
||||
|
||||
uint8_t pw;
|
||||
|
||||
uint8_t sqrmode, sawmode, submode;
|
||||
|
||||
float hpfx, hpfy;
|
||||
|
||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AlphaOsc);
|
||||
};
|
||||
|
||||
END_NAMESPACE_DISTRHO
|
||||
|
||||
|
103
plugin/parameters.cpp
Normal file
103
plugin/parameters.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
Alpha Oscillator POC
|
||||
|
||||
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 "alphaosc.hpp"
|
||||
|
||||
void AlphaOsc::initParameter(uint32_t index, Parameter& parameter) {
|
||||
// define all the different control input parameters
|
||||
switch (index) {
|
||||
case pSqrMode:
|
||||
// set up Square slider
|
||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
||||
parameter.name = "Square";
|
||||
parameter.symbol = "ao_sqr";
|
||||
parameter.ranges.min = 0.0f;
|
||||
parameter.ranges.max = 4.0f;
|
||||
parameter.ranges.def = 1.0f;
|
||||
parameter.enumValues.count = 5;
|
||||
parameter.enumValues.restrictedMode = true;
|
||||
{
|
||||
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[5];
|
||||
enumValues[0].value = 0;
|
||||
enumValues[0].label = "Off";
|
||||
enumValues[1].value = 1;
|
||||
enumValues[1].label = "50%";
|
||||
enumValues[2].value = 2;
|
||||
enumValues[2].label = "25%";
|
||||
enumValues[3].value = 3;
|
||||
enumValues[3].label = "PWM";
|
||||
// dummy value because Carla won't display integer knobs with less than 5 steps
|
||||
enumValues[4].value = 3;
|
||||
enumValues[4].label = "Off";
|
||||
parameter.enumValues.values = enumValues;
|
||||
}
|
||||
break;
|
||||
case pSawMode:
|
||||
// set up Saw slider
|
||||
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
||||
parameter.name = "Saw";
|
||||
parameter.symbol = "ao_saw";
|
||||
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 = "Off";
|
||||
enumValues[1].value = 1;
|
||||
enumValues[1].label = "On";
|
||||
enumValues[2].value = 2;
|
||||
enumValues[2].label = "Oct1";
|
||||
enumValues[3].value = 3;
|
||||
enumValues[3].label = "PWM";
|
||||
enumValues[3].value = 4;
|
||||
enumValues[3].label = "Oct3";
|
||||
enumValues[3].value = 5;
|
||||
enumValues[3].label = "Oct1+3";
|
||||
parameter.enumValues.values = enumValues;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaOsc::setParameterValue(uint32_t index, float value) {
|
||||
switch (index) {
|
||||
case pSqrMode:
|
||||
sqrmode = value;
|
||||
break;
|
||||
case pSawMode:
|
||||
sawmode = value;
|
||||
break;
|
||||
}
|
||||
// we don't need to handle a default condition
|
||||
// if there's a parameter left unhandled, it's probably
|
||||
// a mistake by the plugin host, and we don't much care
|
||||
}
|
||||
|
||||
float AlphaOsc::getParameterValue(uint32_t index) const {
|
||||
switch (index) {
|
||||
case pSqrMode:
|
||||
return sqrmode;
|
||||
case pSawMode:
|
||||
return sawmode;
|
||||
}
|
||||
// if we fall all the way through...
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user