cleanup
This commit is contained in:
parent
5cc2a5c9ca
commit
99339d6aef
@ -29,23 +29,10 @@ AlphaOsc::AlphaOsc() : Plugin(parameterCount, 0, 0), sampleRate(getSampleRate())
|
|||||||
void AlphaOsc::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
void AlphaOsc::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
||||||
// port.groupId = kPortGroupStereo;
|
// port.groupId = kPortGroupStereo;
|
||||||
Plugin::initAudioPort(input, index, port);
|
Plugin::initAudioPort(input, index, port);
|
||||||
|
|
||||||
if (!input && index == 0) port.name = "Osc Out";
|
if (!input && index == 0) port.name = "Osc Out";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processing functions
|
// Processing function
|
||||||
|
|
||||||
void AlphaOsc::activate() {
|
|
||||||
// calculate filter coefficients and stuff
|
|
||||||
printf("called activate()\n");
|
|
||||||
lfoOmega = (1 << 31) / sampleRate * 3.51;
|
|
||||||
omega = (130 / sampleRate) * (1 << 23);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlphaOsc::deactivate() {
|
|
||||||
printf("called deactivate()\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {
|
void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {
|
||||||
bzero(outputs[0], sizeof(float) * frames);
|
bzero(outputs[0], sizeof(float) * frames);
|
||||||
|
|
||||||
@ -53,9 +40,9 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
(void)midiEventCount;
|
(void)midiEventCount;
|
||||||
(void)midiEvents;
|
(void)midiEvents;
|
||||||
|
|
||||||
uint16_t i;
|
uint32_t i;
|
||||||
uint32_t osc;
|
uint32_t osc;
|
||||||
uint8_t lfo;
|
uint8_t lfo, pw;
|
||||||
|
|
||||||
// oscillator outputs
|
// oscillator outputs
|
||||||
float saw, sqr, sub, pwg;
|
float saw, sqr, sub, pwg;
|
||||||
@ -65,11 +52,15 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
|
|
||||||
float out, in;
|
float out, in;
|
||||||
|
|
||||||
|
// handle any MIDI events
|
||||||
|
|
||||||
// steeply "logarithmic" curve similar to the Juno 106 LFO rate curve
|
// steeply "logarithmic" curve similar to the Juno 106 LFO rate curve
|
||||||
// goes from about 0.1Hz to about 60Hz because this "feels about right"
|
// goes from about 0.1Hz to about 60Hz because this "feels about right"
|
||||||
// totally unscientific
|
// totally unscientific
|
||||||
lfoOmega = (0.1 + (pwmrate / (1 + (1 - pwmrate) * 4.75)*60)) / sampleRate * (1<<23);
|
lfoOmega = (0.1 + (pwmrate / (1 + (1 - pwmrate) * 4.75) * 60)) / sampleRate * (1 << 23);
|
||||||
omega = (130 / sampleRate) * (1 << 23);
|
|
||||||
|
// set the frequency for the phase counter
|
||||||
|
omega = (freq / sampleRate) * (1 << 23);
|
||||||
|
|
||||||
// calculate an entire block of samples
|
// calculate an entire block of samples
|
||||||
|
|
||||||
@ -77,19 +68,26 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
// increment phase of saw counter
|
// increment phase of saw counter
|
||||||
// phase is a 24-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;
|
||||||
lfoPhase += lfoOmega;
|
lfoPhase += lfoOmega;
|
||||||
|
|
||||||
// now osc is a ten-bit counter, to give room for the sub osc outputs
|
// osc is the top ten bits of the phase counter, to give room for the sub osc outputs
|
||||||
// square output will be bit 7 of osc, 25% will be bit 7 & bit 6
|
// bits 8 and 9 will be used for the sub squares
|
||||||
// PWM square will be bit 7 & comparator, with the PWM being compared against bits 0-6
|
// bit 7 for the squarewave
|
||||||
|
// bits 0-7 of this will be used for the saw wave
|
||||||
|
// and bits 6, 5, and 4 for the "modulators"
|
||||||
osc = phase >> 14;
|
osc = phase >> 14;
|
||||||
|
|
||||||
// LFO is 7-bit triangle
|
// LFO is 7-bit triangle
|
||||||
lfo = (lfoPhase >> 16) & 0x7f;
|
// the counter is 24-bit, but we take the top byte for 0-255 with fine control of speed
|
||||||
lfo = (lfoPhase & 0x00800000) ? lfo : 127 - lfo;
|
// by taking bits 0-6 we have a value that counts from 0-127 twice as fast as the
|
||||||
|
// desired LFO speed, which is fine
|
||||||
|
// by then taking bit 7 and using that to set whether we're counting up or down (subtract
|
||||||
|
// the counter from 127) we get a lovely triangle wave
|
||||||
|
lfo = (lfoPhase >> 16) & 0x7f; // top eight bits of the counter, keep only 0-6
|
||||||
|
lfo = (lfoPhase & 0x00800000) ? lfo : 0x7f - lfo; // bit 7 is the polarity
|
||||||
|
|
||||||
|
// scale the LFO output to get our adjustable PWM
|
||||||
pw = lfo * pwmdepth;
|
pw = lfo * pwmdepth;
|
||||||
|
|
||||||
// the oscillator outputs in the chip are probably digital signals
|
// the oscillator outputs in the chip are probably digital signals
|
||||||
@ -97,10 +95,11 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
// the square and sub signals picked off the counter bits
|
// the square and sub signals picked off the counter bits
|
||||||
// and a couple of flipflops to generate the sub osc signals
|
// and a couple of flipflops to generate the sub osc signals
|
||||||
|
|
||||||
// 8-bit saw scaled
|
// 8-bit saw scaled to 0-1
|
||||||
saw = (osc & 0xff) / 256.0f;
|
saw = (osc & 0xff) / 256.0f;
|
||||||
|
|
||||||
// various counter bits scaled from 0-1
|
// various counter bits scaled from 0-1
|
||||||
|
// these generate various squarewaves to gate the signals
|
||||||
bit4 = (float)(osc & 0x010) != 0; // 3 octaves up
|
bit4 = (float)(osc & 0x010) != 0; // 3 octaves up
|
||||||
bit5 = (float)(osc & 0x020) != 0; // 2 octaves up
|
bit5 = (float)(osc & 0x020) != 0; // 2 octaves up
|
||||||
bit6 = (float)(osc & 0x040) != 0; // 1 octave up
|
bit6 = (float)(osc & 0x040) != 0; // 1 octave up
|
||||||
@ -110,18 +109,21 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
|
|
||||||
// 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
|
||||||
|
// this is on or off for a variable (by PW) proportion of a half-cycle
|
||||||
|
// of the square or sawtooth wave, kind of like you see on the diagram
|
||||||
|
// on the top panel of the Alpha Juno
|
||||||
pwg = (float)((osc & 0x7f) >= pw) != 0;
|
pwg = (float)((osc & 0x7f) >= pw) != 0;
|
||||||
|
|
||||||
// calculate the oscillator output
|
// calculate the oscillator output
|
||||||
// because all the "bits" are scaled to floats from 0 to 1
|
// because all the "bits" are scaled to floats from 0 to 1,
|
||||||
// we can just multiply them
|
// we can just multiply them together to get our gating
|
||||||
// in the real chip it probably uses AND gates to control outputs
|
// in the real chip it probably uses AND gates to control outputs
|
||||||
// including an AND gate driving the DAC latch pin
|
// including an AND gate driving the DAC latch pin
|
||||||
switch (submode) {
|
switch (submode) {
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
sub = bit8;
|
sub = bit8; // one octave down
|
||||||
break; // one octave down
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
sub = bit8 * bit7; // one octave down, 25% PW
|
sub = bit8 * bit7; // one octave down, 25% PW
|
||||||
break;
|
break;
|
||||||
@ -145,8 +147,8 @@ void AlphaOsc::run(const float **, float **outputs, uint32_t frames, const MidiE
|
|||||||
default:
|
default:
|
||||||
sqr = 0; // oscillator is off
|
sqr = 0; // oscillator is off
|
||||||
break;
|
break;
|
||||||
case 1: // fundamental
|
case 1:
|
||||||
sqr = bit7;
|
sqr = bit7; // fundamental
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sqr = bit7 * bit6; // 25% pulse
|
sqr = bit7 * bit6; // 25% pulse
|
||||||
@ -177,22 +179,23 @@ 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 = (sub * sublevel) + (saw * 0.8) + (sqr * 0.63); // scaled similarly to Juno 106
|
// these are scaled similarly to my Juno 106 (HS60 really) because it's all
|
||||||
|
// very much just guesswork, and it "feels about right"
|
||||||
|
in = (sub * sublevel) + (saw * 0.8) + (sqr * 0.63);
|
||||||
|
|
||||||
// DC removal highpass filter
|
// DC removal highpass filter
|
||||||
// this is very approximately 6Hz at 44.1kHz and 48kHz
|
// this is very approximately 6Hz at 44.1kHz and 48kHz
|
||||||
|
// which corresponds with the 2.2uF capacitor and 12k + 100 ohm resistor between
|
||||||
|
// the voice chip output and filter input in a real Alpha Juno
|
||||||
// honestly it doesn't matter all that much if it's wrong at higher sample rates
|
// honestly it doesn't matter all that much if it's wrong at higher sample rates
|
||||||
out = in - hpfx + .99915 * hpfy;
|
out = in - hpfx + .99915 * hpfy;
|
||||||
hpfx = in;
|
hpfx = in;
|
||||||
hpfy = out;
|
hpfy = out;
|
||||||
|
|
||||||
outputs[0][i] = out*0.5;
|
// scale the output and write it to the buffer
|
||||||
|
outputs[0][i] = out * 0.5;
|
||||||
}
|
}
|
||||||
// printf("%f %f\n", sqr, saw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the plugin
|
// create the plugin
|
||||||
|
@ -56,8 +56,6 @@ class AlphaOsc : public Plugin {
|
|||||||
float getParameterValue(uint32_t index) const override;
|
float getParameterValue(uint32_t index) const override;
|
||||||
|
|
||||||
// Processing
|
// Processing
|
||||||
void activate() 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:
|
||||||
@ -65,7 +63,9 @@ class AlphaOsc : public Plugin {
|
|||||||
uint32_t omega, lfoOmega;
|
uint32_t omega, lfoOmega;
|
||||||
uint32_t phase, lfoPhase;
|
uint32_t phase, lfoPhase;
|
||||||
|
|
||||||
uint8_t pw;
|
uint8_t note = 48; // last heard MIDI note
|
||||||
|
float freq = 130.8; // C3, an octave below Middle C
|
||||||
|
float gate = 0; // output attenuation
|
||||||
|
|
||||||
float pwmrate, pwmdepth, sublevel;
|
float pwmrate, pwmdepth, sublevel;
|
||||||
uint8_t sqrmode, sawmode, submode;
|
uint8_t sqrmode, sawmode, submode;
|
||||||
|
Loading…
Reference in New Issue
Block a user