class: mOperator
FM operator
Description
implements an FM operator using an oscillator (mOscil) and an envelope (mADSR). An mOperator can stand on its own or be chained to other mOperators to create complex FM sounds. An mOperator always returns a 16-bit output regardless of the bitrate of the wavetable used. update() must be called in updateControl and next() must be called in updateAudio. By default, an mOperator object will use the sin8192_int16 wavetable
Template Parameters
template <uint32_t NUM_CELLS = sin8192_int16_NUM_CELLS, class T=int16_t>NUM_CELLS: length of the table being used for your mOperator’s oscillator T: datatype of the table being used for your mOperator’s oscillator (probably int8_t or int16_t)
Class Methods
Constructor
mOperator(const T *TABLE_NAME = sin8192_int16_DATA)TABLE_NAME: data array of table for mOperator’s oscillator. Optional, defaults to sin8192_int16_DATA.
void noteOn(uint8_t note, uint8_t velocity)Sets frequency of oscillator and starts envelope at attack phase.
note: MIDI note (0-127)
velocity: volume (0-127)
void noteOff()Turns note off by moving envelope to release phase
void setTable(const T *TABLE_NAME)Sets table of mOperator’s oscillator. NOTE: if you are changing tables on the fly, all should be of the same length set in your object’s template (ie. if you start by using a table of length 2048, you shouldn’t switch to a table of length 8192)
void setFreq(float f_)Sets frequency of oscillator without triggering envelope.
void setFreqRatio(float r_)Sets the ratio this mOperator will play in relation to the frequency is is told to play (by setFreq or noteOn). This is useful when using multiple operators to build a single voice. For example, if you want one operator to always play an octave above another, you can set its frequency ratio to 2 and send the same MIDI notes to both. The default frequency ratio is 1.
float getFreqRatio()returns the mOperator’s current frequency ratio
void setFixedFreq(float fixed_freq)Used to take operator in and out of fixed frequency mode. This mode is useful when using the mOperator as an LFO in a voice, or for various sound effects.
- if fixed_freq is set to a non-zero value, mOperator will always play that frequency (ignoring frequencies from noteOn and setFreq)
- if fixed_freq is set to zero, operator will exit fixed frequency mode and respond to noteOn and setFreq like normal.
void setLoopingOn()Sets envelope to restart to attack the attack phase once reaching end of release phase.
void setLoopingOff()Sets envelope to stop once it reaches end of release phase;
void setPhaseSyncOn()When phase sync is enabled (which is the default) oscillator will reset to beginning of wavetable when noteOn is called
void setPhaseSyncOff()When phase sync is disabled, oscillator will not reset phase when noteOn is called
void setDroneOn()Enables drone mode, bypassing the envelope, playing continuously .
void setDroneOff()Disables drone mode. Envelope will control oscillator’s volume.
void setADSR(uint32_t attack_time, uint32_t decay_time, uint8_t sustain_level, uint32_t release_time)Sets ADSR envelope parameters
attack_time: attack time in ms
decay_time: decay time in ms
sustain_level: sustain level (0-255)
release_time: release time in ms
void setGain(uint16_t g_)Sets output gain of mOperator (0-255)
void update()MUST BE CALLED IN updateControl: Calculates envelope.
int32_t next(int32_t mod_input = 0)MUST BE CALLED IN updateAudio: Calculates and returns a 16-bit audio sample given a 16-bit frequency modulator signal. If no input is given, mOperator will oscillate without modulation. The easiest modulator signal to use is the output of another mOperator.
Example
// global declaration
mOperator carrier_operator;
mOperator modulator_operator;
// in setup()
carrier_operator.setADSR(10, 400, 160, 500);
modulator_operator.setADSR(1000, 400, 190, 500); // modulator_operator will slowly grow over one second
modulator_operator.setRatio(2);
modulator_operator.setGain(80);
// in updateControl
carrier_operator.update();
modulator_operator.update();
// in updateAudio
int mod_sample = modulator_operator.next();
int out_sample = carrier_operator.next(mod_sample);
// in updateTouch
if (pressed){
carrier_operator.noteOn(60, 100); // triggers a C when any pad is pressed
modulator_operator.noteOn(60, 100);
} else {
carrier_operator.noteOff();
modulator_operator.noteOff();
}