synthvoice
¶
Advanced synthio voices
Author(s): Cooper Dalrymple
Implementation Notes¶
Hardware:
Software and Dependencies:
Adafruit CircuitPython firmware for the supported boards: https://circuitpython.org/downloads
CircuitPython SynthWaveform library: https://github.com/dcooperdalrymple/CircuitPython_SynthWaveform
- class synthvoice.AREnvelope(attack_time: float = 0.05, release_time: float = 0.05, amount: float = 1.0)¶
A simple attack, sustain and release envelope using linear interpolation. Useful for controlling parameters of a
synthio.Note
object other than amplitude which acceptsynthio.BlockInput
values.- Parameters:
attack – The amount of time to go from 0.0 to the specified amount in seconds when the envelope is pressed. Must be greater than 0.0s. Default is 0.05s.
release – The amount of time to go from the specified amount back to 0.0 in seconds when the envelope is released. Must be greater than 0.0s. Default is 0.05s
amount – The level at which to rise or fall to when the envelope is pressed. Value is arbitrary and can be positive or negative, but 0.0 will result in no change. Default is 1.0.
- property amount: float¶
The level at which to rise or fall to when the envelope is pressed (or sustained value). If the envelope is currently in the attack/press state, the targeted value will be updated immediately. Valu7e is arbitrary and can be positive or negative, but 0.0 will result in no change.
- property attack_time: float¶
The rate of attack in seconds. When changing if the envelope is currently in the attack state, it will update the rate immediately. Must be greater than 0.0s.
- property block: synthio.BlockInput¶
Get the
synthio.BlockInput
object to be applied to a parameter.
- property blocks: tuple[synthio.BlockInput]¶
Get all
synthio.BlockInput
objects. In order for it to function properly, these blocks must be added to the primarysynthio.Synthesizer
object using synth.blocks.append(…).
- press()¶
Active the envelope by setting it into the “pressed” state. The envelope’s attack phase will start immediately.
- release()¶
Deactivate the envelope by setting it into the “released” state. The envelope’s release phase will start immediately.
- class synthvoice.LerpBlockInput(rate: float = 0.05, value: float = 0.0)¶
Creates and manages a
synthio.BlockInput
object to “lerp” (linear interpolation) between an old value and a new value. Useful for note frequency “glide” and custom envelopes.- Parameters:
rate – The speed at which to go between values, in seconds. Must be greater than 0.0s. Defaults to 0.05s.
value – The initial value. Defaults to 0.0.
Constructor method
- property block: synthio.BlockInput¶
Get the block input to be used with a
synthio.Note
object.
- property blocks: tuple[synthio.BlockInput]¶
Get all
synthio.BlockInput
objects. In order for it to function properly, these blocks must be added to the primarysynthio.Synthesizer
object using synth.blocks.append(…).
- class synthvoice.Voice(synthesizer: synthio.Synthesizer)¶
A “voice” to be used with a
synthio.Synthesizer
object. Manages one or multiplesynthio.Note
objects.The standard
Voice
class is not meant to be used directly but instead inherited by one of the provided voice classes or within a custom class. This class helps manage note frequency, velocity, and filter state and provides an interface with asynthio.Synthesizer
object.- Parameters:
synthesizer – The
synthio.Synthesizer
object this voice will be used with.
- property amplitude: float¶
The volume of the voice from 0.0 to 1.0. This method should be implemented within the child class.
- property blocks: tuple[synthio.BlockInput]¶
Get all
synthio.BlockInput
objects attributed to this voice.
- property filter_frequency: float¶
The frequency of the filter in hertz. The maximum value allowed and default is half of the sample rate (the Nyquist frequency).
- property filter_mode: synthio.FilterMode¶
The type of the filter. Defaults to
synthio.FilterMode.LOW_PASS
.
- property filter_resonance: float¶
The resonance of the filter (or Q factor) as a number starting from 0.7. Defaults to 0.7.
- property notes: tuple[synthio.Note]¶
Get all
synthio.Note
objects attributed to this voice.
- press(notenum: int, velocity: float | int = 1.0) bool ¶
Update the voice to be “pressed” with a specific MIDI note number and velocity. Returns whether or not a new note is received to avoid unnecessary retriggering. The envelope is updated with the new velocity value regardless. Updating
synthio.Note
objects should typically occur within the child class after calling this method and checking its return value.- Parameters:
notenum – The MIDI note number representing the note frequency.
velocity – The strength at which the note was received, between 0.0 and 1.0. Defaults to 1.0. If an
int
value is used, it will be divided by 127 assuming that it is a midi velocity value.
- release() bool ¶
Release the voice if a note is currently being played. Returns
True
if a note was released andFalse
if not.
- class synthvoice.oscillator.Oscillator(synthesizer: synthio.Synthesizer, root: float = 440.0)¶
A complex single-voice Oscillator with the following features: - amplitude & filter envelopes - LFOs (low-frequency oscillators) for amplitude (tremolo), filter, pitch (vibrato), & panning - pitch glide - waveform looping
- Parameters:
synthesizer – The
synthio.Synthesizer
object this voice will be used with.root – The root frequency used to calculate tuning. Defaults to 440.0hz. Changing this value will effect tuning properties.
- property amplitude: float¶
The relative amplitude of the oscillator from 0.0 to 1.0. An amplitude of 0 makes the oscillator inaudible. Defaults to 1.0.
- property attack_level: float¶
The level that the amplitude envelope will reach after the attack time has passed as a relative value of
amplitude
from 0.0 to 1.0. Defaults to 1.0.
- property attack_time: float¶
The rate of attack of the amplitude envelope in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property bend: float¶
The pitch bend value which changes the oscillator frequency by a relative amount. Positive and negative range is defined by
bend_range
. Defaults to 0.0.
- property bend_range: float¶
The maximum amount the oscillator frequency will “bend” when setting the
bend
property in octaves. Can be positive or negative, and thebend
property can scale this range in both directions. Defaults to 0.0Example settings: - 2.0 = up two octaves - -1.0 = down one octave - 1.0/12.0 = up one semitone (chromatic note)
- property blocks: tuple[synthio.BlockInput]¶
Get all
synthio.BlockInput
objects attributed to this voice.
- property coarse_tune: float¶
The amount of tuning from the root frequency of the oscillator (typically 440.0hz) in octaves. Ie: 1.0 = 880.hz, -2.0 = 110.0hz. Defaults to 0.0.
- property decay_time: float¶
The rate of decay after reaching the
attack_level
of the amplitude envelope in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property filter_amount: float¶
The level to add to the
filter_frequency
in hertz after the filter envelope attack time has passed. This value will be sustained untilrelease()
is called. Defaults to 0hz.
- property filter_attack_time: float¶
The rate of attack of the filter frequency envelope from
filter_frequency
tofilter_frequency
plusfilter_amount
in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property filter_delay: float¶
The amount of time to gradually increase the depth of the filter LFO in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property filter_depth: float¶
The maximum level of the filter LFO to add to
filter_frequency
in hertz in both positive and negative directions. Defaults to 0.0hz.
- property filter_release_time: float¶
The rate of release of the filter frequency envelope back to
filter_frequency
in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property fine_tune: float¶
The amount of tuning from the root frequency of the oscillator (typically 440.0hz) in semitones (1/12 of an octave). Ie: 1.0 = 466.16hz (A#4) and -1.0 = 415.30hz (G#4). Defaults to 0.0.
- property frequency: float¶
The frequency in hertz to set the oscillator to. Updating this value will active the frequency lerp block to gradually change the note frequency based on the glide settings of this voice.
- property glide: float¶
The length of time it takes for the oscillator to “glide” (transition) between frequencies in seconds.
- property notes: tuple[synthio.Note]¶
Get all
synthio.Note
objects attributed to this voice.
- property pan: float¶
The distribution of the oscillator amplitude in the channel(s) output from -1.0 (left) to 1.0 (right). Defaults to 0.0.
- property pan_delay: float¶
The amount of time to gradually increase the depth of the panning LFO in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property pan_depth: float¶
The depth of the panning LFO from 0.0 to 1.0. This value is added to
pan
. Negative values are allowed and will flip the phase of the LFO. Defaults to 0.0.
- property pitch_slew: float¶
The pitch offset in octaves at which the voice starts relative to the desired frequency when first pressed. Can be either positive or negative. Defaults to 0.0.
- property pitch_slew_time: float¶
The amount of time in seconds it takes for the voice to reach the desired pitch after starting with a relative
pitch_slew
adjustment. Must be greater than 0.0s. Defaults to 0.001s.
- press(notenum: int, velocity: float | int = 1.0) bool ¶
Update the voice to be “pressed” with a specific MIDI note number and velocity. Returns whether or not a new note is received to avoid unnecessary retriggering. The envelope is updated with the new velocity value regardless.
- Parameters:
notenum – The MIDI note number representing the note frequency.
velocity – The strength at which the note was received, between 0.0 and 1.0.
- release() bool ¶
Release the voice if a note is currently being played. Returns
True
if a note was released andFalse
if not.
- property release_time: float¶
The rate of decay of the amplitude envelope to 0.0 after
release()
is called in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property sustain_level: float¶
The level that the amplitude envelope will reach after the decay time has passed as a relative value of
amplitude
from 0.0 to 1.0. The note will sustain with this level untilrelease()
is called. Defaults to 0.75.
- property tremolo_delay: float¶
The amount of time to gradually increase the depth of the amplitude LFO in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property tremolo_depth: float¶
The depth of the amplitude LFO. This value is added to
amplitude
. Defaults to 0.0.
- property vibrato_delay: float¶
The amount of time to gradually increase the depth of the frequency LFO in seconds. Must be greater than 0.0s. Defaults to 0.001s.
- property vibrato_depth: float¶
The depth of the frequency LFO in octaves relative to the current note frequency and
bend
. Defaults to 0.0.
- property waveform: array | bytearray | bytes | memoryview | rgbmatrix.RGBMatrix | ulab.numpy.ndarray | None¶
The waveform of the oscillator.
- class synthvoice.sample.Sample(synthesizer: synthio.Synthesizer, looping: bool = True, file: str | None = None, max_size: int = 4096)¶
Voice which will play back an audio file. Handles pitch, looping points, and “.wav” file loading and inherits all properties and functionality of
synthvoice.oscillator.Oscillator
.- Parameters:
synthesizer – The
synthio.Synthesizer
object this voice will be used with.looping – Whether or not to continuously loop the sample or play it once when the voice is pressed. Defaults to true.
file – The path to the compatible audio file (16-bit integer “.wav”). Leave unset to initialize the voice without a specified sample. Defaults to
None
.max_size – The maximum number of samples to load into the waveform from the sample file.
- property duration: float¶
The length of the audio sample given the current state (includes note bend properties).
- property file: str | None¶
The path to a 16-bit signed integer audio “.wav” file within the virtual file system. The audio sample rate and root frequency will automatically be calculated bye the file properties and with an FFT algorithm. An invalid file type will raise
ValueError
.
- looping: bool = True¶
Whether or not to continuously loop the sample or play it once when the voice is pressed.
- press(notenum: int, velocity: float | int = 1.0) bool ¶
Update the voice to be “pressed” with a specific MIDI note number and velocity. Returns whether or not a new note is received to avoid unnecessary retriggering. The envelope is updated with the new velocity value regardless.
- Parameters:
notenum – The MIDI note number representing the note frequency.
velocity – The strength at which the note was received, between 0.0 and 1.0. Defaults to 1.0. If an
int
value is used, it will be divided by 127 assuming that it is a midi velocity value.
- synthvoice.sample.fft(data: ulab.numpy.ndarray, log: bool = True, length: int = 1024) ulab.numpy.ndarray ¶
Perform the Fourier Fast Transform (FFT) on data.
- Parameters:
data – The data to be processed, typically audio samples. The data type must be either
ulab.numpy.int16
orulab.numpy.uint16
or else aValueError
will be raised.log – Use the logarithmic function on the output to convert the result to decibels. Defaults to
True
.length – The resulting length of the spectrogram array. A larger value will be more precise but require more processing and RAM usage.
- synthvoice.sample.fftfreq(data: ulab.numpy.ndarray, sample_rate: int)¶
Use the Fast Fourier Transform to determine the peak frequency of the signal.
- Parameters:
data – The data to be processed, typically audio samples. The data type must be either
ulab.numpy.int16
orulab.numpy.uint16
or else aValueError
will be raised.sample_rate – The rate at which the data was recorded in hertz.
- synthvoice.sample.normalize(data: ulab.numpy.ndarray) ulab.numpy.ndarray ¶
Scale the data so that it reaches the maximum peak capable of the data type (+32767 for
ulab.numpy.int16
).- Parameters:
data – The data to be normalized, typically audio samples. The data type must be
ulab.numpy.int16
or else aValueError
will be raised.
- class synthvoice.percussive.ClosedHat(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a closed hi-hat cymbal using noise waveforms.
- class synthvoice.percussive.Cymbal(synthesizer: synthio.Synthesizer, time: float, frequency: float = 9500.0)¶
The base class to create cymbal sounds with variable timing.
- Parameters:
min_time – The minimum decay time in seconds. Must be greater than 0.0s.
max_time – The maximum decay time in seconds. Must be greater than min_time.
- class synthvoice.percussive.FloorTom(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a low or floor tom drum.
- class synthvoice.percussive.HighTom(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a high or left rack tom drum.
- class synthvoice.percussive.Kick(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a low frequency sine-wave kick drum.
- class synthvoice.percussive.MidTom(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a middle or right rack tom drum.
- class synthvoice.percussive.OpenHat(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing an open hi-hat cymbal using noise waveforms.
- class synthvoice.percussive.Ride(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a ride cymbal using noise waveforms.
- class synthvoice.percussive.Snare(synthesizer: synthio.Synthesizer)¶
A single-shot “analog” drum voice representing a snare drum using sine and noise waveforms.
- class synthvoice.percussive.Tom(synthesizer: synthio.Synthesizer, time: float, frequency: float)¶
The base class to create tom drum sounds with variable timing and frequency.
- Parameters:
min_time – The minimum decay time in seconds. Must be greater than 0.0s.
max_time – The maximum decay time in seconds. Must be greater than min_time.
min_frequency – The minimum frequency in hertz.
max_frequency – The maximum frequency in hertz.
- class synthvoice.percussive.Voice(synthesizer: synthio.Synthesizer, count: int = 3, filter_mode: synthio.FilterMode = synthio.FilterMode.LOW_PASS, filter_frequency: float = 20000.0, frequencies: tuple[float] = [], times: tuple[float] = [], waveforms: tuple[array | bytearray | bytes | memoryview | rgbmatrix.RGBMatrix | ulab.numpy.ndarray] | array | bytearray | bytes | memoryview | rgbmatrix.RGBMatrix | ulab.numpy.ndarray = [])¶
Base single-shot “analog” drum voice used by other classes within the percussive module. Handles envelope times, tuning, waveforms, etc. for multiple
synthio.Note
objects.- Parameters:
count – The number of
synthio.Note
objects to generate. Defaults to 3.filter_mode – The type of filter to use. Defaults to
synthio.FilterMode.LOW_PASS
.filter_frequency – The exact frequency of the filter of all
synthio.Note
objects in hertz. Defaults to 20000hz.frequencies – A list of the frequencies corresponding to each
synthio.Note
object in hertz. Voice doesn’t respond to the note frequency when pressed and instead uses these constant frequencies. Defaults to 440.0hz if not provided.times – A list of decay times corresponding to each
synthio.Note
objects’ amplitude envelope in seconds. Defaults to 1.0s for all notes if not provided.waveforms – A list of waveforms corresponding to each
synthio.Note
object asnumpy.int16
arrays. Defaults to a square waveform for each note.
- property blocks: tuple[synthio.BlockInput]¶
Get all
synthio.BlockInput
objects attributed to this voice.
- property decay_time: float¶
The amount of decay of the amplitude envelope relative to the initial decay time. 0.0 is the default amount of decay, 1.0 is double the decay, and -1.0 is half the decay.
- property notes: tuple[synthio.Note]¶
Get all
synthio.Note
objects attributed to this voice.
- press(velocity: float | int = 1.0) bool ¶
Update the voice to be “pressed”. For percussive voices, this will begin the playback of the voice.
- Parameters:
velocity – The strength at which the note was received, between 0.0 and 1.0.
- release() bool ¶
Release the voice.
synthvoice.percussive.Voice
objects typically don’t implement this operation because of their “single-shot” nature and will always returnFalse
.
- property tune: float¶
The amount of tuning form the root frequencies of the voice in semitones (1/12 of an octave). Defaults to 0.0.
- property waveforms: tuple[array | bytearray | bytes | memoryview | rgbmatrix.RGBMatrix | ulab.numpy.ndarray]¶
The note waveforms as
ulab.numpy.ndarray
objects with theulab.numpy.int16
data type.