#include <granular.hpp>
Public Member Functions | |
| GranularEngineT () | |
| void | prepare (double sample_rate) |
| Sizes the live ring and the window table. | |
| void | reset () |
| Clears grains and the ring, rewinds the schedule, and restarts the random stream. | |
| void | set_source (GrainSource source) |
| GrainSource | source () const |
| void | set_buffer (const SampleType *data, int length, int channels) |
| Borrows an external interleaved buffer. | |
| void | write_live (const SampleType *in, int n) |
| Pushes n mono samples into the live ring. | |
| void | set_stretch (double rate) |
| Playhead advance multiplier. | |
| double | stretch () const |
| void | set_position (double pos01) |
| Playhead centre as a fraction of the source. | |
| double | position () const |
| void | set_position_spray_ms (double ms) |
| double | position_spray_ms () const |
| void | set_density_hz (double hz) |
| double | density_hz () const |
| void | set_grain_ms (double ms) |
| double | grain_ms () const |
| void | set_async_jitter (double j01) |
| 0 is the exact clock; 1 is a true Poisson process. | |
| double | async_jitter () const |
| void | set_max_grains (int count) |
| Grains in slots above the new budget stop immediately, so lowering the budget cannot leave a grain sounding from a slot the pool no longer scans. | |
| int | max_grains () const |
| void | set_steal_policy (StealPolicy policy) |
| StealPolicy | steal_policy () const |
| void | set_window_taper (double t01) |
| 0 is rectangular, 1 is Hann (cosine mode) or triangle (trapezoid mode); in between is a Tukey / flat-topped trapezoid whose tapers occupy taper/2 of the grain at each end. | |
| double | window_taper () const |
| void | set_window_trapezoid (bool trapezoid) |
| bool | window_trapezoid () const |
| void | set_pitch_semitones (double st) |
| double | pitch_semitones () const |
| void | set_pitch_spray_semitones (double st) |
| void | set_pan_spray (double s01) |
| void | set_coherence (Coherence coherence) |
| Coherence | coherence () const |
| void | set_interp (GrainInterp interp) |
| GrainInterp | interp () const |
| void | set_level_db (double db) |
| void | set_mix (double mix01) |
| Dry/wet, 0 = dry . | |
| double | mix () const |
| void | set_seed (std::uint32_t seed) |
| Fixed at reset(); never automatable (series law 2). | |
| std::uint32_t | seed () const |
| std::size_t | latency_samples () const |
| Zero. | |
| double | mean_overlap () const |
| Mean simultaneous overlap N̄ = D·T_g — the quantity both normalization laws are written in terms of. | |
| double | grain_gain () const |
| Per-grain gain the next spawn will use, from the current law and params. | |
| double | window_mean () const |
| Measured from the shipped table, not assumed. | |
| double | window_rms () const |
| double | window_at (double phase) const |
| Window value at a normalised grain phase — the same table read the audio path uses, exposed so a test measures what the engine plays. | |
| int | active_grain_count () const |
| GrainView | grain (int slot) const |
| std::uint64_t | grain_index () const |
| Grains born since reset(). Monotonic; this is the key every draw uses. | |
| std::uint64_t | steal_count () const |
| Grains recycled out from under a still-sounding predecessor. | |
| std::uint64_t | clamp_count () const |
| Spawns whose read position the causality clamp had to move. | |
| int | ring_length () const |
| SampleType | ring_storage_sample (int index) const |
| Physical live-ring storage for diagnostics. | |
| int | causality_guard_samples () const |
| The derived causality guard, in samples: the worst-case total displacement a grain's read pointer can reach away from its nominal centre, which is the maximum position spray plus the longest source span a grain can consume at the highest pitch-up ratio. | |
| void | process (SampleType *out_left, SampleType *out_right, int n) |
| Pure-source render. | |
| void | process (const SampleType *in, SampleType *out_left, SampleType *out_right, int n) |
| Live render that consumes its own input, one sample at a time. | |
Static Public Member Functions | |
| static int | derived_guard_samples (double sample_rate) |
Static Public Attributes | |
| static constexpr int | kMaxGrainBudget = 64 |
| Slot capacity of the grain pool. | |
| static constexpr int | kMinGrainBudget = 32 |
| Floor of the max_grains range. | |
| static constexpr int | kDefaultMaxGrains = 48 |
| [design parameter] default 48 grains, range 32 .. 64. | |
| static constexpr int | kWindowTableSize = 2048 |
| Window table resolution. | |
| static constexpr double | kRingSeconds = 4.0 |
| Live ring length in seconds. | |
| static constexpr double | kDefaultDensityHz = 40.0 |
| [design parameter] default 40 grains/s, range 0.1 .. 2000. | |
| static constexpr double | kMinDensityHz = 0.1 |
| static constexpr double | kMaxDensityHz = 2000.0 |
| static constexpr double | kDefaultGrainMs = 50.0 |
| [design parameter] default 50 ms, range 1 . | |
| static constexpr double | kMinGrainMs = 1.0 |
| static constexpr double | kMaxGrainMs = 500.0 |
| static constexpr double | kDefaultJitter = 0.0 |
| [design parameter] default 0 (synchronous clock), range 0 .. 1. | |
| static constexpr double | kMaxPositionSprayMs = 500.0 |
| [design parameter] default 0 ms, range 0 .. 500 ms. | |
| static constexpr double | kDefaultStretch = 1.0 |
| [design parameter] default 1, range 0 .. 4. Zero is freeze. | |
| static constexpr double | kMaxStretch = 4.0 |
| static constexpr double | kMaxPitchSemitones = 24.0 |
| [design parameter] default 0 st, range −24 . | |
| static constexpr double | kMaxPitchSpraySemitones = 12.0 |
| [design parameter] default 0 st, range 0 .. 12 st. | |
| static constexpr double | kMinLevelDb = -24.0 |
| [design parameter] default 0 dB, range −24 .. +12 dB. | |
| static constexpr double | kMaxLevelDb = 12.0 |
| static constexpr std::uint32_t | kDefaultSeed = 0x9E3779B9u |
| Seed. | |
| static constexpr double | kControlSmoothingMs = 10.0 |
| Control-smoothing time for output level and dry/wet. | |
| static constexpr double | kMinDrawForLog = 1e-12 |
| Floor on a keyed draw before −ln(u). | |
| static constexpr double | kMinOnsetIntervalSamples = 1.0 |
| Floor on the inter-onset interval, in samples. | |
| static constexpr std::uint64_t | kFieldOnsetJitter = 1 |
| static constexpr std::uint64_t | kFieldPositionSpray = 2 |
| static constexpr std::uint64_t | kFieldPitchSpray = 3 |
| static constexpr std::uint64_t | kFieldPanSpray = 4 |
|
inline |
|
inline |
|
inline |
|
inline |
The derived causality guard, in samples: the worst-case total displacement a grain's read pointer can reach away from its nominal centre, which is the maximum position spray plus the longest source span a grain can consume at the highest pitch-up ratio.
Not a free constant.
|
inline |
Spawns whose read position the causality clamp had to move.
|
inline |
|
inline |
|
inlinestatic |
|
inline |
|
inline |
Per-grain gain the next spawn will use, from the current law and params.
|
inline |
Grains born since reset(). Monotonic; this is the key every draw uses.
|
inline |
|
inline |
|
inline |
Zero.
Grains read past samples only; the position offset is musical, not codec latency.
|
inline |
|
inline |
Mean simultaneous overlap N̄ = D·T_g — the quantity both normalization laws are written in terms of.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Sizes the live ring and the window table.
The only member that allocates.
|
inline |
Live render that consumes its own input, one sample at a time.
This overload exists because the write_live + process pair CANNOT be block-size independent: writing a whole block before rendering any of it puts samples in the ring that a grain rendered at the start of that block can legally read, and rendering sample-by-sample does not. Interleaving the two removes the ambiguity, so this is the overload whose output is identical at 1×N and N×1 — and it is also the natural shape for a plugin callback. It is additionally the only overload with a dry signal, so set_mix applies here and nowhere else.
|
inline |
Pure-source render.
In live-ring mode the caller must have pushed this block's input with write_live first.
|
inline |
Clears grains and the ring, rewinds the schedule, and restarts the random stream.
Restarting the stream costs nothing here: the draws are a pure function of the grain index, so rewinding the index to zero is reseeding. Never allocates.
|
inline |
|
inline |
Physical live-ring storage for diagnostics.
Logical validity is still governed by write_head_; after an audio fault this may expose stale storage that the renderer must not read until it has been overwritten.
|
inline |
|
inline |
0 is the exact clock; 1 is a true Poisson process.
|
inline |
Borrows an external interleaved buffer.
The engine never owns, copies, or frees it; length is in FRAMES and channels is the interleave.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Grains in slots above the new budget stop immediately, so lowering the budget cannot leave a grain sounding from a slot the pool no longer scans.
|
inline |
Dry/wet, 0 = dry .
. 1 = wet. Only the interleaved process overload has a dry signal to blend; the two-output overload is a pure source and ignores this.
|
inline |
|
inline |
|
inline |
|
inline |
Playhead centre as a fraction of the source.
In buffer mode this jumps the playhead; in live mode it is how far behind the write head grains sample, as a fraction of the ring.
|
inline |
|
inline |
Fixed at reset(); never automatable (series law 2).
|
inline |
|
inline |
|
inline |
Playhead advance multiplier.
1 is realtime, 0 freezes, 4 scans four times as fast. In live-ring mode there is no traversal to scale — the playhead IS the write head — so stretch acts purely as the freeze switch there: 0 holds the captured centre, anything above 0 tracks.
|
inline |
0 is rectangular, 1 is Hann (cosine mode) or triangle (trapezoid mode); in between is a Tukey / flat-topped trapezoid whose tapers occupy taper/2 of the grain at each end.
|
inline |
|
inline |
|
inline |
Grains recycled out from under a still-sounding predecessor.
|
inline |
|
inline |
|
inline |
Window value at a normalised grain phase — the same table read the audio path uses, exposed so a test measures what the engine plays.
|
inline |
Measured from the shipped table, not assumed.
At full cosine taper these are the exact Hann identities 1/2 and √(3/8).
|
inline |
|
inline |
|
inline |
|
inline |
Pushes n mono samples into the live ring.
See the note on process's interleaved overload for why the two-call form is not block-size independent.
|
staticconstexpr |
Control-smoothing time for output level and dry/wet.
Only these two are smoothed — every per-grain parameter is captured once at spawn, so it cannot zipper. [design parameter] default 10 ms, range 1 .. 100 ms.
|
staticconstexpr |
[design parameter] default 40 grains/s, range 0.1 .. 2000.
|
staticconstexpr |
[design parameter] default 50 ms, range 1 .
. 500 ms. Roads' typical granular range is 1–100 ms; the ceiling here is higher so the engine also covers slow overlapping-drone territory.
|
staticconstexpr |
[design parameter] default 0 (synchronous clock), range 0 .. 1.
|
staticconstexpr |
[design parameter] default 48 grains, range 32 .. 64.
|
staticconstexpr |
Seed.
Fixed at reset(), never automatable (series law 2). [design parameter] any uint32_t; no automation range applies.
|
staticconstexpr |
[design parameter] default 1, range 0 .. 4. Zero is freeze.
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
Slot capacity of the grain pool.
Pinned to the top of max_grains' declared range rather than independently ranged: raising it would require re-deriving the worst-case gain bound. [design parameter] 64 slots, pinned to the max_grains range ceiling.
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
[design parameter] default 0 st, range −24 .
. +24 st. The ±24 bound is what sets r_max = 4 in the causality guard.
|
staticconstexpr |
[design parameter] default 0 st, range 0 .. 12 st.
|
staticconstexpr |
[design parameter] default 0 ms, range 0 .. 500 ms.
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
Floor on a keyed draw before −ln(u).
Guards log(0), which the 53-bit draw can produce with probability 2^-53. Any value far below the smallest non-zero draw works; range 1e-18 .. 1e-6.
|
staticconstexpr |
Floor of the max_grains range.
[design parameter] 32, the bottom of the declared 32..64 budget.
|
staticconstexpr |
|
staticconstexpr |
[design parameter] default 0 dB, range −24 .. +12 dB.
|
staticconstexpr |
Floor on the inter-onset interval, in samples.
Bounds the spawn work per sample to one grain, which is what makes process wait-free rather than merely allocation-free. It never binds at jitter = 0, where the interval is fs/D ≥ 24 samples at the maximum density and 48 kHz. [design parameter] default 1 sample, range 1 .. 8.
|
staticconstexpr |
Live ring length in seconds.
The floor of the range is not free: the causality guard below derives to a fixed 2.5 s at any sample rate, so the ring must clear that with enough margin left for a full grain span. [design parameter] default 4 s, range 3 .. 8 s.
|
staticconstexpr |
Window table resolution.
Powers of two only, so the phase index is a multiply. [design parameter] default 2048, range 512 .. 4096.