TigerBalm2
Member
I'm really enjoying Teensy and the user friendliness of the Audio Library has "unlocked" for me the ability to code my own synthesizer. (I'm a mechanical engineer by training)
As I transition from monophonic to polyphonic, it is getting hard to manage the sheer number of audio objects in my code. Each voice needs multiple oscillators, mixers, envelopes, etc. I wanted to make a "Voice" class that has audio objects as member variables, which would greatly simplify my code. I don't know how to do that, so here's what I landed on: my Voice object has POINTERS to audio objects as member variables. I still use the audio GUI to generate code for my big polyphonic audio graph and insert that at the top of my main.cpp. Then, I instanciate each of my voices and pass audio object pointers into their constructor functions.
After this hard coded plumbing, the voice objects work well and make all the following code simpler. The problem: if I want to add or remove audio object pointers from the voice class I need to edit each voice in the GUI tool and update all the hard coded plumping. It would be great to make my voice object contain the audio objects and audio connections as member variables. Also, the member objects should instanciate when I instanciate the voice.
Is that possible? I saw Paul's tutorial about making new audio objects for the audio library. That article is a little too advanced for me and it doesn't address this question of nested audio objects. Can anyone please point me in the right direction? Thank you! Below is a picture of my audio graph and the Voice class definition.
As I transition from monophonic to polyphonic, it is getting hard to manage the sheer number of audio objects in my code. Each voice needs multiple oscillators, mixers, envelopes, etc. I wanted to make a "Voice" class that has audio objects as member variables, which would greatly simplify my code. I don't know how to do that, so here's what I landed on: my Voice object has POINTERS to audio objects as member variables. I still use the audio GUI to generate code for my big polyphonic audio graph and insert that at the top of my main.cpp. Then, I instanciate each of my voices and pass audio object pointers into their constructor functions.
After this hard coded plumbing, the voice objects work well and make all the following code simpler. The problem: if I want to add or remove audio object pointers from the voice class I need to edit each voice in the GUI tool and update all the hard coded plumping. It would be great to make my voice object contain the audio objects and audio connections as member variables. Also, the member objects should instanciate when I instanciate the voice.
Is that possible? I saw Paul's tutorial about making new audio objects for the audio library. That article is a little too advanced for me and it doesn't address this question of nested audio objects. Can anyone please point me in the right direction? Thank you! Below is a picture of my audio graph and the Voice class definition.
Code:
class Voice
{
public:
Voice (AudioSynthWaveformModulated * oscAPtr,
AudioSynthWaveformModulated * oscBPtr,
AudioSynthNoiseWhite * noisePtr,
AudioMixer4 * mixAPtr,
AudioEffectEnvelope * envPtr,
AudioAmplifier * ampPtr,
AudioFilterStateVariable * filterPtr);
int noteOn;
int attack;
int release;
int xMod;
int yMod;
int zMod;
int noteNum;
int velocity;
//One pointer per audio object
AudioSynthWaveformModulated * oscA;
AudioSynthWaveformModulated * oscB;
AudioSynthNoiseWhite * noise;
AudioMixer4 * mixA;
AudioEffectEnvelope * env;
AudioAmplifier * amp;
AudioFilterStateVariable * filter;
void begin(); //initialize things
};
Voice::Voice(AudioSynthWaveformModulated * oscAPtr,
AudioSynthWaveformModulated * oscBPtr,
AudioSynthNoiseWhite * noisePtr,
AudioMixer4 * mixAPtr,
AudioEffectEnvelope * envPtr,
AudioAmplifier * ampPtr,
AudioFilterStateVariable * filterPtr) {
noteOn = 0;
attack = 0;
release = 0;
xMod = 0;
yMod = 0;
zMod = 0;
noteNum = 0;
velocity = 0;
//assign all the audio object pointers to member vars
oscA = oscAPtr;
oscB = oscBPtr;
noise = noisePtr;
mixA = mixAPtr;
env = envPtr;
amp = ampPtr;
filter = filterPtr;
}
void Voice::begin() {
oscA->begin(1,440,WAVEFORM_SAWTOOTH);
oscB->begin(0.9,440,WAVEFORM_SQUARE);
noise->amplitude(0.7);
mixA->gain(0,.7);
mixA->gain(1,.7);
mixA->gain(2,.2);
//setup envelope
env->delay(0);
env->attack(10);
env->decay(0);
env->sustain(1.0);
env->release(10);
//setup amp
amp->gain(0.7);
filter->frequency(10000);
filter->resonance(0.7);
}
//Voice Object Instantiation
const int numVoices = 4;
Voice voice[] = {
Voice(&oscA1,&oscB1,&noise1,&mixA1,&env1,&1,&filter1),
Voice(&oscA2,&oscB2,&noise2,&mixA2,&env2,&2,&filter2),
Voice(&oscA3,&oscB3,&noise3,&mixA3,&env3,&3,&filter3),
Voice(&oscA4,&oscB4,&noise4,&mixA4,&env4,&4,&filter4)
};