Eighty-seven classes that compute what a physical object would do rather than replaying a recording of one. Ready-made instruments at the top, and the waveguide primitives to build your own underneath.
1. The idea
A physical model computes a mathematical description of a sound source — the stiffness of a bar, the length of a tube, the pressure of a breath — and lets the sound emerge from that simulation. Nothing is sampled and nothing is pre-baked.
The payoff is expressiveness. Because the parameters are physical, they behave the way physical things behave: strike a modelled drum harder and the timbre changes, not just the level; shorten a modelled string and the harmonics shift as they would on a real one. This is very difficult to achieve with sampling and effortless here.
The cost is that a physical model, like a physical instrument, usually needs to be excited before it does anything. This is the single most common reason a physical model appears to be silent.
"A West African goblet drum, computed from first principles"
perc := Djembe new.
dsp := perc asDsp.
dsp init.
dsp start.
dsp displayUI. "press DjembeTrigger to strike it"
dsp stop.
2. Modal percussion
ModalPercussion covers struck objects, modelled as a bank of resonant modes.
Four of the eight are bells, tuned to the different national traditions of bell founding —
which is exactly the kind of thing a physical model can express and a sample library cannot
generalise.
| Class | Instrument |
|---|---|
| Djembe | West African goblet drum |
| DjembeMIDI | Djembe with MIDI note input |
| Marimba | Sub-Saharan idiophone with tuned bars |
| MarimbaMIDI | Marimba with MIDI note input |
| EnglishBell | English bell tuning |
| FrenchBell | French bell tuning |
| GermanBell | German bell tuning |
| RussianBell | Russian bell tuning |
Underneath them are PhModalModel and PhModeFilter, which let you
specify your own set of modes — frequency, gain and decay time each — and so build an object
that has never existed. See Synthesis §4.
Marimba for
Djembe in a working patch requires changing exactly one word, which makes them
ideal for learning what modal parameters actually do.
3. String instruments
3.1 Ready-made instruments
| Class | Instrument |
|---|---|
| ElecGuitar | Electric guitar, plucked string model |
| ElecGuitarMIDI | Electric guitar with MIDI note input |
| Guitar | Acoustic guitar |
| GuitarMIDI | Acoustic guitar with MIDI note input |
| NylonGuitarMIDI | Nylon-string guitar |
| ViolinModel | Bowed violin |
| ViolinMIDI | Violin with MIDI note input |
| KarplusStrongMIDI | Karplus–Strong plucked string |
"Guitar into a reverb — the example from MasterLu lesson 6"
synth := ElecGuitar new => GreyHole new.
dsp := synth asDsp.
dsp init.
dsp start.
dsp displayUI. "press ElecGuitarTrigger to pluck"
dsp stop.
The bowed models are the ones that reward experimentation most: bowPressure:
and bowVelocity: interact the way a real bow does, including the ability to
produce a scratchy, unstable tone if you get the combination wrong.
3.2 String parts
The instruments above are assemblies. The components are available separately, which is how you build an instrument that does not exist yet:
| Class | Role |
|---|---|
| PhIdealString | A lossless ideal string |
| PhSteelString, PhNylonString | Strings with material-appropriate damping |
| PhOpenString | String open at both ends |
| PhOpenStringPickup, PhOpenStringPickdown | Open string with pickup direction |
| PhNylonGuitar, PhNylonGuitarModel | Assembled nylon guitar body |
| PhStringSegment | A length of string, for building composites |
| PhGuitarBridge, PhGuitarNuts | Terminations at each end of the string |
| PhLStringRigidTermination, PhRStringRigidTermination | Rigid terminations, left and right |
| PhKarplusStrong | The Karplus–Strong algorithm itself |
| PhKsReflexionFilter | Reflection filter for Karplus–Strong |
| PhBridgeFilter | Bridge filtering |
4. Wind instruments
| Class | Instrument |
|---|---|
| FluteModel | Flute — a jet driving an open tube |
| FluteMIDI | Flute with MIDI note input |
| ClarinetMIDI | Clarinet, single reed |
| BrassMIDI | Brass instrument, lip-driven |
4.1 Wind parts
Wind models are built from an excitation mechanism plus a resonating tube, and both halves are separately available:
| Class | Role |
|---|---|
| PhTube, PhOpenTube | The resonating air column |
| PhReedTable | Reed nonlinearity table |
| PhClarinetReed, PhClarinetMouthPiece | Clarinet excitation |
| PhClarinetModel, PhClarinetUI | Assembled clarinet, with and without interface |
| PhFluteJetTable | Flute jet nonlinearity |
| PhFluteModelUI, PhFluteUI | Assembled flute with interface |
| PhBrassLipsTable | Brass lip-reed nonlinearity |
| PhBrassModelUI, PhBrassUI | Assembled brass model with interface |
…Table classes provide, and swapping one for another turns one instrument into
another.
5. Exciters
An exciter is what sets a model in motion: a strike, a pluck, a puff of air. Because they are separate objects, any exciter can drive any resonator.
| Class | Excitation |
|---|---|
| PhStrike, PhStrikeModel | A struck impulse, with contact modelling |
| PhPluckString | A plucked displacement |
| PhImpulseExcitation | A bare impulse |
| PhBlower, PhBlower_UI | Breath pressure for wind models |
PhBlower instead of PhPluckString, or a
modal bar with a noise burst, produces instruments that do not exist physically but remain
entirely coherent — because the resonator still behaves like an object.
6. Formant and vocal synthesis
Formant synthesis models the resonances of the vocal tract — the fixed frequency bands that make a vowel recognisable regardless of pitch.
| Class | Method |
|---|---|
| SFFormantModelBP | Band-pass filter bank formant model |
| SFFormantModelBP_ui | Band-pass model with interface |
| SFFormantModelFofCycle | FOF granular formant synthesis |
| SFFormantModelFofCycle_UI | FOF model with interface |
| PhVoiceGender | Vocal tract gender parameter |
7. Building your own: bidirectional waveguides
The deepest layer is a set of bidirectional waveguide primitives — where signals travel in two directions along a medium and reflect at its ends, exactly as waves do in a real string or tube. These are the pieces the instruments above are assembled from.
| Class | Role |
|---|---|
| PhWaveguide | The waveguide itself |
| PhPmElement | Superclass of bidirectional elements |
| PhPmOutElement | Superclass of output-side elements |
| PhChain, PhEndChain | Assemble elements into a chain and terminate it |
| PhBasicBlock | A generic block within a chain |
| PhTerminations | Termination behaviour at the chain ends |
| InLeftWave, InRightWave, InLeftRightWave | Inject a signal travelling in a given direction |
| OutLeftWave, OutRightWave, OutLeftRightWave | Tap a signal travelling in a given direction |
| CloseIns, CloseOuts | Close the unused ends of a chain |
| PhAllpassNL | Nonlinear allpass — adds the character of a driven medium |
| PhF2l, PhL2f, PhL2s | Conversions between frequency, length and samples |
PhNylonGuitarModel, PhClarinetModel — as worked examples
rather than starting from primitives.
PhF2l and its siblings are worth knowing about even if you never build a
waveguide: they convert between a pitch and the physical length that produces it, which is
how a model knows how long to make its string when you ask for a note.
8. The physical setters
Physical models take physical parameters, supplied by two dedicated traits. These are what make the family expressive:
| Setter | Controls |
|---|---|
| pressure: | Breath or bow pressure |
| breathGain: | Amount of breath noise in a wind model |
| bowPressure: | How hard the bow presses |
| bowVelocity: | How fast the bow moves |
| bowPosition: | Where along the string the bow contacts |
| pluckPosition: | Where along the string it is plucked |
| strikePosition: | Where the object is struck |
| strikeSHarpness: | How sharp the strike is — mallet hardness |
| stringLength: | Physical string length |
| tubeLength: | Physical tube length |
| bellOpening: | How open the bell of a brass instrument is |
| stiffness: | Material stiffness — affects inharmonicity |
| excitation: | The excitation signal itself |
| length: | Generic length parameter |
pluckPosition: and strikePosition: change timbre without changing
pitch or loudness, because they change which modes get energy. Sweeping one under an LFO or
an envelope is a very cheap way to make a model sound played rather than triggered.
10. Troubleshooting
The model is completely silent
It has not been excited. Open dsp displayUI and press the trigger, or send
dsp trig: 'DjembeTrigger' — §1.
A wind model makes a continuous tone I cannot stop
Breath pressure is a sustained parameter, not a trigger. Set pressure: or
breathGain: back to zero — §8.
The bowed string sounds scratchy and unstable
That is physically accurate: the bow pressure and velocity combination is outside the range that sustains a stable Helmholtz motion. Adjust both together — §3.1.
Changing the frequency changes the timbre too
Expected. In a physical model, pitch comes from the size of the object, and size affects which modes ring. This is the behaviour you are paying for.
playNote:prefix:dur: does nothing on a model
Its frequency and gate are not labelled to match the prefix. Set them with symbols first — see Parameters §2.
My hand-built waveguide is silent, or explodes
Almost always the terminations: an unterminated chain leaks, and a chain terminated with too
much reflection gain runs away. Check CloseIns/CloseOuts and the
reflection coefficients — §7.