Crate heron_sound

Crate heron_sound 

Source
Expand description

heron-sound is a library of DSP utilities used in Heron Sounds audio plugins.

Currently supports the following DSP components:

As well as a variety of utilities to support the above.

§Implementation

To help develop DSP components, we provide two basic traits, Gen and Proc. Gen is for components that generate some value from their internal state without any explicit input, while Proc is for processors that take some input value and produce an output. The inputs and outputs may be samples, gains, or more complex types, but should not be user-modifiable parameters.

To pass in user-modifiable parameters, both traits have a Spec associated type which is passed by shared reference at processing time and evaluated, along with the processor’s internal state, to produce an output.

For example, an envelope follower can be implemented as a Proc that takes an input sample and returns a bool indicating whether the envelope is engaged or not:

struct EnvFollower {
    engaged: bool,
    counter: u32,
}
 
struct EnvFollowerSpec {
    threshold: f64,
    hold_time: u32,
}
 
impl Proc<f64, bool> for EnvFollower {
    type Spec = EnvFollowerSpec;
    fn proc(&mut self, spec: &Self::Spec, sample: f64) -> bool {
        // implementation omitted
    }
}

Its internal state keeps track of whether it’s currently engaged and for how long, and its associated Spec type keeps track of the amplitude threshold and hold time, both of which can be set by the user. At processing time, it checks whether the input sample’s amplitude is above the threshold, increments its internal counter and checks it against the user-set hold time, and computes a boolean value to return. To see how this is implemented in practice, take a look at EnvFollower and EnvFollowerSpec.

Most of the code in this library consists of implementations of Gen and Proc, but we also include some miscellaneous utils in the util mod.

§Approach

The components in this library are implemented according to the following constraints:

  • keep memory use low
  • but prefer caching values over recomputing them
  • avoid allocations during processing
  • perform as few operations as possible during processing
  • maintain a strict boundary between user-modifiable parameters and internal mutable state
  • minimize dependencies
  • avoid unsafe code

As well as a few more relaxed constraints:

  • avoid newtypes, but use type aliases where it aids readability
  • use f64 as the default float type
  • prefer use of phase offsets to pitches in Hz to minimize computations (see pitch)
  • in simple code, bounds checks can be skipped in release builds to aid performance
  • allow some unnecessary memory use if it’s small and keeps code cleaner
  • keep components as generic as feasible, but allow some opinionated decisions (see ExpAdsrSpec)

§Future

In general, we put code in this library as soon as we can find a way to make it generic enough to be useful for more than one type of plugin (and write adequate tests for it). Expect the functionality to expand as we clean up application-specific code and make it more modular.

The following additions are in the works, but not fully tested or cleaned up:

  • First class support for plugin parameters
  • Ring buffers, delay lines, and pitch-shifting
  • Distortion algorithms
  • Additional filter types

Modules§

clock
Sample rate utilities.
env
Envelope generator implementations.
filter
Filter implementations.
follow
Envelope follower implementations.
lfo
Low-frequency oscillator implementations.
modulate
Utilities for modulating parameters.
osc
Oscillator implementations.
phase
Phasor implementation.
pitch
Utilities for manipulating pitches (or phase increments).
trigger
Midi note trigger implementation.
util
Miscellaneous useful stuff.
wave
Low-level computations for oscillator waveforms.

Macros§

accessors
helper to create get_val() and set_val() fns.
check_float_01
Check that float values are in range 0..=1.
check_float_finite
Check that float values are finite.
check_float_nonneg
Check that float values are nonnegative.
check_float_nonzero
Check that float values are nonzero.
check_float_pos
Check that float values are positive and nonzero.
check_hz_bounds
Check that float values representing Hz are positive and non-zero.
check_int_less_than
Check that int values are less than a constant.
check_phase_bounds
Check that float values representing phases are in range 0..1.
getters
helper to create get_val() and get_val_mut() fns.
index_accessors
helper to create get_val() and set_val() fns that take indexes.
index_getters
helper to create get_val() and get_val_mut() fns that take indexes.

Traits§

Gen
A processor that generates a value, with no input.
Proc
A processor that transforms a value.

Type Aliases§

F
Basic float type (currently f64 but this may change).
Hz
Anything measured in Hz; positive only.
Note
A midi note; 0..128.
Phase
Phase position of a wave; 0.0..1.0.
Sample
Amplitude of a sample; -1.0..=1.0.
Scale
Anything measured in fractions.
Seconds
Anything measured in seconds; positive only, probably.
Vel
Midi velocity; 0..128.