dynatos
Dynatos is dedicated to dynamics, articulations, and expressive envelopes, handling the conversion of symbolic dynamics into precise amplitude values and parametric envelopes.
Dynamics
Dynamics Classes
Dynamics classes and utilities for musical expression.
This module provides classes for working with musical dynamics, including individual dynamic markings and dynamic ranges.
- class klotho.dynatos.dynamics.dynamics.Dynamic(marking, db_value)[source]
Bases:
objectRepresents a musical dynamic marking with both symbolic and numeric representations.
A Dynamic object encapsulates both the traditional musical marking (e.g., ‘f’, ‘pp’) and its corresponding decibel value, providing seamless conversion between symbolic and numeric representations of dynamics.
- Parameters:
Examples
>>> dyn = Dynamic('f', -12) >>> dyn.marking 'f' >>> dyn.db -12 >>> dyn.amp 0.25118864315095825
Amplitude Utilities
Amplitude and decibel conversion utilities.
This module provides functions for converting between linear amplitude values and logarithmic decibel representations.
Scaling Utilities
Psychoacoustic frequency-amplitude scaling utilities.
This module provides functions for scaling amplitude based on frequency and loudness according to psychoacoustic principles, accounting for human perception of sound at different frequencies and levels.
Envelopes
Envelope Classes
Envelopes for shaping the dynamics of musical sequences.
This module provides the Envelope class for creating and manipulating time-varying amplitude or parameter envelopes with support for various curve shapes and normalization options.
- class klotho.dynatos.envelopes.envelopes.Envelope(values, times=1.0, curve=0.0, normalize_values=False, normalize_times=False, value_scale=1.0, time_scale=1.0)[source]
Bases:
objectA flexible envelope generator for time-varying parameter control.
The Envelope class creates smooth transitions between a series of values over specified time durations, with support for curve shaping, normalization, and scaling. The envelope is immutable after construction.
- Parameters:
values (list) – List of breakpoint values to interpolate between.
times (float or list, optional) – Duration(s) for each segment. If a single value, all segments use the same duration. If a list, must have one fewer element than values. Default is 1.0.
curve (float or list, optional) – Curve shape for each segment. 0 = linear, negative = exponential, positive = logarithmic. If a single value, all segments use the same curve. Default is 0.0.
normalize_values (bool, optional) – Whether to normalize values to 0-1 range at construction. Default is False.
normalize_times (bool, optional) – Whether to normalize times to sum to 1 at construction. Default is False.
value_scale (float, optional) – Scale factor applied to all values at construction. Default is 1.0.
time_scale (float, optional) – Scale factor applied to all times when computing durations. Default is 1.0.
Examples
>>> env = Envelope([0, 1, 0.5, 0], times=[0.1, 0.8, 0.1]) >>> env.at_time(0.5) 0.875
>>> decay = Envelope([1, 0], times=2.0, curve=-3) >>> decay.at_time(0) 1.0 >>> decay.at_time(2.0) 0.0
- __init__(values, times=1.0, curve=0.0, normalize_values=False, normalize_times=False, value_scale=1.0, time_scale=1.0)[source]
- classmethod perc(attackTime=0.01, releaseTime=1.0, curve=-4.0, time_scale=1.0)[source]
Create a percussive envelope: 0 -> 1 -> 0
- Parameters:
- Returns:
A percussive envelope instance.
- Return type:
- classmethod adr(attackTime=0.01, decayTime=0.3, decayLevel=0.5, releaseTime=1.0, curve=-4.0, time_scale=1.0)[source]
Create an ADR envelope (3 segments): 0 -> 1 -> decayLevel -> 0
- Parameters:
attackTime (float, optional) – Duration of attack phase. Default is 0.01.
decayTime (float, optional) – Duration of decay phase. Default is 0.3.
decayLevel (float, optional) – Level after decay. Default is 0.5.
releaseTime (float, optional) – Duration of release phase. Default is 1.0.
curve (float, optional) – Curve shape for all segments. Default is -4.0.
time_scale (float, optional) – Time scale factor. Default is 1.0.
- Returns:
An ADR envelope instance.
- Return type:
- classmethod adsr(attackTime=0.01, decayTime=0.3, sustainTime=0.5, sustainLevel=0.5, releaseTime=1.0, curve=-4.0, time_scale=1.0)[source]
Create an ADSR envelope (4 segments): 0 -> 1 -> sustainLevel (hold) -> 0
- Parameters:
attackTime (float, optional) – Duration of attack phase. Default is 0.01.
decayTime (float, optional) – Duration of decay phase. Default is 0.3.
sustainTime (float, optional) – Duration of sustain phase. Default is 0.5.
sustainLevel (float, optional) – Level during sustain. Default is 0.5.
releaseTime (float, optional) – Duration of release phase. Default is 1.0.
curve (float, optional) – Curve shape for all segments. Default is -4.0.
time_scale (float, optional) – Time scale factor. Default is 1.0.
- Returns:
An ADSR envelope instance.
- Return type:
- classmethod pairs(pairs, curve=0.0, time_scale=1.0)[source]
Create an envelope from (time, value) pairs.
- Parameters:
- Returns:
An envelope instance defined by the given pairs.
- Return type:
Examples
>>> env = Envelope.pairs([(0, 0), (0.1, 1), (0.5, 0.5), (1.0, 0)])
- property values
List of breakpoint values.
- property times
List of segment durations.
- property time_scale
Time scale factor applied to segment durations.
- property total_time
Total duration of the envelope.
- property breakpoint_times
Cumulative time points for each breakpoint value.
- property normalized_times
Cumulative breakpoint times normalized to the [0, 1] range.
- at_time(time)[source]
Get the envelope value at a specific time.
Results are memoized on a per-instance cache keyed by the requested time, so repeated queries against the same envelope are O(1) after the first. The cache lifetime is bound to the envelope instance itself (unlike a module-level
lru_cache, which would keep every envelope alive for the life of the interpreter).- Parameters:
time (float) – Time point to query (must be within [0, total_time]).
- Returns:
Interpolated envelope value at the given time.
- Return type:
- Raises:
ValueError – If time is outside the envelope duration.
Curve Utilities
Curve generation and mapping utilities for envelopes.
This module provides functions for generating various types of curves including linear and exponential lines, arch/swell shapes, and value mapping with curve transformations.
- klotho.dynatos.envelopes.utils.curves.line(start=0.0, end=1.0, steps=100, curve=0.0)[source]
Generate a curved line from start to end value over n steps.
- Parameters:
start (float, optional) – Starting value (default is 0.0).
end (float, optional) – Ending value (default is 1.0).
steps (int, optional) – Number of steps (default is 100).
curve (float, optional) – Shape of the curve. Negative for exponential, positive for logarithmic, 0 for linear (default is 0.0).
- Returns:
Array of values following the specified curve.
- Return type:
- klotho.dynatos.envelopes.utils.curves.arch(base=0.0, peak=1.0, steps=100, curve=0.0, axis=0)[source]
Generate a swelling curve that rises and falls.
Starts and ends at the base value, peaking at the peak value.
- Parameters:
base (float, optional) – Starting and ending value (default is 0.0).
peak (float, optional) – Peak value (default is 1.0).
steps (int, optional) – Number of steps (default is 100).
curve (float or list of float, optional) – Shape of the curve. A single number applies the same curve to both sides (negative for exponential, positive for logarithmic). A list of two values sets ascending and descending curves independently (default is 0.0).
axis (float, optional) – Position of the peak (-1 to 1). 0 centers the peak, negative shifts earlier, positive shifts later (default is 0).
- Returns:
Array of values following a swell curve.
- Return type: