# mixed-signals API Reference
Complete reference for all public types, traits, and functions.
**Version**: 0.2.1
---
## Table of Contents
- [Core Concepts](#core-concepts)
- [Prelude](#prelude)
- [Traits](#traits)
- [Generators](#generators)
- [Noise](#noise)
- [Random](#random)
- [Envelopes](#envelopes)
- [Physics](#physics)
- [Easing](#easing)
- [Composition](#composition)
- [Processing](#processing)
- [Shuffle](#shuffle)
- [RNG](#rng)
- [Types](#types)
- [Math Utilities](#math-utilities)
- [Visualization](#visualization)
---
## Core Concepts
### Bipolar Output Convention
All oscillators and noise generators output **bipolar [-1, 1]** by default. This matches audio/synthesis conventions and enables mathematically correct composition.
```rust
use mixed_signals::prelude::*;
// Bipolar output [-1, 1]
let sine = Sine::default();
assert_eq!(sine.sample(0.25), 1.0); // Peak
assert_eq!(sine.sample(0.75), -1.0); // Trough
// Normalize to [0, 1] for TUI work
let opacity = sine.normalized();
assert_eq!(opacity.sample(0.0), 0.5); // Center maps to 0.5
```
### Determinism
All signals are deterministic. Same inputs always produce same outputs. Random/noise generators use seeds for reproducibility.
### SignalTime
Time parameters use `f64` for precision over long-running sessions. Outputs remain `f32`.
---
## Prelude
Import common types with a single use statement:
```rust
use mixed_signals::prelude::*;
```
**Includes:**
- All generators (Sine, Triangle, Square, etc.)
- All noise types (WhiteNoise, PerlinNoise, etc.)
- All physics solvers
- Composition and processing operators
- Core traits (Signal, SignalExt, SignalContext)
- Easing functions
- Rng
---
## Traits
### Signal
Core trait for all signal generators.
```rust
pub trait Signal: Send + Sync {
fn output_range(&self) -> SignalRange;
fn sample(&self, t: SignalTime) -> f32;
fn sample_with_context(&self, t: SignalTime, ctx: &SignalContext) -> f32;
fn sample_into(&self, t_start: SignalTime, dt: SignalTime, out: &mut [f32]);
fn sample_vec(&self, t_start: SignalTime, dt: SignalTime, count: usize) -> Vec<f32>;
}
```
### SignalExt
Fluent combinator methods for all Signal types.
| `.add(other)` | Add two signals |
| `.multiply(other)` | Multiply two signals |
| `.scale(factor)` | Scale by constant factor |
| `.mix(other, blend)` | Linear blend (0.0 = self, 1.0 = other) |
| `.map(fn)` | Apply custom function |
| `.invert()` | Negate signal value |
| `.normalized()` | Convert to [0, 1] range |
| `.normalized_from(range)` | Normalize from explicit range |
```rust
let organic = sine.mix(noise, 0.2).normalized();
```
### SignalContext
Runtime context for deterministic, reproducible behavior.
```rust
let ctx = SignalContext::new(frame, seed)
.with_dimensions(width, height)
.with_char_index(index)
.for_phase(Phase::Active, progress);
```
**Fields:**
- `frame: u64` - Frame number
- `seed: u64` - Reproducibility seed
- `width, height: u16` - Render area dimensions
- `phase: Option<Phase>` - Lifecycle phase
- `char_index: Option<usize>` - Character index
### Phase
Lifecycle phases for entrance/exit effects.
```rust
pub enum Phase {
Start, // Beginning/fade-in
Active, // Main state (default)
End, // Ending/fade-out
Done, // Completed
Custom(u8), // Application-defined (0-251)
}
```
### SignalRange
Expected output range.
```rust
pub struct SignalRange { pub min: f32, pub max: f32 }
// Constants
SignalRange::UNIT // [0.0, 1.0]
SignalRange::BIPOLAR // [-1.0, 1.0]
```
---
## Generators
All output **bipolar [-1, 1]**. Use `.normalized()` for [0, 1].
### Oscillators
| `Sine` | Smooth periodic oscillation | frequency, amplitude, offset, phase |
| `Triangle` | Linear up/down ramp | frequency, amplitude, offset, phase |
| `Square` | Binary pulse wave | frequency, amplitude, offset, phase, duty_cycle |
| `Sawtooth` | Linear ramp with reset | frequency, amplitude, offset, phase |
| `Pulse` | Variable-width pulse | frequency, amplitude, offset, phase, duty_cycle |
```rust
let sine = Sine::new(1.0, 1.0, 0.0, 0.0); // freq, amp, offset, phase
let square = Square::default();
```
### Utility Generators
| `Constant` | Fixed value | value |
| `Ramp` | Linear ramp | frequency, amplitude, offset, phase |
| `Step` | Step function | frequency, phase, threshold |
| `Keyframes` | Piecewise linear | keyframes: Vec<(SignalTime, f32)> |
```rust
let constant = Constant::new(0.5);
let keyframes = Keyframes::new(vec![
(0.0, 0.0),
(0.5, 1.0),
(1.0, 0.3),
]);
```
### Advanced
| `PhaseAccumulator` | Continuous phase tracking for FM synthesis |
| `PhaseSine` | Phase-to-sine converter |
---
## Noise
Continuous stochastic signals from `mixed_signals::noise`.
| `WhiteNoise` | Pure random, uncorrelated | [-1, 1] |
| `PerlinNoise` | Smooth gradient noise | [-1, 1] |
```rust
let noise = PerlinNoise::with_seed(42);
```
---
## Random
Distribution-based generators from `mixed_signals::random`. All seeded and deterministic.
### Standard Variants (ChaCha8Rng)
| `SeededRandom` | Uniform random | seed |
| `GaussianNoise` | Normal distribution | seed, mean, std_dev |
| `PoissonNoise` | Discrete events | seed, lambda |
| `PinkNoise` | 1/f noise | seed |
| `CorrelatedNoise` | Temporal smoothing | seed, correlation |
| `SpatialNoise` | Position-based | seed |
| `PerCharacterNoise` | Per-index deterministic | seed |
| `ImpulseNoise` | Random impulses | seed, probability |
| `StudentTNoise` | Heavy-tailed | seed, df |
```rust
let gaussian = GaussianNoise::new(42, 0.0, 1.0);
let per_char = PerCharacterNoise::with_seed(99);
```
### Fast Variants (SplitMix64, ~25x faster)
| `FastSeededRandom` | Fast uniform [0, 1] |
| `FastPinkNoise` | Fast 1/f noise |
| `FastCorrelatedNoise` | Fast temporal smoothing |
---
## Envelopes
Time-shaped control signals from `mixed_signals::envelopes`.
| `Adsr` | Attack-Decay-Sustain-Release (normalized time) | attack, decay, sustain, release, peak |
| `LinearEnvelope` | Attack/hold/release (normalized time) | attack, release, peak |
| `Impact` | Percussive hit (absolute time) | intensity, decay |
| `LinearDecay` | Linear falloff (absolute time) | duration |
| `ExponentialDecay` | Exponential falloff (absolute time) | rate |
```rust
let adsr = Adsr::new(0.1, 0.2, 0.7, 0.3);
let impact = Impact::new(1.0, 3.0);
let linear_decay = LinearDecay::new(1.5);
let exponential_decay = ExponentialDecay::new(2.0);
```
---
## Physics
Deterministic physics solvers from `mixed_signals::physics`. All implement `Signal`.
| `DampedSpring` | Harmonic oscillation with damping | Bouncy buttons, elastic snap-back |
| `BouncingDrop` | Multi-bounce with energy loss | Modal drop-in, notifications |
| `FrictionDecay` | Exponential velocity decay | Scroll momentum, fling gestures |
| `SimplePendulum` | Pendulum oscillation | Swinging elements |
| `CircularOrbit` | Uniform circular motion | Loading spinners, radial menus |
| `BallisticTrajectory` | Projectile motion | Thrown objects, arcs |
| `PointAttractor` | Force field toward a point | Magnetic snap, gravity wells |
```rust
use mixed_signals::physics::{DampedSpring, BouncingDrop};
let spring = DampedSpring::default();
let drop = BouncingDrop::rubber_ball(0.0, 300.0, 500.0);
```
### DampedSpring
```rust
DampedSpring::default() // Slightly underdamped
DampedSpring::critically_damped(k, x0) // No overshoot
DampedSpring::with_stiffness(k) // Custom stiffness
```
### BouncingDrop
```rust
BouncingDrop::rubber_ball(start, ground, gravity) // restitution=0.6
BouncingDrop::no_bounce(start, ground, gravity) // restitution=0.0
drop.time_to_first_bounce()
drop.duration_until_stop()
```
### PointAttractor
```rust
PointAttractor::new(target_x, target_y, strength)
PointAttractor::with_falloff(x, y, strength, falloff) // Custom falloff
PointAttractor::linear(x, y, strength) // falloff=1.0
PointAttractor::cubic(x, y, strength) // falloff=3.0
attractor.force_at(px, py) // Returns (fx, fy)
```
See `docs/PHYSICS_SOLVERS.md` for comprehensive documentation.
---
## Easing
Smooth interpolation curves from `mixed_signals::easing`.
```rust
use mixed_signals::easing::{ease, EasingType};
let eased = ease(0.5, EasingType::CubicOut);
```
### EasingType (25 variants)
| Linear | `Linear` |
| Quad | `QuadIn`, `QuadOut`, `QuadInOut` |
| Cubic | `CubicIn`, `CubicOut`, `CubicInOut` |
| Sine | `SineIn`, `SineOut`, `SineInOut` |
| Back | `BackIn`, `BackOut`, `BackInOut` |
| Elastic | `ElasticIn`, `ElasticOut`, `ElasticInOut` |
| Bounce | `BounceIn`, `BounceOut`, `BounceInOut` |
| Expo | `ExpoIn`, `ExpoOut`, `ExpoInOut` |
| Circ | `CircIn`, `CircOut`, `CircInOut` |
See `docs/EASING_CATALOG.md` for detailed descriptions.
---
## Composition
Signal combining operators from `mixed_signals::composition`.
| `Add<A, B>` | Sum two signals | Unclamped |
| `Multiply<A, B>` | Multiply two signals | Unclamped |
| `Mix<A, B>` | Linear blend | lerp(a, b, blend) |
| `WeightedMix` | Weighted N-signal average | Normalized |
| `FrequencyMod` | FM synthesis | Modulated frequency |
| `VcaCentered` | Voltage-controlled amp | Centered scaling |
```rust
let sum = Add::new(sine, noise);
let mix = Mix::new(signal_a, signal_b, 0.3);
let weighted = WeightedMix::new()
.add(signal_a, 0.6)
.add(signal_b, 0.4);
```
**Note**: Composition operators do not clamp output, enabling proper audio/synthesis workflows.
---
## Processing
Signal transformation from `mixed_signals::processing`.
### Core Transforms
| `Normalized<S>` | Convert to [0, 1] |
| `NormalizedFrom<S>` | Normalize from explicit range |
| `Abs<S>` | Absolute value |
| `Invert<S>` | Negate value |
| `Clamp<S>` | Hard limit to [min, max] |
| `Remap<S>` | Map between ranges |
| `Quantize<S>` | Discretize to N levels |
```rust
let normalized = Normalized::new(sine);
let clamped = Clamp::new(signal, 0.0, 1.0);
let remapped = Remap::new(signal, SignalRange::BIPOLAR, SignalRange::new(0.0, 480.0));
```
### Audio Filters (Stateful)
| `Biquad<S>` | IIR filter (lowpass, highpass, bandpass, notch, allpass) |
| `Svf<S>` | State variable filter |
| `LowPass<S>` | Single-pole smoothing |
| `Clipper<S>` | Hard/soft clipping |
```rust
let lowpass = LowPass::new(signal, 0.1); // cutoff
```
### Helper Functions
```rust
use mixed_signals::processing::{bipolar_to_unipolar, unipolar_to_bipolar, remap_range};
let normalized = bipolar_to_unipolar(-0.5); // 0.25
let bipolar = unipolar_to_bipolar(0.75); // 0.5
```
---
## Shuffle
Deterministic shuffling algorithms from `mixed_signals::shuffle`.
| `fisher_yates` | O(n) | Standard unbiased shuffle |
| `sattolo` | O(n) | Cyclic permutation (no fixed points) |
| `partial_shuffle` | O(k) | Shuffle only first k elements |
| `shuffle_copy` | O(n) | Non-mutating shuffle |
| `weighted_shuffle` | O(n log n) | Priority-biased ordering |
| `constrained_shuffle` | O(n²) | Max consecutive repeats |
| `riffle_shuffle` | O(n) | Realistic card riffle |
| `overhand_shuffle` | O(n) | Casual card shuffle |
| `interleave` | O(n) | Deterministic Faro shuffle |
| `reservoir_shuffle` | O(n) | Streaming/iterator input |
| `smooth_shuffle` | O(n²) | Minimize jarring transitions |
```rust
use mixed_signals::shuffle::fisher_yates;
use mixed_signals::rng::Rng;
let mut rng = Rng::with_seed(42);
let mut items = vec![1, 2, 3, 4, 5];
fisher_yates(&mut items, &mut rng);
```
### Animators
Frame-by-frame shuffle visualization:
- `RiffleAnimator` - Stepped riffle animation
- `OverhandAnimator` - Stepped overhand animation
---
## RNG
Traditional random number generation from `mixed_signals::rng`.
```rust
use mixed_signals::rng::Rng;
let mut rng = Rng::with_seed(42);
```
| `uniform(min, max)` | Uniform in range |
| `gaussian(mean, std_dev)` | Normal distribution |
| `poisson(lambda)` | Discrete event count |
| `chance(probability)` | Boolean probability test |
| `choose(&items)` | Random selection |
| `shuffle(&mut items)` | In-place shuffle |
| `shuffle_cyclic(&mut items)` | Sattolo shuffle |
| `shuffle_partial(&mut items, k)` | Partial shuffle |
| `shuffle_weighted(items)` | Weighted shuffle |
```rust
let dice = rng.uniform(1.0, 7.0).floor() as i32;
let hit = rng.chance(0.7);
let color = rng.choose(&["red", "green", "blue"]);
```
---
## Types
### SignalSpec
Serializable signal specification for hot-reloading.
```rust
use mixed_signals::types::SignalSpec;
let spec = SignalSpec::Sine {
frequency: 1.0,
amplitude: 1.0,
offset: 0.0,
phase: 0.0,
};
let signal = spec.build().unwrap();
```
Supports JSON/TOML configuration:
```json
{
"type": "mix",
"blend": 0.2,
"a": { "type": "sine", "frequency": 1.0 },
"b": { "type": "white_noise", "seed": 42 }
}
```
### SignalOrFloat
Parameter that can be a signal or constant.
```rust
use mixed_signals::types::SignalOrFloat;
let param = SignalOrFloat::Float(0.5);
let param = SignalOrFloat::Signal(Box::new(sine));
```
---
## Math Utilities
Low-level utilities from `mixed_signals::math`.
### Bezier Curves
```rust
use mixed_signals::math::{solve_bezier, quadratic_bezier};
let t = solve_bezier(target_x, x1, y1, x2, y2);
let y = quadratic_bezier(t, p0, p1, p2);
```
### Fast Random
```rust
use mixed_signals::math::{fast_random, fast_random_batch};
let value = fast_random(seed, key); // [0, 1]
fast_random_batch(seed, &keys, &mut output); // Vectorized
```
---
## Visualization
Optional TUI visualization (requires `visualization` feature).
```toml
[dependencies]
mixed-signals = { version = "0.2.1", features = ["visualization"] }
```
```rust
use mixed_signals::visualization::{SignalView, RenderMode};
let view = SignalView::new(signal)
.render_mode(RenderMode::Braille);
```
---
## Feature Flags
| `std` | Standard library support (default) |
| `visualization` | SignalView widget (ratatui + crossterm) |
| `audio` | WAV file generation (hound) |
| `realtime-audio` | Real-time playback (rodio, requires ALSA on Linux) |
---
## See Also
- `README.md` - Overview and quick start
- `QUICKSTART.md` - 5-minute getting started guide
- `CHEATSHEET.md` - Quick reference
- `docs/PHYSICS_SOLVERS.md` - Physics solver catalog
- `docs/EASING_CATALOG.md` - Easing curve catalog
- `HOWTO-VISUALIZER.md` - Example demos guide