Intrinsic functions
namespace soul::intrinsics
The intrinsics
namespace contains low-level, commonly-used functions.
This is a special-case namespace, as the functions inside it can be used without needing to specify their namespace (i.e. you can just write abs(x)
, no need to write soul::intrinsics::abs(x)
).
Many of these functions have reference implementations defined in this file, but which will be substituted for more optimal implementations by a JIT engine if possible. The [[intrin]]
annotation is used as a hint to the performer back-end that this function should be replaced by a native implementation if one is available. (Note that some of the functions here have non-functional implementations and rely on the performer to use a native implementation for them to work at all).
Functions
abs
Familiar abs() function, accepting most scalar types.
T.removeReference abs<T> (T n)
max
Returns the greater of two scalar values.
T.removeReference max<T> (T a,
T b)
min
Returns the lesser of two scalar values.
T.removeReference min<T> (T a,
T b)
min
Returns the lesser of two scalar values.
int32 min (int32 a,
int32 b)
clamp
Clamps a scalar value to the nearest value within a given range.
T.removeReference clamp<T> (T n,
T low,
T high)
wrap
Performs a negative-number-aware modulo operation to wrap a number to a zero-based range.
T.removeReference wrap<T> (T n,
T range)
wrap
Performs a negative-number-aware integer modulo operation.
int32 wrap (int32 n,
int32 range)
floor
Performs a C++-compatible floor function on a scalar floating point value.
T.removeReference floor<T> (T n)
ceil
Performs a C++-compatible ceil function on a scalar floating point value.
T.removeReference ceil<T> (T n)
lerp
Returns a linearly-interpolated value between two scalar values.
T.removeReference lerp<T> (T start,
T stop,
T amount)
fmod
Performs a C++-compatible fmod function on some scalar floating point values.
T.removeReference fmod<T> (T x,
T y)
remainder
Performs a C++-compatible remainder function on some scalar floating point values.
T.removeReference remainder<T> (T x,
T y)
sqrt
Returns the square root of a scalar floating point value.
T.removeReference sqrt<T> (T n)
pow
Raises a scalar floating point value to the given power.
T.removeReference pow<T> (T a,
T b)
exp
Returns the exponential of a scalar floating point value.
T.removeReference exp<T> (T n)
log
Returns the log-e of a scalar floating point value.
T.removeReference log<T> (T n)
log10
Returns the log 10 of a scalar floating point value.
T.removeReference log10<T> (T n)
roundToInt
Rounds a floating point number up or down to the nearest integer.
int32 roundToInt (float32 n)
roundToInt
Rounds a floating point number up or down to the nearest integer.
int64 roundToInt (float64 n)
isnan
Returns true if the floating point argument is a NaN.
bool isnan<T> (T n)
isinf
Returns true if the floating point argument is an INF.
bool isinf<T> (T n)
addModulo2Pi
Adds a delta to a value, and returns the resulting value modulo PI/2. A typical use-case for this is in incrementing the phase of an oscillator.
T.removeReference addModulo2Pi<T> (T value,
T increment)
sum
Returns the sum of an array or vector of scalar values.
T.elementType sum<T> (T t)
product
Returns the product of an array or vector of scalar values.
T.elementType product<T> (T t)
read
Reads an element from an array, allowing the index to be any type of floating point type. If a floating point index is used, it will be rounded down to an integer index - for an interpolated read operation, see readLinearInterpolated(). Indexes beyond the range of the array will be wrapped.
Array.elementType read<Array, IndexType> (const Array& array,
IndexType index)
readLinearInterpolated
Reads a linearly-interpolated value from an array of some kind of scalar values (probably a float or float-vector type). Indexes beyond the range of the array will be wrapped.
Array.elementType readLinearInterpolated<Array, IndexType> (const Array& array,
IndexType index)
get_array_size
NB: this is used internally, not something you'd want to call from user code
int32 get_array_size<Array> (const Array& array)
Miscellaneous audio utilities
This module is a collection of commonly-used audio helper functions and types.
namespace soul
Functions
dBtoGain
Converts a decibel level to a gain factor.
float32 dBtoGain (float32 decibels)
dBtoGain
Converts a decibel level to a gain factor.
float64 dBtoGain (float64 decibels)
gainTodB
Converts a gain factor to a decibel level.
float32 gainTodB (float32 gain)
gainTodB
Converts a gain factor to a decibel level.
float64 gainTodB (float64 gain)
noteNumberToFrequency
Converts a MIDI note (usually in the range 0-127) to a frequency in Hz.
float32 noteNumberToFrequency (int32 note)
noteNumberToFrequency
Converts a MIDI note (usually in the range 0-127) to a frequency in Hz.
float32 noteNumberToFrequency (float32 note)
frequencyToNoteNumber
Converts a frequency in Hz to an equivalent MIDI note number.
float32 frequencyToNoteNumber (float32 frequency)
getSpeedRatioForPitchedSample
Returns the ratio by which a sample's playback must be sped-up in order to map from its native sample-rate and note to a target sample-rate and note.
float64 getSpeedRatioForPitchedSample (float64 sourceSampleRate,
float32 sourceMIDINote,
float64 targetSampleRate,
float32 targetMIDINote)
tau2pole
Returns the coefficient for a filter pole, based on a t60 decay time in seconds.
float64 tau2pole (float64 t60,
float64 sampleRate)
tau2pole
Returns the coefficient for a filter pole, based on a t60 decay time in seconds.
float32 tau2pole (float32 t60,
float32 sampleRate)
pole2tau
Returns the t60 decay time in seconds for a filter pole coefficient in the range 0 to 1.
float64 pole2tau (float64 pole,
float64 sampleRate)
pole2tau
Returns the t60 decay time in seconds for a filter pole coefficient in the range 0 to 1.
float32 pole2tau (float32 pole,
float32 sampleRate)
namespace soul::audio_samples
This namespace contains some handy stuctures to use when declaring external
variables which are going to be loaded with data from audio files.
Structures
An external
variable declared with the type soul::audio_samples::Mono
can be loaded with monoised data from an audio file.
struct Mono
{
}
An external
variable declared with the type soul::audio_samples::Stereo
can be loaded with stereo data from an audio file.
struct Stereo
{
}
namespace soul::pan_law
This namespace contains various pan-related helper functions
Functions
linear
Applies a simple linear pan law to convert a pan position (-1.0 to 1.0) to a (left, right) pair of stereo gains.
float32<2> linear (float32 pan)
centre3dB
Applies a 3dB-centre pan law to convert a pan position (-1.0 to 1.0) to a (left, right) pair of stereo gains.
float32<2> centre3dB (float32 pan)
namespace soul::smoother
Functions for applying a smoothing filter on a changing value. A smoother is useful for avoiding discontinuities in control values such as parameter changes, etc.
Structures
struct State
{
}
Musical note utilities
This module contains various structs which can be used to model note-control events coming from sources such as MIDI keyboards.
The SOUL policy is to keep the use of actual MIDI to a minimum, so we encourage incoming MIDI data to be converted into these strongly-typed structures, and to use them internally, rather than attempting to work with MIDI bytes like it's the 1980s.
namespace soul::note_events
This namespace contains some types which are handy for representing synthesiser note events. They do a similar job to MIDI events, but as strongly-typed structs instead of a group of bytes. Things like the midi::MPEParser class generate them.
The events do contain a channel number, in the same way that MIDI does, but there are no restrictions on its range.
Structures
Represents a note-on (key-down) event.
struct NoteOn
{
}
Represents a note-off (key-up) event.
struct NoteOff
{
}
Represents a change to the pitch that should be applied to any notes being played on the channel specified.
struct PitchBend
{
}
Represents a change to the pressure that should be applied to any notes being played on the channel specified.
struct Pressure
{
}
Represents a change to the Y-axis parameter that should be applied to any notes being played on the channel specified.
struct Slide
{
}
Represents a change to a user-defined control parameter that should be applied to any notes being played on the channel specified.
struct Control
{
}
namespace soul::voice_allocators
Simple voice allocation helpers, which take a single stream of input events, and redirect them to an array of target voice processors.
Specialisation Parameters
namespace soul::voice_allocators (int32 mpeMasterChannel = 0)
processor soul::voice_allocators::Basic
A simple voice-allocator which will find either an inactive voice, or the least-recently used active voice if it needs to steal one.
Specialisation Parameters
processor soul::voice_allocators::Basic (int32 voiceCount)
Inputs
Outputs
Structures
struct VoiceInfo
{
}
Variables
int32 nextAllocatedVoiceAge = 1000000000
int32 nextUnallocatedVoiceAge = 1
int32 sustainCC = 64
VoiceInfo[ voiceCount] voiceInfo
bool[16] channelSustainActive
bool masterSustainActive
Mix and gain control utilities
This file provides a set of processors for common tasks like mixing together sources, applying fixed gains, or applying envelope shapes.
namespace soul::mixers
This namespace contains a set of processors for common tasks like mixing together sources.
processor soul::mixers::FixedSum
Simple processor which adds two sources together using fixed gains for each source.
Specialisation Parameters
processor soul::mixers::FixedSum (using SampleType,
float32 gain1,
float32 gain2)
Inputs
- stream in1 (SampleType)
- stream in2 (SampleType)
Outputs
- stream out (SampleType)
processor soul::mixers::DynamicSum
Simple processor which adds two sources together using streams to control the gains to apply to each source.
Specialisation Parameters
processor soul::mixers::DynamicSum (using SampleType)
Inputs
- stream in1 (SampleType)
- stream in2 (SampleType)
- stream gain1 (float32)
- stream gain2 (float32)
Outputs
- stream out (SampleType)
processor soul::mixers::DynamicMix
Simple processor which mixes together two sources, using a stream of values to indicate the ratio.
The mixRange constant allows you to set the range of values that will be passed in the mix stream, so e.g. mixRange = 1.0 means that mix will be in the range 0 to 1, and mixRange = 100 means the values will be 0 to 100. The mix stream is expected to contain values between 0 and mixRange, where mix = 0 produces 100% in1, and mix = mixRange produces 100% in2.
Specialisation Parameters
processor soul::mixers::DynamicMix (using SampleType,
float32 mixRange)
Inputs
- stream in1 (SampleType)
- stream in2 (SampleType)
- stream mix (float32)
Outputs
- stream out (SampleType)
namespace soul::gain
Utility processors for common tasks like applying gain in various ways.
processor soul::gain::FixedGain
Simple processor which applies a fixed gain to a signal.
Specialisation Parameters
processor soul::gain::FixedGain (using SampleType,
float32 fixedGain)
Inputs
- stream in (SampleType)
Outputs
- stream out (SampleType)
processor soul::gain::DynamicGain
Simple processor which applies a changeable gain level to a signal.
Specialisation Parameters
processor soul::gain::DynamicGain (using SampleType)
Inputs
- stream in (SampleType)
- stream gain (float32)
Outputs
- stream out (SampleType)
processor soul::gain::SmoothedGainParameter
Converts an input event parameter in decibels to a smoothed stream of raw gain levels.
Specialisation Parameters
processor soul::gain::SmoothedGainParameter (float32 slewRateSeconds)
Inputs
- event volume (float32)
Outputs
- stream gain (float32)
Variables
float32 targetGain
float32 currentGain
float32 increment
int32 remainingRampSamples
graph soul::gain::SmoothedGain
A graph that combines DynamicGain and SmoothedGainParameter
Specialisation Parameters
graph soul::gain::SmoothedGain (float32 slewRateSeconds = 0.1f)
Inputs
- stream in (float32)
- volume ()
Outputs
- stream out (float32)
Processor Instances
gainProcessor = soul::gain::DynamicGain float32
gainParameter = soul::gain::SmoothedGainParameter slewRateSeconds
namespace soul::envelope
Generators for common envelope shapes.
processor soul::envelope::FixedAttackReleaseEnvelope
Creates an envelope which applies convex attack and release curves based on a stream of NoteOn and NoteOff events.
The envelope implements fixed-length attack and release ramps where the hold level is based on the velocity of the triggering NoteOn event, multiplied by the holdLevelMultiplier parameter.
Specialisation Parameters
processor soul::envelope::FixedAttackReleaseEnvelope (float32 holdLevelMultiplier,
float32 attackTimeSeconds,
float32 releaseTimeSeconds)
Inputs
- event noteIn (soul::note_events::NoteOn, soul::note_events::NoteOff)
Outputs
- stream levelOut (float32)
Variables
bool active = false
float32 targetLevel
RNGs and noise-generators
This module contains a range of simple RNG and noise generating functions and processors.
namespace soul::random
This namespace contains some random number generation helpers. We're assuming that nobody's going to be using these RNGs for security-critical cryptographic applications. All the algorithms here are chosen to be fast, and definitely not cryptographically strong!
Structures
State for a Park-Miller random number generator.
struct RandomNumberState
{
The current seed.
Top tip: when generating a seed, you might want to use the processor.id
constant, to make sure that each instance of a processor has a differently-seeded RNG. If you want the RNG to be different each time the program runs, you could also throw the processor.session
constant into the mix too.
For example:
processor MyProcessorUsingRandomNumbers
{
...etc...
soul::random::RandomNumberState rng;
let mySeed = 12345; // Whenever seeding a RNG, you should pick a 'salt' value
// that's as unique as possible
void run()
{
// Initialising it like this will produce the same sequence of numbers for
// every instance of this processor:
rng.reset (mySeed);
// This will result in each instance of this processor generating a different
// sequence, but each time you load and run the program, you may get the
// same sequences as the last run:
rng.reset (processor.id + mySeed);
// This will result in each instance of this processor generating the same
// sequence, but it will be different each time you load and run the program:
rng.reset (processor.session + mySeed);
// This will result in each instance of this processor producing a different
// sequence, and each will also be different each time you load and run the program:
rng.reset (processor.session + processor.id + mySeed);
}
}
}
Functions
reset
Resets an RNG state object with the given seed value.
void reset (RandomNumberState& state,
int64 seed)
getNextInt32
Returns the next number in the full 32-bit integer range.
int32 getNextInt32 (RandomNumberState& state)
getNextUnipolar
Advances the given RNG state and returns a value 0 to 1.
float32 getNextUnipolar (RandomNumberState& state)
getNextBipolar
Advances the given RNG state and returns a value -1 to 1.
float32 getNextBipolar (RandomNumberState& state)
namespace soul::noise
This namespace contains generators for various flavours of noise.
processor soul::noise::White
White noise generator
Outputs
- stream out (float32)
processor soul::noise::Brown
Brown noise generator
Outputs
- stream out (float32)
processor soul::noise::Pink
Pink noise generator
Outputs
- stream out (float32)
Timeline event utilities
The timeline
namespace contains various structs and functions which are used when dealing with positions and tempos along a timeline.
namespace soul::timeline
The timeline
namespace contains various structs and functions which are used when dealing with positions and tempos along a timeline.
Structures
Represents a simple time-signature.
struct TimeSignature
{
}
Represents a tempo in BPM.
struct Tempo
{
}
Represents the state of a host which can play timeline-based material.
struct TransportState
{
In the absence of enums, the valid values for the state are: 0 = stopped, 1 = playing, 2 = recording.
}
Represents a position along a timeline, in terms of frames and also (where appropriate) quarter notes.
struct Position
{
A number of frames from the start of the timeline.
The number of quarter-notes since the beginning of the timeline. A host may not have a meaningful value for this, so it may just be 0. Bear in mind that a timeline may contain multiple changes of tempo and time-signature, so this value will not necessarily keep increasing at a constant rate.
The number of quarter-notes from the beginning of the timeline to the start of the current bar. A host may not have a meaningful value for this, so it may just be 0. You can subtract this from currentQuarterNote to find out how which quarter-note the position represents within the current bar.
}
Functions
quarterNotesPerBeat
float32 quarterNotesPerBeat (TimeSignature timeSig)
beatsPerQuarterNote
float32 beatsPerQuarterNote (TimeSignature timeSig)
secondsPerBeat
float32 secondsPerBeat (Tempo tempo)
secondsPerQuarterNote
float32 secondsPerQuarterNote (Tempo tempo,
TimeSignature timeSig)
framesPerBeat
float64 framesPerBeat (Tempo tempo,
float64 sampleRate)
framesPerQuarterNote
float64 framesPerQuarterNote (Tempo tempo,
TimeSignature timeSig,
float64 sampleRate)
isStopped
bool isStopped (TransportState t)
isPlaying
bool isPlaying (TransportState t)
isRecording
bool isRecording (TransportState t)
Oscillators
This module contains a collection of oscillator algorithms for generating various wave-shapes. The collection covers low frequency designs and high quality alias free algotithms.
namespace soul::oscillators
The oscillators
namespace is parameterised with a SampleType
and PhaseType
. The SampleType
specifies the output type, and can be either float32
or float64
. The PhaseType
is used internally to track phase position, so higher resolution data types can be used to reduce frequency inaccuracy for very critical applications.
By default the SampleType
and PhaseType
are float32.
Specialisation Parameters
namespace soul::oscillators (using SampleType = float32,
using PhaseType = float32)
Variables
float32 minFreqHz = 0.0f
float32 maxFreqHz = 22000.0f
float32 defaultFreqHz = 1000.0f
namespace soul::oscillators::phasor
A unipolar ramp (phasor) oscillator. This is a non-bandlimited oscillator that will cause aliasing, but is used internally by the BLEP oscillator.
Structures
processor soul::oscillators::phasor::Processor
A processor that produces a stream of phase values as its output.
Specialisation Parameters
processor soul::oscillators::phasor::Processor (float32 initialFrequency = 1000)
Inputs
- event frequencyIn (float32)
Outputs
- stream out (SampleType)
Variables
State s
processor soul::oscillators::Sine
A simple sinewave oscillator which receives input events to control its frequency.
Specialisation Parameters
processor soul::oscillators::Sine (float32 initialFrequency = 1000)
Inputs
- event frequencyIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 phaseIncrement = float (initialFrequency * twoPi * processor.period)
namespace soul::oscillators::poly_blep
A semi band-limited oscillator with sawtooth, square and triangle wave shapes using the PolyBLEP (Polynomial Band-Limited Step) technique. You may want to oversample this oscillator, in order to reduce aliasing.
namespace soul::oscillators::poly_blep::shapers
Contains different wave-shaping functions.
Functions
namespace soul::oscillators::poly_blep::Shape
Contains constants for different wave-shapes
Variables
int32 sawtooth = 0
int32 triangle = 1
int32 square = 2
processor soul::oscillators::poly_blep::Processor
A processor which generates a dynamically adjustable wave-shape.
Specialisation Parameters
processor soul::oscillators::poly_blep::Processor (int32 initialShape = 0,
float32 initialFrequency = 1000)
Inputs
- event shapeIn (float32)
- event frequencyIn (float32)
Outputs
- stream out (SampleType)
namespace soul::oscillators::quadrature
A quadrature sinusoidal oscillator producing sine and cosine outputs simultaneously. The updateInterval
defines the samples between updates to the frequency taking effect. https://vicanek.de/articles/QuadOsc.pdf
Specialisation Parameters
namespace soul::oscillators::quadrature (int32 updateInterval = 16)
Structures
Functions
update
Updates a quadrature::State object for a new rate.
void update (Coeffs& c,
float64 freqHz,
float64 sampleRate)
process
Generates the next samples for a quadrature::State object.
SampleType[2] process (State& s,
Coeffs& c)
processor soul::oscillators::quadrature::Processor
A processor that generates a pair of sine/cosine output streams.
Specialisation Parameters
processor soul::oscillators::quadrature::Processor (float32 initialFrequency = 1000)
Inputs
- event frequencyIn (float32)
Outputs
- stream sineOut (SampleType)
- stream cosineOut (SampleType)
Variables
float32 frequency = initialFrequency
bool recalc = true
namespace soul::oscillators::lfo
A tempo-syncable LFO with some common shapes and options for uni-polar or bi-polar output. Unipolar LFO shapes run between 0 and 1, whilst Bipolar run between -1 and 1.
namespace soul::oscillators::lfo::shapers
Various LFO shape generator functions.
namespace soul::oscillators::lfo::Shape
A set of constants to specify different LFO shapes.
Variables
int32 triangle = 0
int32 square = 1
int32 rampUp = 2
int32 rampDown = 3
int32 sine = 4
int32 sampleAndHold = 5
namespace soul::oscillators::lfo::Polarity
Polarity control constants.
Variables
int32 unipolar = 0
int32 bipolar = 1
processor soul::oscillators::lfo::Processor
A processor which implements an LFO with events to control its parameters. Changes to the frequency and depth are smoothed, but expect discontinuities if the shape or polarity are updated.
Specialisation Parameters
processor soul::oscillators::lfo::Processor (int32 initialShape = 0,
int32 initialPolarity = 0,
float32 initialDepth = 1.0f,
float32 initialFrequency = 1.0f)
Inputs
- event positionIn (soul::timeline::Position)
- event transportStateIn (soul::timeline::TransportState)
- event tempoIn (soul::timeline::Tempo)
- event rateHzIn (float32)
- event rateTempoIn (float32)
- event depthIn (float32)
- event shapeIn (float32)
- event polarityIn (float32)
- event rateModeIn (float32)
- event syncIn (float32)
Outputs
- stream out (SampleType)
Variables
PhaseType phase
float32 phaseIncrement = float32 (initialFrequency * processor.period)
int32 shape = initialShape
int32 polarity = initialPolarity
smoother::State depth
int32 smoothingSamples = int (float (processor.frequency) * 0.02f)
bool transportRunning = false
bool qnMode = false
bool timelineSync = false
float64 qnScalar = 1.0
float64 qnPos = 0.0
float32 qnPhaseIncrement = (120.0f / 60.0f) * (1.0f / 44100.0f)
PhaseType prevPhase = 1.0f
SampleType noiseSample
Filters
This module contains a collection of filter implementations, including more traditional biquad based filters and TPT variants, which are more suitable for modulation.
Notes:
- Filter coefficients are typically labelled a and b. Different literature uses different conventions for what a and b mean. This code uses the following:
-
b
: feed-forward, numerator, zero, FIR coefficients. -
a
: feed-back, denominator, pole, IIR coefficients. - Although each filter comes with a Processor, they are designed so that their state, coefficients and functions can be used independently.
- Each filter has a
State
struct and aCoeffs
struct. -
process()
functions generate an output y for an input x. -
update()
functions take high level parameters such as mode, frequency, Q, mode and update the filter coefficients. -
reset()
functions reset the filter state/histories to 0. -
clear()
functions clears filter coefficients. - The filters are designed for channel-wise vectorisation, which can be achieved by specialising the filter's namespace with a vector type.
- Some filters are suitable for modulation, others are not, check the comments at the top of the namespace.
namespace soul::filters
Specialisation Parameters
namespace soul::filters (using SampleType = float32,
using CoeffType = float64,
int32 updateInterval = 16)
Variables
float32 minFreqHz = 5.0f
Processor parameter min/max/defaults
float32 maxFreqHz = 22000.0f
float32 defaultFreqHz = 1000.0f
float32 defaultQuality = 0.707107f
float32 defaultGain = 0.f
float64 normalisedFreqLimit = 0.49
The frequency upper-bound for update functions. (Just below nyquist, e.g 0.49 * 44100 = ~22kHz).
namespace soul::filters::dc_blocker
Highpass filter for removing DC offset.
y[n] = x[n] - x[n-1] + b0 * y[n-1]
Structures
Holds the filter state.
processor soul::filters::dc_blocker::Processor
Specialisation Parameters
processor soul::filters::dc_blocker::Processor (float64 frequency = 30.0f)
Inputs
- stream in (SampleType)
Outputs
- stream out (SampleType)
namespace soul::filters::biquad
Biquadratic (two-pole-two-zero) IIR filter building block.
Direct Form I (DFI):
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
Transposed Direct Form II (TDFII):
y[n] = b0 * x[n] + s1
s1 = b1 * x[n] + a1 * y[n] + s2
s2 = b2 * x[n] + a2 * y[n]
Structures
Holds a set of filter coefficients.
Holds the filter state.
Functions
set
Initialises a set of coefficients.
void set (Coeffs& c,
CoeffType b0,
CoeffType b1,
CoeffType b2,
CoeffType a0,
CoeffType a1,
CoeffType a2)
setNonNormalised
Sets the coefficients, normalising based on the first feedback coefficient v.a[0]
setNormalised
Sets the coefficients, assuming v is already normalised.
processDFI
SampleType processDFI (State& s,
SampleType x,
Coeffs& c)
processTDFII
SampleType processTDFII (State& s,
SampleType x,
Coeffs& c)
processOnePole
Like processTDFII, but optimised for c.b[2] and c.a[2] == 0.
SampleType processOnePole (State& s,
SampleType x,
Coeffs& c)
processCascadeDFI
SampleType processCascadeDFI<StateArrayType, CoeffsArrayType> (SampleType x,
StateArrayType& s,
CoeffsArrayType& c)
processCascadeTDFII
SampleType processCascadeTDFII<StateArrayType, CoeffsArrayType> (SampleType x,
StateArrayType& s,
CoeffsArrayType& c)
namespace soul::filters::onepole
First-order IIR filter.
y[n] = b0 * x[n] - a1 * y[n-1]
Coefficients derived from Pirkle. This filter is not suitable for modulation.
Functions
update
Updates a set of coefficients for the given settings.
void update (biquad::Coeffs& c,
float64 sampleRate,
int32 mode,
float64 freqHz)
namespace soul::filters::onepole::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
int32 allpass = 2
processor soul::filters::onepole::Processor
A processor to render a onepole filter.
Specialisation Parameters
processor soul::filters::onepole::Processor (int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event modeIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
int32 mode = initialMode
bool recalc = true
namespace soul::filters::rbj_eq
RBJ biquad EQ, 2nd Order IIR Filter.
This filter is not suitable for modulation. See https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html
Functions
update
Updates a set of coefficients for the given settings.
void update (biquad::Coeffs& c,
float64 sampleRate,
int32 mode,
float64 freqHz,
float64 quality,
float64 gaindB)
namespace soul::filters::rbj_eq::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
int32 bandpass = 2
int32 lowShelf = 3
int32 highShelf = 4
int32 peaking = 5
int32 notch = 6
int32 allpass = 7
processor soul::filters::rbj_eq::Processor
Specialisation Parameters
processor soul::filters::rbj_eq::Processor (int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz,
float32 initialQuality = defaultQuality,
float32 initialGain = defaultGain)
Inputs
- stream in (SampleType)
- event modeIn (float32)
- event frequencyIn (float32)
- event qualityIn (float32)
- event gainIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
float32 quality = initialQuality
float32 gain = initialGain
int32 mode = initialMode
bool recalc = true
namespace soul::filters::sos_cascade
Generic second-order-section cascade biquad processors.
processor soul::filters::sos_cascade::Processor
Supply an array of coefficients for each SOS. The size of the array should be a multiple of 6, and the coefficients are expected to be normalised already
Specialisation Parameters
processor soul::filters::sos_cascade::Processor (const CoeffType[] coeffs)
Inputs
- stream in (SampleType)
Outputs
- stream out (SampleType)
namespace soul::filters::butterworth
N-th order Butterworth filter, made by cascading multiple second order sections.
This filter is not suitable for modulation.
Functions
update
Updates a set of coefficients for the given settings.
void update<CoeffsArrayType> (CoeffsArrayType& coeffs,
float64 sampleRate,
int32 order,
int32 mode,
float64 freqHz)
namespace soul::filters::butterworth::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
processor soul::filters::butterworth::Processor
Butterworth processor. The order must be > 0
Specialisation Parameters
processor soul::filters::butterworth::Processor (int32 order,
int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event modeIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
int32 mode = initialMode
bool recalc = true
bool clear = true
namespace soul::filters::analytic
Analytic filter / IIR Hilbert transformer.
https://dsp.stackexchange.com/a/59157
Increasing numFilters will increase the accuracy of the quadrature output across the pass band but introduce more delay with respect to the input signal. The filter passband is from transitionBandwidthHz to nyquist - transitionBandwidthHz.
Specialisation Parameters
namespace soul::filters::analytic (int32 numFilters = 6,
float32 transitionBandwidthHz = 20.0f)
Structures
Holds the filter state.
Functions
update
Updates a filter state with the given sample rate.
void update (State& s,
float64 sampleRate)
process
SampleType[2] process (State& s,
SampleType x)
namespace soul::filters::analytic::polyphase_iir_design
Polyphase IIR Designer. Based on HIIR http://ldesoras.free.fr/prod.html#src_hiir
Structures
Holds a set of filter coefficients.
struct TransitionParams
{
}
Functions
compute
Coeffs compute (float64 transition)
Variables
numCoefficients = numFilters * 2
order = numCoefficients * 2 + 1
namespace soul::filters::analytic::dual_apf
Parallel 2nd-order all-pass.
y[n] = c * (x[n] + y[n - 2]) - x[n - 2]
Structures
Holds the filter state.
struct State
{
}
Functions
process
SampleType[2] process (State& s,
SampleType[2] x)
processor soul::filters::analytic::Processor
Inputs
- stream in (SampleType)
Outputs
- stream realOut (SampleType)
- stream imagOut (SampleType)
Variables
State s
namespace soul::filters::complex_resonator
Complex Resonator filter.
See https://ccrma.stanford.edu/~jos/smac03maxjos/smac03maxjos.pdf This filter is suitable for modulation
Structures
Holds the filter state.
Holds a set of filter coefficients.
struct Coeffs
{
}
Functions
update
Updates a set of coefficients for the given settings.
void update (Coeffs& c,
float64 sampleRate,
float64 freqHz,
float64 t60)
process
SampleType[2] process (State& s,
Coeffs& c,
SampleType x)
processor soul::filters::complex_resonator::Processor
Specialisation Parameters
processor soul::filters::complex_resonator::Processor (float32 initialFrequency = defaultFreqHz,
float32 initialDecay = 1.0f,
float32 initialGain = 1.0f)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event decayIn (float32)
- event gainIn (float32)
Outputs
- stream realOut (SampleType)
- stream imagOut (SampleType)
Variables
float32 frequency = initialFrequency
float32 decay = initialDecay
float32 gain = initialGain
bool recalc = true
namespace soul::filters::tpt
This namespace contains a set of "Topology preserving transform" filters.
namespace soul::filters::tpt::onepole
"Topology preserving transform" one-pole filter.
Derived from work by Zavalishin and Pirkle. This filter is suitable for modulation.
Structures
Holds a set of filter coefficients.
Holds the filter state.
Functions
update
Updates a set of coefficients for the given settings.
void update (Coeffs& c,
float64 sampleRate,
float64 freqHz)
processLPF
SampleType processLPF (State& s,
SampleType x,
Coeffs& c)
processHPF
SampleType processHPF (State& s,
SampleType x,
Coeffs& c)
processAPF
SampleType processAPF (State& s,
SampleType x,
Coeffs& c)
namespace soul::filters::tpt::onepole::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
int32 allpass = 2
processor soul::filters::tpt::onepole::Processor
Specialisation Parameters
processor soul::filters::tpt::onepole::Processor (int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event modeIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
int32 mode = initialMode
bool recalc = true
namespace soul::filters::tpt::svf
"Topology preserving transform" multi-mode state variable filter (SVF).
Derived from work by Zavalishin and Pirkle. This filter is suitable for modulation.
Structures
Holds the filter state.
Functions
update
Updates a set of coefficients for the given settings.
void update (Coeffs& c,
float64 sampleRate,
float64 freqHz,
float64 quality)
process
SampleType[3] process (State& s,
SampleType x,
Coeffs& c)
namespace soul::filters::tpt::svf::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
int32 bandpass = 2
processor soul::filters::tpt::svf::Processor
Specialisation Parameters
processor soul::filters::tpt::svf::Processor (float32 initialFrequency = defaultFreqHz,
float32 initialQuality = defaultQuality)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event qualityIn (float32)
Outputs
- stream lowpassOut (SampleType)
- stream bandpassOut (SampleType)
- stream highpassOut (SampleType)
Variables
float32 frequency = initialFrequency
float32 quality = initialQuality
bool recalc = true
namespace soul::filters::tpt::butterworth
N-th order Butterworth filter, made by cascading TPT filters. This filter is suitable for modulation
Functions
update
Updates a set of coefficients for the given settings.
void update<SVFCoeffsArrayType> (SVFCoeffsArrayType& svfCoeffs,
onepole::Coeffs& onepoleCoeffs,
float64 sampleRate,
int32 order,
float64 freqHz)
process
SampleType process<StateArrayType, CoeffsArrayType> (SampleType x,
StateArrayType& svfStates,
CoeffsArrayType& svfCoeffs,
onepole::State& onepoleState,
onepole::Coeffs& onepoleCoeffs,
int32 mode,
bool oddOrder)
namespace soul::filters::tpt::butterworth::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
processor soul::filters::tpt::butterworth::Processor
Butterworth processor. The order must be > 1
Specialisation Parameters
processor soul::filters::tpt::butterworth::Processor (int32 order,
int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event modeIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
int32 mode = initialMode
bool recalc = true
namespace soul::filters::tpt::crossover
4th-order Linkwitz-Riley crossover filter, which outputs two bands of audio.
The channels should sum together to produce a flat response. This filter is suitable for modulation.
Structures
Holds the filter state.
Holds a set of filter coefficients.
processor soul::filters::tpt::crossover::Processor
Specialisation Parameters
processor soul::filters::tpt::crossover::Processor (float32 initialFrequency = defaultFreqHz)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
Outputs
- stream lowOut (SampleType)
- stream highOut (SampleType)
Functions
update
Updates a set of coefficients for the given settings.
void update (Coeffs& c,
float64 sampleRate,
float64 freqHz)
Variables
float32 frequency = initialFrequency
bool recalc = true
namespace soul::filters::tpt::simper_eq
SVF EQ.
Based on the work of Andy Simper: https://cytomic.com/files/dsp/SvfLinearTrapOptimised2.pdf
This filter is suitable for modulation.
Structures
Holds a set of filter coefficients.
Holds the filter state.
Functions
update
Updates a set of coefficients for the given settings.
void update (Coeffs& c,
float64 sampleRate,
int32 mode,
float64 freqHz,
float64 quality,
float64 gain)
process
SampleType process (State& s,
SampleType x,
Coeffs& c)
namespace soul::filters::tpt::simper_eq::Mode
Constants for use in specifying the filter mode.
Variables
int32 lowpass = 0
int32 highpass = 1
int32 bandpass = 2
int32 lowShelf = 3
int32 highShelf = 4
int32 peaking = 5
int32 notch = 6
int32 allpass = 7
int32 bell = 8
processor soul::filters::tpt::simper_eq::Processor
Specialisation Parameters
processor soul::filters::tpt::simper_eq::Processor (int32 initialMode = 0,
float32 initialFrequency = defaultFreqHz,
float32 initialQuality = defaultQuality,
float32 initialGain = defaultGain)
Inputs
- stream in (SampleType)
- event frequencyIn (float32)
- event qualityIn (float32)
- event gainIn (float32)
- event modeIn (float32)
Outputs
- stream out (SampleType)
Variables
float32 frequency = initialFrequency
float32 quality = initialQuality
float32 gain = initialGain
int32 mode = initialMode
bool recalc = true
MIDI utilities
In general, the SOUL policy towards MIDI is to avoid it as much as is humanly possible, so most of these helper functions are concerned with converting MIDI messages to soul::note_events
types, and then the other libraries use these strongly-typed events to model note actions, rather than dealing with raw MIDI events.
namespace soul::midi
Various MIDI-related types and functions.
Structures
This type is used to represent a packed short MIDI message. When you create an input event endpoint and would like it to receive MIDI, this is the type that you should use for it.
struct Message
{
}
processor soul::midi::MPEParser
This event processor receives incoming MIDI events, parses them as MPE, and then emits a stream of note events using the types in soul::note_events. A synthesiser can then handle the resulting events without needing to go near any actual MIDI or MPE data.
Inputs
- event parseMIDI (Message)
Outputs
Variables
int32 MPESlideControllerID = 74
Frequency-domain utilities
namespace soul::DFT
Discrete Fourier Transform functions.
Functions
forward
Performs a real forward DFT from an input buffer to an output buffer.
void forward<SampleBuffer> (const SampleBuffer& inputData,
SampleBuffer& outputData)
inverse
Performs a real inverse DFT from an input buffer to an output buffer.
void inverse<SampleBuffer> (const SampleBuffer& inputData,
SampleBuffer& outputData)
performComplex
For internal use by the other functions: performs a O(N^2) complex DFT.
void performComplex<SampleBuffer> (const SampleBuffer& inputReal,
const SampleBuffer& inputImag,
SampleBuffer& outputReal,
SampleBuffer& outputImag,
SampleBuffer.elementType scaleFactor)