From e565fb35b6f8d348175bc9316f8725d7641a1237 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Wed, 11 Nov 2020 17:05:28 -0700 Subject: [PATCH] FMVoice is now a class --- synth.cpp | 46 ++++++++++++++--------------- synth.h | 82 ++++++++++++++++++++++++++++++---------------------- uilleann.ino | 12 ++++---- 3 files changed, 77 insertions(+), 63 deletions(-) diff --git a/synth.cpp b/synth.cpp index b4e2488..1b85228 100644 --- a/synth.cpp +++ b/synth.cpp @@ -1,47 +1,47 @@ #include "synth.h" #include "synth_waveform.h" -void FMVoiceLoadPatch(FMVoice *v, FMPatch *p) { +void FMVoice::LoadPatch(FMPatch *p) { for (int i=0; ioperators[i]; - v->oscillators[i].frequencyModulation(1); - v->oscillators[i].begin(op.waveform); - v->envelopes[i].delay(op.delayTime); - v->envelopes[i].attack(op.attackTime); - v->oscillators[i].amplitude(op.holdAmplitude); - v->envelopes[i].hold(op.holdTime); - v->envelopes[i].decay(op.decayTime); - v->envelopes[i].sustain(op.sustainAmplitude / op.holdAmplitude); - v->envelopes[i].release(op.releaseTime); + this->oscillators[i].frequencyModulation(1); + this->oscillators[i].begin(op.waveform); + this->envelopes[i].delay(op.delayTime); + this->envelopes[i].attack(op.attackTime); + this->oscillators[i].amplitude(op.holdAmplitude); + this->envelopes[i].hold(op.holdTime); + this->envelopes[i].decay(op.decayTime); + this->envelopes[i].sustain(op.sustainAmplitude / op.holdAmplitude); + this->envelopes[i].release(op.releaseTime); // This feels wasteful 🙁 for (int j=0; jmixers[i].gain(j, p->gains[i][j]); + this->mixers[i].gain(j, p->gains[i][j]); } - v->outputMixer.gain(i, p->gains[i][NUM_OPERATORS]); + this->outputMixer.gain(i, p->gains[i][NUM_OPERATORS]); } - v->patch = p; + this->patch = p; } -void FMVoiceSetPitch(FMVoice *v, float freq) { +void FMVoice::SetPitch(float freq) { for (int i=0; i<4; i++) { - FMOperator op = v->patch->operators[i]; - v->oscillators[i].frequency(op.offset + (freq * op.multiplier)); + FMOperator op = this->patch->operators[i]; + this->oscillators[i].frequency(op.offset + (freq * op.multiplier)); } } -void FMVoiceNoteOn(FMVoice *v, float freq) { - FMVoiceSetPitch(v, freq); +void FMVoice::NoteOn(float freq) { + SetPitch(freq); for (int i=0; i<4; i++) { - v->envelopes[i].noteOn(); + this->envelopes[i].noteOn(); } - v->playing = true; + this->playing = true; } -void FMVoiceNoteOff(FMVoice *v) { +void FMVoice::NoteOff() { for (int i=0; i<4; i++) { - v->envelopes[i].noteOff(); + this->envelopes[i].noteOff(); } - v->playing = false; + this->playing = false; } diff --git a/synth.h b/synth.h index 8c35942..fc0d08f 100644 --- a/synth.h +++ b/synth.h @@ -80,14 +80,54 @@ typedef struct FMPatch { /** FMVoice sets up all the Audio objects for a voice. */ -typedef struct FMVoice { - AudioMixer4 mixers[NUM_OPERATORS]; - AudioSynthWaveformModulated oscillators[NUM_OPERATORS]; - AudioEffectEnvelope envelopes[NUM_OPERATORS]; - AudioMixer4 outputMixer; - FMPatch *patch; - bool playing; -} FMVoice; +class FMVoice { + public: + /** LoadPatch loads a patch into a voice. + */ + void LoadPatch(FMPatch *p); + + /** SetPitch sets the pitch (Hz) of a voice. + * + * This does not signal the envelope in any way. + * You would use this for a glissando, portamento, or pitch bend. + * In my bagpipe, this prevents "reed noise" when changing notes. + */ + void SetPitch(float pitch); + + /** SetModulation sets the modulation amount of a voice. + * + * What this means depends on the loaded patch. + * For a "normal" bagpipe patch, this would adjust the intensity of + * of a filter, or set the level of an oscillator. + * In an old-school keyboard patch, this would set the + * intensity of a Low Frequency Oscillator to set a vibrato. + */ + void setModulation(float level); + + /** NoteOn sets the pitch (Hz) of a voice, and starts in playing. + * + * This tells the envelope generators to begin. + * On a piano, this is what you would use when a key is pressed. + * In my bagpipe, this triggers "reed noise". + */ + void NoteOn(float pitch); + + /** NoteOff stops a note from playing. + * + * This turns the voice "off" by shutting down all the envelope generators. + * On a piano, this is what you would use when a key is released. + * In my bagpipe, this corresponds to all holes being closed. + */ + void NoteOff(); + + + AudioMixer4 mixers[NUM_OPERATORS]; + AudioSynthWaveformModulated oscillators[NUM_OPERATORS]; + AudioEffectEnvelope envelopes[NUM_OPERATORS]; + AudioMixer4 outputMixer; + FMPatch *patch; + bool playing; +}; /** FMOperatorWiring outputs AudioConnection initializers to wire one FM Operator */ @@ -108,30 +148,4 @@ typedef struct FMVoice { FMOperatorWiring(name, 2), \ FMOperatorWiring(name, 3) -/** FMVoiceLoadPatch loads a patch into a voice. - */ -void FMVoiceLoadPatch(FMVoice *v, FMPatch *p); -/** FMVoiceSetPitch sets the pitch (Hz) of a voice. - * - * This does not signal the envelope in any way. - * You would use this for a glissando, portamento, or pitch bend. - * In my bagpipe, this prevents "reed noise" when changing notes. - */ -void FMVoiceSetPitch(FMVoice *v, float pitch); - -/** FMVoiceNoteOn sets the pitch (Hz) of a voice, and starts in playing. - * - * This tells the envelope generators to begin. - * On a piano, this is what you would use when a key is pressed. - * In my bagpipe, this triggers "reed noise". - */ -void FMVoiceNoteOn(FMVoice *v, float pitch); - -/** FMVoiceNoteOff stops a note from playing. - * - * This turns the voice "off" by shutting down all the envelope generators. - * On a piano, this is what you would use when a key is released. - * In my bagpipe, this corresponds to all holes being closed. - */ -void FMVoiceNoteOff(FMVoice *v); diff --git a/uilleann.ino b/uilleann.ino index 1fd2fe1..18e39e7 100644 --- a/uilleann.ino +++ b/uilleann.ino @@ -128,8 +128,8 @@ void setup() { // Turn on drones for (int i=0; i<3; i++) { - FMVoiceLoadPatch(&Drones[i], &Bank[0]); - FMVoiceNoteOn(&Drones[i], JustPitches[NOTE_D4 - 12*i] + i); + Drones[i].LoadPatch(&Bank[0]); + Drones[i].NoteOn(JustPitches[NOTE_D4 - 12*i] + i); } // Turn on all mixer channels @@ -201,7 +201,7 @@ void updateTunables(uint8_t buttons, int note) { patch = (patch + bankSize) % bankSize; FMPatch *p = &Bank[patch]; - FMVoiceLoadPatch(&Chanter, p); + Chanter.LoadPatch(p); display.clearDisplay(); display.setCursor(0, 0); @@ -302,7 +302,7 @@ void loop() { if (silent) { - FMVoiceNoteOff(&Chanter); + Chanter.NoteOff(); } else { // Calculate pitch, and glissando pitch uint16_t pitch = JustPitches[note]; @@ -321,9 +321,9 @@ void loop() { } if (Chanter.playing) { - FMVoiceSetPitch(&Chanter, pitch); + Chanter.SetPitch(pitch); } else { - FMVoiceNoteOn(&Chanter, pitch); + Chanter.NoteOn(pitch); } }