This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
#define NUM_OPERATORS 4
/** FMOperator defines all settable paramaters to an operator.
* An FM operator consists of:
* - An input
* - An oscillator
* - An envelope generator
* Frequency Modulation happens by chaining oscillators together,
* using the output of one to modulate the frequency of the next.
* Oscillators generate waveforms in a shape defined by
* `synth_waveform.h`. WAVEFORM_SINE is a good one to start with.
* Other sensible options are SAWTOOTH, SQUARE, and TRIANGLE.
* Frequency for an oscillator is calculated with:
* offset + (voiceFrequency × multiplier)
* Oscillator frequency is then modulated by the level obtained
* by the input mixer: level of 1.0 shifts frequency up by
* 8 octaves, level of -1.0 shifts frequency down by 8 octaves.
* The envelope modifies amplitude of the oscillator output,
* using the following rules:
* - stay at 0 until Note On
* - stay at 0 for `delayTime` milliseconds
* - linear increase to `holdAmplitude` for `attackTime` milliseconds
* - stay at `holdAmplitude` for `holdTime` milliseconds
* - linear decrease to `sustainAmplitude` for `decayTime` milliseconds
* - stay at `sustainAmplitude` until Note Off
* - linear decrease to 0 for `releaseTime` milliseconds
/** FMPatch defines all parameters to a voice patch.
* This defines the "sound" of an FM voice,
* just like a "Patch" does in a hardware synthesizer.
* I think of a "patch" being the physical cables that
* connect oscillators together, and to the output mixer.
* Each operator has NUM_OPERATORS input gains,
* one output gain (to the voice output mixer),
* and NUM_OPERATORS operators.
* Historical FM synthisizers,
* such as the DX7 or DX9,
* used "algorithms" to patch operators into one another:
* this is done with 0.0 or 1.0 values to the gains.
* The "feedback" on operator 4 of the DX9
* can be accomplished by patching an operator into itself.
/** FMVoice sets up all the Audio objects for a voice.
/** LoadPatch loads a patch into a voice.
/** 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.
/** GetPitch returns the pitch (Hz) of a voice.
/** 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.
/** 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".
/** 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.