Sound design via tropical geometry β draw a tropical curve, hear the sound.
Synthesizer patch design is an art form. You twiddle knobs until something sounds right, but there's no mathematical framework that tells you why a patch works or how to smoothly morph between two patches. The space of possible sounds is vast and unstructured.
Tropical geometry replaces addition with max and multiplication with addition. This simple change turns smooth algebraic curves into piecewise-linear ones with sharp corners and edges. And those corners and edges map perfectly to synthesizer parameters:
- Each vertex of a tropical polynomial β a distinct synth patch
- Each edge between vertices β a smooth morphing path between patches
- The Newton polytope (the convex hull of exponent vectors) β the entire timbre space
The "aha moment" is that tropical polynomials are the same as ReLU neural networks. A tropical polynomial max(cβ + aβΒ·x, cβ + aβΒ·x, ...) is exactly a single-layer ReLU network with specific weight constraints. This means:
- Sound design = network architecture design
- Patch morphing = interpolation along tropical edges
- Timbre space = Newton polytope of the tropical polynomial
This crate implements:
- The tropical semiring (max-plus algebra) with proper
AddandMuloperators - Tropical polynomials with evaluation and active-region classification
- Newton polytopes (vertices as synth patches)
- SynthPatch β full synthesizer parameters derived from tropical vertices
- MorphPath β linear interpolation between patches along tropical edges
- TimbreSpace β the complete navigable sound-design space
- MIDI CC mapping β convert any patch to standard MIDI control messages
ββββββββββββββββββββββββββββββββββββββββββββββββ
β TimbreSpace β
β (polynomial β patches β morph paths) β
βββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βββββββββββββββββΌβββββββββββββββββββββββββββββββ
β TropicalPolynomial β
β (max of tropical monomials) β
β evaluate(), active_monomial(), classify_grid()β
βββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
ββββββββββββ΄βββββββββββ
β β
ββββββββββΌβββββββββ ββββββββββΌβββββββββ
β Tropical β β Newton β
β Monomial β β Polytope β
β (c β xβ^aβ β β¦)β β (vertices = β
β β β patches) β
βββββββββββββββββββ ββββββββββ¬βββββββββ
β
βββββββββββΌββββββββββ
β SynthPatch β
β (oscillators, β
β filter, envelope,β
β effects) β
βββββββββββ¬ββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β β β
ββββββββββΌβββββββ βββββββΌβββββββ ββββββββΌβββββββ
β MorphPath β β MIDI CC β β Patch β
β (lerp at t) β β Mapper β β from_vertexβ
βββββββββββββββββ ββββββββββββββ βββββββββββββββ
| Module | Purpose |
|---|---|
semiring |
The tropical semiring: Tropical(f64) with max-plus algebra |
polynomial |
Tropical monomials, polynomials, Newton polytopes |
patch |
SynthPatch with oscillators, filter, envelope, effects |
morph |
MorphPath β linear interpolation between patches |
timbre |
TimbreSpace β the full navigable sound space |
midi |
MIDI CC mapping from patches to control messages |
error |
Error types |
| Operation | Standard | Tropical |
|---|---|---|
| Addition (β) | a + b | max(a, b) |
| Multiplication (β) | a Γ b | a + b |
| Zero (additive identity) | 0 | ββ |
| One (multiplicative identity) | 1 | 0 |
| Power: xβΏ | x Γ x Γ ... Γ x | x + x + ... + x = nΒ·x |
use tropical_synth::Tropical;
let a = Tropical(3.0);
let b = Tropical(5.0);
// Tropical addition = max
assert_eq!(a + b, Tropical(5.0));
// Tropical multiplication = addition
assert_eq!(a * b, Tropical(8.0));
// Identities
assert_eq!(Tropical::ZERO + a, a); // -β β a = a
assert_eq!(Tropical::ONE * a, a); // 0 β a = a
// Power = scalar multiplication
assert_eq!(Tropical(3.0).pow(4), Tropical(12.0));A tropical polynomial is the max of tropical monomials:
p(x) = max(cβ + aβΒ·xβ + bβΒ·xβ, cβ + aβΒ·xβ + bβΒ·xβ, ...)
Each monomial is a hyperplane in the input space. The polynomial's graph is a piecewise-linear convex function whose "corners" are where the active monomial changes.
use tropical_synth::{TropicalPolynomial, TropicalMonomial};
let poly = TropicalPolynomial::new(vec![
TropicalMonomial::new(0.0, vec![2, 0]), // 2xβ
TropicalMonomial::new(0.0, vec![0, 2]), // 2xβ
TropicalMonomial::new(3.0, vec![1, 1]), // 3 + xβ + xβ
]);
// Evaluate at a point
let val = poly.evaluate(&[1.0, 2.0]).unwrap();
// max(2Β·1, 2Β·2, 3+1+2) = max(2, 4, 6) = 6
// Which monomial is active?
let idx = poly.active_monomial(&[10.0, 0.0]).unwrap();
// At (10, 0): 2Β·10=20 wins β monomial 0The Newton polytope of a tropical polynomial is the convex hull of the exponent vectors. Each vertex of this polytope corresponds to a monomial, and in this crate, to a synth patch.
The edges of the Newton polytope are the morph paths β smooth transitions between patches where one monomial hands off to another.
A tropical polynomial max(cβ + aβΒ·x, ..., cβ + aβΒ·x) is exactly a single-layer ReLU network:
y = max_i (cα΅’ + aα΅’ Β· x) = max(WΒ·x + b)
This means:
- Training a ReLU network = fitting a tropical polynomial
- Network width = number of monomials
- Network depth = degree of the polynomial
- Sound design = network architecture design
use tropical_synth::{
TropicalPolynomial, TropicalMonomial, TimbreSpace, MorphPath
};
// Define a tropical polynomial (3 patches in 2D parameter space)
let poly = TropicalPolynomial::new(vec![
TropicalMonomial::new(0.0, vec![2, 0]),
TropicalMonomial::new(0.0, vec![0, 2]),
TropicalMonomial::new(3.0, vec![1, 1]),
]);
// Build the timbre space
let space = TimbreSpace::new(poly).unwrap();
println!("{} patches", space.len());
// Get the active patch at a parameter point
let patch = space.active_patch(&[5.0, 0.0]).unwrap();
println!("Filter cutoff: {:.0} Hz", patch.filter.cutoff_hz);
// Morph between two patches
let mut morph = space.morph(0, 1).unwrap();
morph.set_t(0.5).unwrap();
let mid = morph.current_patch();
println!("Midpoint cutoff: {:.0} Hz", mid.filter.cutoff_hz);Each vertex of the Newton polytope maps to a full synth patch:
use tropical_synth::SynthPatch;
// From a tropical vertex (exponents, coefficient)
let patch = SynthPatch::from_vertex(&[2, 1], 1.5);
// - Exponent sum β number of oscillators (1-3)
// - First exponent β waveform (saw, square, triangle, sine, noise)
// - Coefficient β filter cutoff (logarithmic)
// - Second exponent β envelope attack
println!("Oscillators: {}", patch.oscillators.len());
println!("Waveform: {:?}", patch.oscillators[0].waveform);
println!("Cutoff: {:.0} Hz", patch.filter.cutoff_hz);
println!("Attack: {:.3}s", patch.envelope.attack_s);Any patch can be converted to standard MIDI CC messages:
use tropical_synth::{SynthPatch, MidiCCMapper};
let mapper = MidiCCMapper::new(0); // channel 0
let patch = SynthPatch::simple();
let messages = mapper.map_patch(&patch).unwrap();
for msg in &messages {
println!("CC{} = {} (ch{})", msg.cc, msg.value, msg.channel);
}
// Output: CC7 (volume), CC74 (brightness), CC73 (attack), CC72 (release), etc.Standard CC mappings:
| Parameter | CC Number |
|---|---|
| Volume | 7 |
| Brightness (filter cutoff) | 74 |
| Filter resonance | 71 |
| Attack | 73 |
| Release | 72 |
| Decay | 75 |
| Sustain | 70 |
| Reverb | 91 |
| Chorus | 93 |
| Detune | 94 |
- Tropical evaluation: O(n) where n = number of monomials
- Active monomial: O(n) linear scan
- Grid classification: O(resolution^d) where d = dimensionality
- Patch morphing: O(1) β linear interpolation of numeric fields
- MIDI mapping: O(1) per patch
All operations are real-time safe β no allocation in the hot path.
| Feature | tropical-synth | Traditional synths | Neural audio |
|---|---|---|---|
| Patch structure | Tropical vertices | Knob positions | Network weights |
| Morphing | Tropical edge interpolation | Crossfade | Latent interpolation |
| Space structure | Newton polytope | Unstructured | Latent space |
| Mathematical foundation | Tropical geometry / ReLU networks | None | Deep learning |
| MIDI output | β Built-in | β Native | β |
| Patch from math | β from_vertex() | β | β |
tropical-synth integrates with:
lotka-beatsβ species timbre profiles use tropical patchesgroovemesh-plrβ PLR transitions mapped to tropical morph pathsspreadsheet-engineβ tropical polynomials as formula cell inputsnoether-guardβ conservation checking for energy-like tropical quantities
MIT