FMVoice is now a class
This commit is contained in:
parent
458b9eb891
commit
e565fb35b6
46
synth.cpp
46
synth.cpp
|
@ -1,47 +1,47 @@
|
||||||
#include "synth.h"
|
#include "synth.h"
|
||||||
#include "synth_waveform.h"
|
#include "synth_waveform.h"
|
||||||
|
|
||||||
void FMVoiceLoadPatch(FMVoice *v, FMPatch *p) {
|
void FMVoice::LoadPatch(FMPatch *p) {
|
||||||
for (int i=0; i<NUM_OPERATORS; i++) {
|
for (int i=0; i<NUM_OPERATORS; i++) {
|
||||||
FMOperator op = p->operators[i];
|
FMOperator op = p->operators[i];
|
||||||
|
|
||||||
v->oscillators[i].frequencyModulation(1);
|
this->oscillators[i].frequencyModulation(1);
|
||||||
v->oscillators[i].begin(op.waveform);
|
this->oscillators[i].begin(op.waveform);
|
||||||
v->envelopes[i].delay(op.delayTime);
|
this->envelopes[i].delay(op.delayTime);
|
||||||
v->envelopes[i].attack(op.attackTime);
|
this->envelopes[i].attack(op.attackTime);
|
||||||
v->oscillators[i].amplitude(op.holdAmplitude);
|
this->oscillators[i].amplitude(op.holdAmplitude);
|
||||||
v->envelopes[i].hold(op.holdTime);
|
this->envelopes[i].hold(op.holdTime);
|
||||||
v->envelopes[i].decay(op.decayTime);
|
this->envelopes[i].decay(op.decayTime);
|
||||||
v->envelopes[i].sustain(op.sustainAmplitude / op.holdAmplitude);
|
this->envelopes[i].sustain(op.sustainAmplitude / op.holdAmplitude);
|
||||||
v->envelopes[i].release(op.releaseTime);
|
this->envelopes[i].release(op.releaseTime);
|
||||||
|
|
||||||
// This feels wasteful 🙁
|
// This feels wasteful 🙁
|
||||||
for (int j=0; j<NUM_OPERATORS; j++) {
|
for (int j=0; j<NUM_OPERATORS; j++) {
|
||||||
v->mixers[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++) {
|
for (int i=0; i<4; i++) {
|
||||||
FMOperator op = v->patch->operators[i];
|
FMOperator op = this->patch->operators[i];
|
||||||
v->oscillators[i].frequency(op.offset + (freq * op.multiplier));
|
this->oscillators[i].frequency(op.offset + (freq * op.multiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMVoiceNoteOn(FMVoice *v, float freq) {
|
void FMVoice::NoteOn(float freq) {
|
||||||
FMVoiceSetPitch(v, freq);
|
SetPitch(freq);
|
||||||
for (int i=0; i<4; i++) {
|
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++) {
|
for (int i=0; i<4; i++) {
|
||||||
v->envelopes[i].noteOff();
|
this->envelopes[i].noteOff();
|
||||||
}
|
}
|
||||||
v->playing = false;
|
this->playing = false;
|
||||||
}
|
}
|
||||||
|
|
70
synth.h
70
synth.h
|
@ -80,14 +80,54 @@ typedef struct FMPatch {
|
||||||
|
|
||||||
/** FMVoice sets up all the Audio objects for a voice.
|
/** FMVoice sets up all the Audio objects for a voice.
|
||||||
*/
|
*/
|
||||||
typedef struct 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];
|
AudioMixer4 mixers[NUM_OPERATORS];
|
||||||
AudioSynthWaveformModulated oscillators[NUM_OPERATORS];
|
AudioSynthWaveformModulated oscillators[NUM_OPERATORS];
|
||||||
AudioEffectEnvelope envelopes[NUM_OPERATORS];
|
AudioEffectEnvelope envelopes[NUM_OPERATORS];
|
||||||
AudioMixer4 outputMixer;
|
AudioMixer4 outputMixer;
|
||||||
FMPatch *patch;
|
FMPatch *patch;
|
||||||
bool playing;
|
bool playing;
|
||||||
} FMVoice;
|
};
|
||||||
|
|
||||||
/** FMOperatorWiring outputs AudioConnection initializers to wire one FM Operator
|
/** FMOperatorWiring outputs AudioConnection initializers to wire one FM Operator
|
||||||
*/
|
*/
|
||||||
|
@ -108,30 +148,4 @@ typedef struct FMVoice {
|
||||||
FMOperatorWiring(name, 2), \
|
FMOperatorWiring(name, 2), \
|
||||||
FMOperatorWiring(name, 3)
|
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);
|
|
||||||
|
|
12
uilleann.ino
12
uilleann.ino
|
@ -128,8 +128,8 @@ void setup() {
|
||||||
|
|
||||||
// Turn on drones
|
// Turn on drones
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
FMVoiceLoadPatch(&Drones[i], &Bank[0]);
|
Drones[i].LoadPatch(&Bank[0]);
|
||||||
FMVoiceNoteOn(&Drones[i], JustPitches[NOTE_D4 - 12*i] + i);
|
Drones[i].NoteOn(JustPitches[NOTE_D4 - 12*i] + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn on all mixer channels
|
// Turn on all mixer channels
|
||||||
|
@ -201,7 +201,7 @@ void updateTunables(uint8_t buttons, int note) {
|
||||||
patch = (patch + bankSize) % bankSize;
|
patch = (patch + bankSize) % bankSize;
|
||||||
|
|
||||||
FMPatch *p = &Bank[patch];
|
FMPatch *p = &Bank[patch];
|
||||||
FMVoiceLoadPatch(&Chanter, p);
|
Chanter.LoadPatch(p);
|
||||||
|
|
||||||
display.clearDisplay();
|
display.clearDisplay();
|
||||||
display.setCursor(0, 0);
|
display.setCursor(0, 0);
|
||||||
|
@ -302,7 +302,7 @@ void loop() {
|
||||||
|
|
||||||
|
|
||||||
if (silent) {
|
if (silent) {
|
||||||
FMVoiceNoteOff(&Chanter);
|
Chanter.NoteOff();
|
||||||
} else {
|
} else {
|
||||||
// Calculate pitch, and glissando pitch
|
// Calculate pitch, and glissando pitch
|
||||||
uint16_t pitch = JustPitches[note];
|
uint16_t pitch = JustPitches[note];
|
||||||
|
@ -321,9 +321,9 @@ void loop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Chanter.playing) {
|
if (Chanter.playing) {
|
||||||
FMVoiceSetPitch(&Chanter, pitch);
|
Chanter.SetPitch(pitch);
|
||||||
} else {
|
} else {
|
||||||
FMVoiceNoteOn(&Chanter, pitch);
|
Chanter.NoteOn(pitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue