◆ Phonon
Digital Instrument Environment
Phonon is a modular digital instrument environment for composing, performing, and experimenting with sound and vision. It combines a hierarchical module system, a chord-aware harmonic engine, a timeline-based arrangement view with full parameter automation, audio track support, hardware-accelerated video playback with real-time shader effects, performance zones with a dedicated DJ mode for live audiovisual sets, and a library of over 230 synthesizers, drum machines, samplers, effects, and generative tools — all running through a signal path modeled after vintage analog mixing hardware.
Phonon's arrangement, mixing, and recording workflows are substantially those of a modern DAW — timeline, tracks, regions, MIDI and audio capture, a full signal-path mixer, parameter automation. What makes it different is what sits on top: any CV can be routed to any knob on any module. Audio or CV signals can drive a real-time visual engine that layers HD video with GPU shader effects. A DJ-inspired performance mode lets you play the whole environment — music and visuals together — as a live instrument, moving nonlinearly between musical and visual states. As far as we know, no other software combines all of this in one place.
Phonon rewards exploration. Its arrangement, mixing, and recording workflows will feel familiar to any DAW user, while the harmonic engine, CV routing, visual engine, and DJ mode open up territory no other tool reaches. It is genuinely powerful, and it does things nothing else can.
01 Getting Started
When Phonon launches, you'll see a splash screen with three options:
✦ Starter Patch: Creates a three-track project: a metallic pluck arpeggio (Harmonic Follower → Preset Machine), a warm pad (Harmonic Follower → Oh Bee Osc → SAM Filter), and a deep house drum kit (FOTF Generator → Analog Kick II + Hi-Hat Synth + CombiSnare). Hit play and hear music immediately.
📄 New Project: Opens an empty project.
📂 Open Project: Load an existing .phonon file.
Links to documentation, a getting-started video, and the Discord community are at the bottom of the splash screen.
After the splash screen, you'll see the main window divided into two areas: the hierarchy tree on the left and the arrangement view filling the rest. The hierarchy shows every module in your project as a tree. The arrangement shows a timeline where you place regions to control when tracks play.
The hierarchy starts with three permanent sections:
🎹 Harmonic Engine — chord progressions
📁 Control — CV sequencers, LFOs
────────────────────
📁 Master — your tracks and modules
└ 📁 Pluck
├ ♫ Harmonic Follower — arp up, octave 3
├ ✦ Preset Machine — Metallic Pluck preset
└ 🔉 Gain
└ 📁 Pad
├ ♫ Harmonic Follower — chord sustained
├ ◫ Oh Bee Osc — dual "SAM" style oscillators
├ ◈ SAM Filter — low cutoff, warm resonance
└ 🔉 Gain
└ 📁 Drums
├ 🏠 FOTF Generator — deep house
├ ◉ Analog Kick II
├ 🎩 Hi-Hat Synth
├ 🪘 CombiSnare
└ 🔉 Gain
────────────────────
🎛 Tuber Console ON
└ ▣ Freebaby — bus compressor
To make sound: right-click Master → Add Track, then right-click the new track → Add Module and choose a synthesizer. The track automatically includes a Gain module at the end for volume and pan control. Press Space to play.
Save your project (Ctrl+S) before importing audio files or
loading samples. Saving creates the project directory, and audio you import afterward is copied
into the project's /samples/ folder — keeping the project self-contained and portable.
If you import before the first save, those files are referenced from their original locations and
can go missing when the project moves.
02 Core Concepts
Module Chains
Modules within a track are processed in series — audio flows from top to bottom. A typical chain: Generator → Synthesizer → Effect → Effect → Gain. The generator produces notes (an arpeggiator, harmonic follower, or sequencer), the synthesizer (or drum machine or sample player) turns them into sound, effects modify it (reverb, filter, delay), and the Gain module controls final volume and pan.
Tracks
Tracks live under Master and are summed together for the final output. Each track is an independent signal chain. Tracks can be muted, soloed, and routed to audio buses. New modules are automatically inserted before the trailing Gain module.
Harmonic Awareness
Phonon's distinguishing feature is its harmonic engine. The Harmonic Engine defines chord progressions organized into banks, sections, and forms. Harmonic Follower modules placed in tracks read the current chord and generate MIDI notes accordingly — arpeggios, pads, bass lines, melodies — all harmonically coherent without manual note programming.
Control Rack
The Control section at the top of the hierarchy holds modulation sources — LFOs, envelope loopers, CV sequencers, and utility modules — that live outside any track. They write to the project's CV buses, and any knob or slider on any module can read from a bus to be modulated. This is how one LFO can sweep a filter, pulse a gain, and animate a visual all at once. See CV Bus System.
Visual Graph
Alongside the audio engine, Phonon runs a real-time visual node graph: a patchable chain of generator and effect nodes that renders audio-reactive visuals and layers them over hardware-accelerated video with GPU shader effects. Audio bands, CV buses, and Blocks signals can all drive the visuals, so the picture moves with the music. See Visuals & Video.
DJ Mode
DJ Performance Mode turns whole Phonon projects into a live instrument. Two decks — each a complete project with its own tracks, effects, video, and visuals — play side by side with a crossfader, per-deck EQ and effects, vinyl scratching, and beat-synced performance zones for jumping around a song. See DJ Performance Mode. (DJ mode is currently in beta — see the note in that section.)
03 Interface
Hierarchy Tree
The left panel shows the module hierarchy as a tree. Right-click nodes to access context menus. Double-click any module to open its dedicated editor window. Drag nodes to reorder them within their parent.
Master: Add Track, Add Audio Bus
Track: Add Module, Add Generator, Send to Bus, Mute, Solo, Rename, Delete
Module: Mute, Rename, Delete
Control: Add Control Module (CV/utility only)
Tuber Console: Add Bus Effect (dynamics, filters, reverb, modulation, stereo, distortion, utility), Open Mixer
Structure / Harmonic Engine / Song Structure: No context menu (permanent fixtures)
Arrangement View
The right side of the main window is the arrangement timeline. From top to bottom:
LOOP — thin lane at the top. Drag to create a loop region.
SONG — global song structure lane. Place colored section markers (Verse, Chorus, Bridge, etc.) with optional tempo and time signature overrides.
Track lanes — one per track under Master. Module/MIDI tracks always play — regions control MIDI note output and variation, not track silence. To silence a track over a span, automate the Gain module's Mute parameter (see Automation Lanes). Audio tracks play where regions contain samples; effects always process.
Automation sub-lanes — thin lanes below any track that has automation. Show the automation curve, editable points, and a mode label ([R] Read, [T] Touch, [—] Off). See Automation Lanes.
Audio track lanes — tracks with WAV regions display waveforms directly in the lane. Drag-and-drop WAV files onto the arrangement to create audio tracks. See Audio Tracks.
🎛 TUBER — gold-tinted lane at the bottom. Place regions here to trigger bus effects.
A 140px column on the left of the arrangement shows track headers (visible by default, toggle with H). Each header contains:
Track type icon: Geometric shapes identify track types at a glance — ● red circle (audio track), ■ blue square (MIDI/normal track), ▲ green triangle (bus), ✕ orange X (Tuber console).
Track name: Truncated to fit the header width.
M / S buttons: Clickable Mute and Solo controls. Mute glows red when active, Solo glows gold. Changes are reflected in both the header and the hierarchy tree.
Gain slider: A handle-less horizontal bar to the right of the M/S buttons. Click and drag to adjust the track's gain in real-time. For normal tracks, the slider controls the GainModule's Volume.Base (linear, unity at center). For the Tuber console, it controls MasterFader. The slider displays the gain in dB, turns orange above unity, and stays in bidirectional sync with the Mixer tab in the drawer — changes in either place update the other.
Level meter: Thin horizontal bar at the bottom of each header showing the track's peak output level. Green → yellow → red color coding. Peak levels are computed per-track from the audio callback with smooth 0.92× decay.
When headers are hidden (H), the arrangement shifts left and floating track labels appear instead. Headers expand vertically with the Z zoom toggle.
Selecting one or more regions opens the Inspector Panel — a 240px sidebar on the right showing editable properties for the selected region(s). The sidebar auto-hides when nothing is selected.
MIDI region controls: Mute (three-state for mixed selections), Transpose (±24 semitones), Velocity Mod (−100% to +100%), and Quantize grid (Off, 1/4, 1/8, 1/8 triplet, 1/8 dotted, 1/16, 1/16 triplet, 1/32). All transforms are non-destructive — the piano roll always shows the original notes, and the transforms are applied at playback time.
Audio region controls: Mute, Loop toggle, Reverse toggle, Retime Method dropdown (Pitch Shift / Granular), Pitch Method dropdown (Granular / Varispeed — controls how per-bucket pitch corrections are applied), current rate display, Remove Retiming button, and Quantize grid. Changing either method immediately changes how audio is played back.
Mixed selection: When both MIDI and audio regions are selected, only Mute is shown (applies to both types).
All sidebar changes are undoable and refresh the arrangement display in real time.
Click a region to select it. Shift+click to add/remove from multi-selection. Ctrl+A selects all regions across all tracks. Escape clears the selection. Selected regions show a blue highlight border.
Ctrl+C copies all selected regions (MIDI and audio) to the clipboard, preserving lane relationships. Ctrl+V pastes at the playhead position with deep-copied data (independent from the source). Delete / Backspace removes all selected regions.
All clipboard operations use compound undo — paste and delete of multiple regions undo as a single action.
Track color: Right-click a track in the hierarchy → 🎨 Track Color. 12 preset colors (Red, Orange, Gold, Green, Teal, Blue, Purple, Pink, Slate, Brown, Mint) or None. Tints the track lane background in the arrangement and adds a colored dot (●) in the hierarchy tree next to the track name.
Region color (track default): Right-click a track → 🎨 Region Color. Sets the default color for all regions on that track (MIDI and audio). Replaces the standard teal/green region fill with the chosen color.
Region color (per-region): Right-click any individual region → 🎨 Color. Overrides the track default for that specific region. Color priority: per-region override → track region color → global default.
All colors serialize with the project.
Follow playhead: When enabled (Settings → "Follow playhead during playback"), the arrangement view automatically scrolls to keep the playhead visible during playback. Scrolling manually during playback breaks the follow — pressing play again resets it. On by default.
Auto-extend: The arrangement canvas automatically grows as you add or extend regions. There is always at least 16 bars of empty space beyond your furthest content. Audio regions are included in the length calculation.
Transport & Position Display
The top info bar shows the Phonon logo on the left, a centered position panel (BPM controls and beat position), and status text with zoom controls on the right. Transport controls (play/stop/record, metronome, visuals) have moved to the Preview Drawer button column. The status text is fixed-width (200px, right-aligned) so it doesn't shift the centered display.
BAR — large bold display showing bar.beat.subdivision (e.g., "3.2.1"). Updates on every playhead movement including arrow keys and micro-nudge.
BPM — shows the current tempo to one decimal place. Click to open a modal input dialog with a numeric spinner (0.1 increment, 20–400 range) and a 🥁 Tap Tempo button. Tap repeatedly to detect BPM from your tapping rhythm (averages the last 2–8 tap intervals, resets after 2 seconds of inactivity). The detected BPM fills the input field in real time. Press Enter or click Set to confirm.
CHORD — gold text showing the current chord from the Harmonic Engine (e.g., "Am7"). Shows "—" when no chord is active.
TIME — elapsed time in minutes:seconds.tenths (e.g., "1:23.4"). Correctly accounts for tempo changes throughout the song by walking through all global region tempo overrides.
Mixer
The mixer is the default tab in the bottom drawer. Switch to it with the 🎚 Mixer tab button at the top of the drawer's column, or press 1 from anywhere in the app (the drawer pops open if collapsed). Each track gets a channel strip with: name, bus routing indicator, Mute / Solo buttons, a rotary Pan knob, a vertical volume fader, and stereo level meters flanking the fader. The master strip sits on the right. Meters show green below −6 dB, yellow approaching 0 dB, and red when clipping. The Tuber Console can be switched to Clean mode from the mixer's top bar.
Rotary knob centered at 0 (center pan). Drag vertically to adjust (100 px of travel = full range). Double-click the knob to reset it to center. Range is −1 (full L) to +1 (full R). Pan is applied per-channel inside the StuderConsole using equal-power cosine/sine panning.
Vertical fader with a custom mixing-desk-style cap handle. The fader is bidirectionally linked to the track's GainModule — moving it in the mixer, changing the Volume knob in the module's Params panel, or CV-modulating the gain all stay in sync.
dB scale with log-taper: the fader uses a Yamaha/Harrison-style piecewise curve so 0 dB (unity) sits at ˜75% travel, with fine control around unity and aggressive attenuation near the bottom. Positions at key breakpoints: bottom → −∞ (true silence, snap zone); 5% travel → −60 dB; 25% → −30; 50% → −12; 75% → 0 (unity); 100% → +12 dB.
Double-click the fader to snap to unity (0 dB). The numeric readout below the fader shows dB (“+3.2 dB”, “−6.0 dB”, “−∞”). The underlying storage is still linear gain, so CV routing, save files, and automation lanes all continue to work unchanged — the dB display and log curve are UI-only.
The master fader uses the same dB convention and taper.
Right-click in the global (SONG) track → 🏁 Set End of Song Here to place a red dashed marker line with "🏁 END" label. When the playhead reaches this marker, stem bounce and recording automatically stop. Right-click again to move or remove it. The marker is serialized with loop zones in the project file.
Preview Drawer
The bottom panel of the main window is the Preview Drawer — a tabbed interface combining audio/video analysis, master processing, and DJ performance controls. A vertical button column on the left provides tab navigation and action buttons.
Page tabs: Mixer (1), Audio Analysis (2), Master Audio (3), Video Analysis (4), Master Video (5).
Action buttons: Record (bounce), Metronome toggle, Open Visuals.
DJ button (pinned to bottom): Enter/exit DJ Performance Mode.
All buttons are 42px with custom-drawn icons. A separator divides page tabs from action buttons.
The left portion of the drawer shows a live OpenGL preview of the visual graph output. The preview respects the video's native aspect ratio with letterboxing/pillarboxing.
Below the preview: 8 custom-drawn buttons — Open Window, Beginning, Prev Bar, Prev Frame, Play/Pause, Next Frame, Next Bar, and Slice. Play syncs with spacebar. Slice creates an undo point and splits video/audio regions at the playhead.
24px stereo VU meter with green→yellow→red gradient, peak hold indicators, clip indicator, and dB tick marks. Fed from the master peak values.
Audio Analysis Tab
Scrolling waterfall display with log frequency scale and a Wikipedia-style color LUT. Uses WriteableBitmap circular buffer. Pink noise compensation for balanced frequency representation.
Lissajous L/R stereo phase scope with blue-cyan color scheme, persistence/decay, and phase correlation meter. Auto-gain scaling for consistent display.
48-band log-frequency bar display with peak hold and frequency labels.
ITU-R BS.1770 loudness metering with K-weighting filter (high shelf + highpass RLB). Displays Momentary (400ms, white needle), Short-term (3s, colored bar), and Integrated (running average since play, resets on play start) LUFS values. True Peak L/R readouts in dBTP with color coding (green/yellow/red). Platform target markers on the meter bar: Spotify/YouTube (−14 LUFS), Apple Music (−16), CD (−9). Scrolling history bar graph at the bottom with platform target lines.
Master Audio Tab
4-band parametric equalizer — low shelf (80 Hz), two peak bands (500 Hz, 3 kHz), high shelf (10 kHz). RBJ biquad filter implementation, stereo processing. Visual display shows live spectrum background with frequency response curve overlay and 4 colored draggable handles (red, gold, green, blue). Double-click a handle to reset it to default frequency and 0 dB gain. Auto-bypasses when all bands are flat.
Brick wall limiter with three large rotary knobs: Threshold (orange, −24 to 0 dB), Ceiling (gold, −6 to 0 dB), Release (blue, 10–500 ms). Gain reduction meter at the bottom with color-coded fill (green → orange → red). Double-click any knob to reset to default.
Mid-side stereo width control with large rotary knob. 0% = mono (side channel zeroed), 100% = normal stereo (unity), 200% = extra wide (side channel doubled). Per-sample smoothing prevents clicks. Stereo field visualization bar and L/R labels. Double-click to reset to 100%.
Tape-style soft-clipping waveshaper (tanh). Variable drive (1× at 0%, 4× at 100%) with automatic gain compensation and dry/wet blend. DC blocker prevents offset buildup. Live transfer curve visualization updates as you adjust the knob. Double-click to reset to OFF.
Signal chain: Audio → Master EQ → Stereo Width → Saturation → Master Limiter → Peak Metering → Analyzer.
Video Analysis Tab
RGB + luminance distribution display from BGRA frame data with overlapping filled curves.
Chrominance distribution on a circular plot. Angle = hue, distance from center = saturation. RGB→YCbCr (BT.601) conversion. Includes SMPTE color bar target boxes (R, MG, B, CY, G, YL), skin tone reference line, quarter-radius graticule circles, and crosshairs. Pixels are color-coded by hue position for intuitive reading. Phosphor persistence decay.
Luminance waveform display — each column of the source frame maps to a vertical brightness plot. IRE grid lines at 0/25/50/75/100%. Click to toggle between Luma mode (single white waveform) and RGB Parade mode (three side-by-side R/G/B waveforms). Phosphor persistence with 60% decay.
Master Video Tab
Full 9-stage GPU color pipeline applied via the ScreenNode shader: input levels → brightness → contrast → gamma → color balance (luminance-weighted shadows/midtones/highlights) → temperature → tint → saturation → output levels. 18 parameters serialized to the project file.
Controls: SlimSlider widgets for levels/tone, ColorWheelControl (circular HSV ring with draggable point) for shadow/mid/highlight RGB offsets. Double-click any control to reset.
Rotary Knobs
All modules use custom-drawn rotary knobs with arc indicators, pointer lines, and tick marks. Drag vertically to adjust. Double-click to reset to the default value (captured at creation time).
04 Controls
Keyboard Shortcuts
| Key | Action |
|---|---|
| Space | Play / Pause. Works from any window — module editors, mixer, bank, etc. All child windows automatically forward transport keys to the main window. With a loop active, playback starts at the loop start. |
| Enter | Stop and return playhead to the beginning of the song. Works from any window. Not intercepted when a text field has focus. |
| X | Switch to the Mixer drawer tab (opens drawer if collapsed). Same as pressing 1. |
| Ctrl+S | Save project. Works from any window. First save prompts for location and creates a project directory. |
| Ctrl+O | Open a project file. |
| Ctrl+N | New project (with confirmation dialog). |
| Ctrl+Z | Undo — reverses exactly one operation. Works from any window. See History Panel. |
| Ctrl+Y | Redo — re-applies the next operation. Works from any window. |
| Ctrl+H | Show / hide the History Panel on the right edge of the window. |
| Ctrl+Shift+B | Arm stem bounce — starts recording per-track stems. |
| Ctrl+P | Enter / exit DJ Performance Mode. |
| 1 | Switch to Mixer drawer tab (opens drawer if collapsed). |
| 2 | Switch to Audio Analysis drawer tab. |
| 3 | Switch to Master Audio drawer tab. |
| 4 | Switch to Video Analysis drawer tab. |
| 5 | Switch to Master Video drawer tab. |
| ← | Move playhead by one bar. |
| → | Move playhead by one bar. |
| Escape | Clear region selection. Exit performance mode if active. |
| Ctrl+← / → | Move playhead by one beat. |
| Ctrl+Shift+← / → | Move playhead by a 16th note. |
| R | Record on the selected track. On an audio track, arms audio recording from the input device (optional 1-bar count-in, configurable in Settings). On a MIDI / instrument track, arms MIDI capture and auto-starts playback. Press R again to stop. See MIDI Recording. |
| Shift+< / > | Micro-nudge playhead by 1/128th note. |
| Ctrl+A | Select all regions (MIDI and audio) across all tracks. Selected regions show a blue highlight and can be dragged together. |
| Ctrl+E | Extract to new project — select tracks to clone into a fresh project. |
| Ctrl+C | Copy selected regions (MIDI and audio) to clipboard. |
| Ctrl+V | Paste clipboard at playhead position (deep copy). |
| Delete / Back | Delete all selected regions. |
| Z | Toggle track zoom — switches between 72px (default) and 36px track height. Zoomed view shows stereo waveform channels stacked. |
| H | Toggle track headers — 140px column with type icons, M/S buttons, and level meters. |
| B | Open / focus the Pattern Bank window (MIDI and Audio banks). |
| V | Open the Visualizer (real-time audio-reactive visuals + node graph). |
Mouse Controls
| Action | Location | Result |
|---|---|---|
| Left click | Empty space below tracks | Move playhead and clear selection |
| Left click | Empty space on a track | Clear selection (does not move playhead — prevents accidental playhead moves when missing a region edge) |
| Left click | Ruler | Move playhead to that position |
| Left click + drag | Ruler | Scrub playhead continuously. Pauses playback on drag start. |
| Left click + drag | Region body | Move region |
| Left click + drag | Region edge (±6px) | Resize region |
| Left click + drag | Loop track | Create or move loop region |
| Right click | Track lane (empty) | Create a new 1-bar region |
| Right click | Audio region | Context menu: slice, copy, paste, loop, mute, warp, detect pitch, reverse, normalize, pitch shift, time stretch, delete |
| Double click | Audio region | Open the Warp Editor (timing + pitch correction hub) |
| Right click | Region | Context menu: section type, variation, mute, delete |
| Right click | Global track (empty) | Create a new 1-bar song section, or set/remove end-of-song marker (🏁) |
| Right click | Global region | Set section type, tempo, time signature, variation |
| Right click | Loop track | Create or remove loop |
| Right click | Any slider/knob | MIDI Learn context menu |
| Ctrl + drag | Region body or edge | Snap to 16th notes (0.25 beats) instead of full beats |
| Drag | Left gold edge | Trim the start of the audio region. For looping regions, trims the loop content start while the region end stays fixed. |
| Drag | Right gold edge | Resize the audio content. For looping regions, changes the loop iteration size while the total loop duration stays fixed. |
| Drag | Loop end edge (outer right) | Extend or shorten the total loop duration. Minimum is one loop iteration. |
| Shift + drag | Left or right gold edge | Non-destructive retime (varispeed — pitch changes with speed). Can be applied from either end. |
| Ctrl+Shift + drag | Left or right gold edge | Non-destructive retime with free positioning (no beat snap). |
| Drag edge, then press Shift | Any gold edge | Seamlessly switches from resize mode to retime mode mid-drag. |
| Drag file | Video track | Drop .mov/.mp4/.avi/.mkv/.webm files to create a video region. Ghost preview shows duration. |
| Left click + drag | Video region body | Move the video clip on the timeline (beat-snapped). |
| Drag | Video region gold edge | Resize/trim the video clip. Left edge adjusts video start offset; right edge capped at video duration. |
| Right click | Video region | Context menu: slice at playhead, copy, duplicate, delete, help. |
| Right click | Video track (empty) | Paste video region at playhead (if clipboard has one), help. |
| Drag | Module in hierarchy | Move module between tracks (drop onto another track's container) |
| Scroll wheel | Arrangement | Scroll horizontally (left/right) — the default |
| Shift + scroll | Arrangement | Scroll vertically (up/down) |
| Ctrl + scroll | Arrangement | Zoom in/out (toward cursor) |
| Double click | Hierarchy tree node | Open module editor window |
| Right click | Hierarchy tree node | Context menu (actions depend on node type) |
| Left drag | Hierarchy tree node | Reorder within the same parent |
05 Song Structure
Harmonic Engine
The Harmonic Engine is the harmonic brain of your project. It defines chord progressions organized into Banks, each containing Sections (groups of chords) and a Form (the order sections play in). The engine advances through chords based on the clock position.
Bank — a complete harmonic setup (e.g., "Verse", "Chorus"). Multiple banks allow different progressions for different song sections.
Section — a group of chord changes within a bank (e.g., Section A: Cm → G♯ → F♯).
Form — the order sections play: [0, 0, 1, 0] means A, A, B, A.
Chord Entry — root note + chord type + duration in measures.
Mood Generator — select a mood from the dropdown and click Generate to create a theory-aware progression. 14 moods: Dark, Melancholy, Ambient, Hopeful, Tense, Uneasy, Awe-Inspiring, Glorious, Frightful, Spooky, Unsettling, Uplifting, Jubilant, Celebratory. Each mood uses appropriate scales (Lydian, Harmonic Minor, Mixolydian, Phrygian, etc.), diatonic chord qualities, and characteristic root movement patterns. Each click generates a unique progression.
The Harmonic Engine does not produce sound — it only manages harmonic state. Harmonic Follower modules read the current chord and generate MIDI notes.
Harmonic Follower
A Harmonic Follower reads the current chord from the Harmonic Engine and generates MIDI note events. Multiple followers in different tracks can interpret the same progression differently — one playing arpeggios, another playing pads, another playing a bass line.
Each follower has a mode that determines how it voices the current chord: chord pads, arpeggios (up/down/random), bass notes, melodic patterns, and more. Modes can be overridden per song section (Verse, Chorus, etc.) so the same follower plays differently in different parts of the song.
Interpolate Chord Changes: When enabled, on the last beat before a chord change, the follower plays only pivot tones — notes that belong to both the current and upcoming chord. For example, going from Cm (C-Eb-G) to Ab (Ab-C-Eb), it plays only C and Eb. This creates smooth Philip Glass-style transitions where the harmony is already halfway to the new chord before it arrives. If no common tones exist, normal playback continues.
Humanize: Multi-layered dynamics model: phrase arcs (velocity rises and falls over 16-beat cycles), metric accent (downbeats louder), breathing (5.5-second sinusoidal swell), melodic contour (higher notes slightly emphasized), chord voice weighting (top note emphasized, inner voices recessed), repetition drift, and micro-jitter.
Global Track
The SONG lane in the arrangement defines song structure visually. Place colored regions representing Verse (blue), Chorus (red), Bridge (green), Intro (amber), Outro (purple), or Break (grey). Each global region can optionally override the tempo and time signature for that section.
Loop Track
The LOOP lane at the top of the arrangement defines a playback loop. Only one loop region can exist. When a loop is active, pressing Play starts at the loop start, and the playhead returns to the loop start when it reaches the end. A subtle green overlay highlights the looped area across all tracks.
Regions
Regions on track lanes serve different purposes depending on track type. Module/MIDI tracks always play — regions control MIDI note output (via MidiRegionModule) and drive pattern variation, but effects, generators, and drum sequencers run continuously. Reverb tails, delays, and other time-domain effects ring out naturally without needing special tail regions. Audio tracks only produce audio where regions contain sample data, but their effects chain always processes (so reverb/delay tails ring out after the region ends). Right-click empty space on a track to create a 1-bar region.
Variation (1–8): Drives pattern variation in sequencer modules.
Mute: For MIDI regions, muting a region skips its note output but does not silence the track — other modules (drum sequencers, generators) continue playing. For audio regions, muted regions produce no audio.
🎹 Edit MIDI: Opens the piano roll for the region.
✂ Split at Playhead: Splits a MIDI region at the current playhead position. Notes spanning the split point are truncated correctly and offsets are adjusted for the second half.
Multi-selection: Press Ctrl+A to select all regions across all tracks. Selected regions show a blue highlight border. Drag any selected region to move all selected regions together — useful for adding breathing room at the start of a song. Press Escape to deselect.
🔁 Loop MIDI: Looping MIDI regions display dimmed note previews at each loop repetition, so you can see the full playback content at a glance. Dashed lines mark loop boundaries.
🎵 Shift: Right-click a MIDI region → Shift submenu to transpose by ±Octave, ±Fifth, or ±Fourth.
06 Modules
Phonon ships with over 230 modules — the building blocks of your instrument. Each module is a link in a track's chain: it receives audio and MIDI events, processes them, and passes them to the next module. Double-click any module in the hierarchy to open its dedicated editor window. Modules can be dragged between tracks in the hierarchy panel.
Synthesizers — Analog
Synthesizers — Digital
Synthesizers — Experimental
Synthesizers — Physical Modeling
Drum Synths
Drum Machines & Pattern Generators
Stack multiple drum synths on one track, each triggered by different MIDI notes from a pattern generator. Layer waveguide snare + noise snare for body + crack. Every voice has independent controls, effects, and automation.
Samplers
Right-click any audio region → 🎹 Convert to Multi Sampler. Automatic transient detection splits the audio, saves slices as WAVs, creates a playable Multi Sampler. Record yourself hitting objects, convert, play.
Effects — Filters
Effects — Reverb & Delay
Effects — Modulation & Dynamics
Effects — Distortion, Character & Stereo
Bus Effects
Designed for the Tuber Console bus or audio bus chains:
Generators & Sequencers
Utility, CV & Control
VST Hosting
VST editor windows use native Win32 hosting for maximum plugin compatibility. Editor windows stay on top of the main Phonon window so they remain accessible while working in the arrangement. Windows auto-resize to match the plugin's reported editor dimensions.
07 Routing
CV Bus System
Phonon has 64 CV buses for control voltage modulation. Control modules (LFOs,
envelope loopers, sequencers, envelope followers) write to buses; audio modules read from them.
Any parameter displayed as a ModParam (the controls with
cv ◂ 3 ▸ depth underneath) can be modulated by a CV bus.
Set the bus number (0–63) and depth (−1 to +1) to modulate the parameter.
A bus value of "—" means no modulation. The final parameter value is:
base + bus[sample] × depth.
Any knob or slider on any module can be CV-modulated by right-clicking and selecting 📡 CV Modulate.... This opens a dialog where you set the CV bus number and depth. The binding is stored on the track and persists across saves — no need to open the module panel after loading.
CV modulation works on any knob or slider across every module, with no per-module setup, and updates continuously as the modulating signal changes.
The Complex Envelope Editor lets you draw arbitrary envelope shapes with multiple control points and 8 curve types: Linear, Exp In, Exp Out, Log In, Log Out, S-Curve, Hold (step), and Bezier (smootherstep). Click to add points, drag to move them (constrained between neighbors), right-click to delete. Press C to cycle curve types. Presets include ADSR, Attack-Release, Ramp Up/Down, Triangle, S-Curve Rise, and Flat.
Three modules use complex envelopes:
Complex Env Module (Utility) — sits in a track chain, triggers on MIDI NoteOn,
writes the envelope shape to a CV bus via WriteImmediate so downstream modules
see the value in the same buffer.
Env Looper (Control rack) — loops the envelope shape continuously on a CV bus. Rate syncs to BPM (beats) or runs free (Hz). Like an LFO with any waveshape you draw.
Cmplx Env Synth (Experimental) — wavetable synth with three built-in complex envelopes controlling morph position, filter cutoff, and amplitude. Self-documenting — the module panel includes full instructions.
Audio Buses
Right-click Master → Add Audio Bus to create a summing bus. Then right-click any track → Send to Bus to route that track's output to the bus instead of the master output. Audio buses appear in the hierarchy with a 🔊 icon and green text. Bus tracks can have their own effects (reverb sends, parallel compression, etc.).
Tuber Console
Phonon's summing path is modeled after vintage mixing hardware. Each channel passes through an input transformer (Beyer/Malotki iron saturation), an ECC83 valve stage (even-harmonic distortion), and an output transformer. Switch it to “Clean” mode from the top bar of the Mixer tab in the drawer to bypass the valve and transformer coloration. New projects default to Clean mode.
A gold 🎛 Tuber Console node sits below Master in the hierarchy, with a corresponding gold lane in the arrangement view.
Adding effects: Right-click the Tuber node → Add Bus Effect. Choose from Dynamics, Filters, Reverb, Modulation, Stereo, Distortion, or Utility.
Audio flow: Tracks → Tuber channel strips → Tuber summing bus → Bus effects chain → Master output.
Block Editor (Visual Patching)
The Block Editor provides a visual node-based patching environment. Create processing nodes, connect them with bezier cables, and build custom signal flows. The system supports 15+ node types with topological sort for correct processing order. CV cables propagate per-sample. Block patches are saved and loaded with the project.
Automation Lanes
Any parameter in Phonon can be automated. Right-click any knob, slider, or integer slider in a module window and select ⤴ Add Automation Lane. A thin automation sub-lane appears below the track in the arrangement view, showing the parameter name and automation curve. Integer parameters (like Metal Noise, step counts, instrument types) are also supported — CV and automation values are rounded to the nearest integer automatically.
Parameters are uniquely identified by their column and control labels (e.g., "VOICE 1.LP Reso" vs "VOICE 2.LP Reso"), so identically-named controls on different voices or sections get independent automation lanes.
Read [R] — plays back recorded automation. The parameter value follows the automation curve during playback, and the slider in the module window moves in real time.
Touch [T] — records while you're touching. During playback, moving the slider (or a MIDI-learned knob) records automation points at the current beat position. When you stop moving, playback resumes from the existing curve. Touch mode punches over existing automation — it erases and replaces the region you're touching.
Off [—] — lane exists but is bypassed. The parameter is not affected.
Editing points: Left-click in an automation lane to add a new point. Drag points to move them (both beat position and value). Hold Ctrl to disable beat snapping for fine positioning. Right-click a point to delete it.
Context menu: Right-click anywhere in an automation lane to switch modes, add or delete points, clear all points, or delete the lane entirely.
Automation data is saved with the project and restored on load. Linear interpolation is used between points. The value holds at the first point before it, and at the last point after it.
08 MIDI Control
MIDI Learn
Every knob and slider in Phonon supports MIDI Learn and automation. Right-click any control to see the context menu:
Select 🎛 MIDI Learn, then move a knob or fader on your MIDI controller. The parameter is now bound — the on-screen slider moves in real time as you turn the physical knob (synced at 20Hz). To remove a binding, right-click the same control and select Remove MIDI Binding.
Select ⤴ Add Automation Lane to create an automation lane for that parameter in the arrangement view. See Automation Lanes for details on recording and editing automation.
MIDI Recording
Any non-audio track can be armed to capture MIDI notes from a connected keyboard. There are two ways to arm:
- Select the track in the hierarchy and press R. This arms and auto-starts playback. Press R again to stop.
- Right-click the track header and choose ⏺ Capture MIDI. This only arms the track — playback must be started separately. Multiple tracks can be armed at once this way.
Arming has an important side-effect: if the track doesn't already have a MIDI Region module in its chain, one is added automatically, so keys you play become audible through the track's instrument stack immediately. This means you can audition sounds while the transport is stopped and actually hear them before recording anything.
Notes played during recording are committed to a fresh MIDI region on the track at the beat position where recording began. Velocity and per-note MIDI CC data (mod wheel, pitch bend, sustain) are captured alongside notes. Transport stop, pause, or pressing R again finalizes the region and disarms the track — arming is a per-take action, not a sticky mode.
Overdub with loop regions. If a loop region is active when recording begins, the capture anchors to the loop bounds and subsequent passes add notes to the same region. Each loop wrap is a new overdub pass — hold a key across the wraparound and the note splits cleanly at the boundary. Stop the transport to commit whatever accumulated across all passes. Without a loop region, recording is linear — rewinding the transport mid-take finalizes and stops.
Live MIDI
Live MIDI lets you play a track's instrument stack in real time from a connected keyboard, independent of record arming. This is the "play alongside the song" workflow: arm a bass track's live MIDI, play along with the arrangement while it plays, no recording, no commit.
Right-click a non-audio track for two menu entries:
- 🎹 Live MIDI: On / Off — toggle the feature on the track.
- Configure Live MIDI Range… — opens a modal where you set the note range (lowest and highest MIDI note) and optionally a specific source device.
The note range lets you split a keyboard across multiple tracks. A common setup: bass track listens to C1–B2, pad track listens to C3–B4, lead track listens to C5 and up. Play the keyboard and each zone automatically routes to the right track. Notes outside a track's range simply don't trigger it.
The source-device filter is useful when you have multiple MIDI inputs connected. For example, leave most tracks on "(Any device)" so any keyboard plays them, but restrict a sound-design track to a specific pad controller so random keyboard input doesn't trigger it accidentally.
Known limitation. Live MIDI currently requires the transport to be playing. Stop the transport and incoming notes are suppressed. This is a side effect of how Phonon's synth modules release voices on transport stop to prevent stuck notes — a safety behavior that also happens to eat live input. For now, start playback (even on an empty song) before playing.
Multiple Input Devices
Phonon's MIDI input layer is a hub — it holds multiple devices open simultaneously and aggregates their events. In practice this means you can have a keyboard and a controller connected at the same time: the keyboard drives notes (for recording and live play), and the controller drives CC bindings (via MIDI Learn) and zone triggers, all without conflict.
Current UI limitation: The Settings window still shows a single device selector. Auto-connect on startup opens whatever device was last used. To actually use a second device today, connect it and it may be picked up automatically depending on the platform; proper multi-device Settings UI is a planned follow-up.
Settings & Persistence
Open ⚙ Settings to select and connect your MIDI input device. Phonon
remembers your device and auto-reconnects on startup. The device preference is stored at
%AppData%/Meadow/midi_device.txt.
MIDI parameter bindings (knob/slider assignments) are saved as a .midi sidecar
file alongside your project. Zone triggers are saved as a .zones sidecar file.
Live MIDI settings (enabled state, note range, preferred device name) are persisted in the
project file alongside each track. All are restored when you reload the project. Bindings
become active when you open the module's editor window (which creates the live parameter
connection).
09 Stem Bounce
Press Ctrl+Shift+B to arm a stem bounce. Phonon resets
to beat 0, starts playback, and records each track's audio output to individual WAV files
in real time. Press Stop to finalize — stems are saved to a timestamped
Stems - date - time/ folder alongside your project. Each file is named
with the track number and name (e.g., 01 - Synth.wav).
This captures VST output, effects, and everything in the signal chain — perfect for importing stems into another DAW or sharing individual track recordings.
For live audiovisual performance — playing music and visuals together as an instrument — see DJ Performance Mode.
10 Audio Tracks
Phonon supports audio tracks alongside its module-based tracks. Create an audio track (right-click Master → Add Audio Track), then drag WAV files onto it in the arrangement view. Record directly from your audio input with the built-in recording system.
Drag & drop import: Drag any WAV file onto an existing audio track lane. A ghost preview shows the exact placement and duration before dropping. Drop position snaps to the nearest beat. Multi-file drop supported. Supports 16-bit, 24-bit, and 32-bit float WAV files.
Audio recording: Press R to arm recording. If the 1-bar count-in
is enabled (Settings → "1-bar count-in before recording"), the playhead moves back one bar,
a metronome count-in plays, and recording starts at the original playhead position. The count-in
setting and metronome toggle are both configurable in Settings. Press Space,
Enter, or R to stop. Audio is trimmed to the beat boundary and auto-saved
to the project's /samples/ folder. Configure input/output devices and sample rate
in Settings.
Region editing: Right-click for context menu: Slice at Playhead, Split at Playhead, Copy, Paste, Loop toggle, Mute, Delete, and Convert to Multi Sampler (with automatic transient detection).
Effects chain: Audio tracks can have child modules just like any other track. Add effects (reverb, delay, EQ, etc.) as children of the audio track and they process the audio output in series.
Portable projects: Audio files are copied into the project's /samples/
folder when saving, so the project is self-contained. All audio processing operations (pitch shift,
reverse, normalize, etc.) also save to the project directory.
Audio Region Tools
Right-click an audio region to access a comprehensive set of non-destructive and destructive
audio processing tools. Destructive operations save a new WAV file to the project's
/samples/ directory.
📊 Analyze BPM: Onset detection with histogram binning. Shows primary BPM, half-time and double-time alternatives, and onset count. Click "Set BPM" to apply the detected tempo to the project transport.
🔄 Change BPM: Non-destructively retime the region to match a new tempo. Enter original and target BPM — the playback rate and duration adjust based on the BPM ratio, equivalent to a shift-drag retime. Warp markers scale proportionally. No resampling, no new files. Fully undoable.
🎯 Quantize To: Non-destructive audio quantization using warp markers. Transient detection finds onsets, then warp markers snap each transient to the nearest grid position (16th, 8th, or quarter notes). The original audio is untouched — playback reads through the warp map. For retimed regions, markers are automatically scaled to match the current playback rate. Set to "Off" to remove quantization and clear warp markers.
⇄ Reverse: Non-destructive reverse toggle. Flips the playback direction without modifying the original audio data. Works with all other non-destructive operations — reverse a retimed, quantized, looping region and everything composes correctly.
📢 Normalize To: Normalize peak level to 0 dB, −3 dB, or −6 dB.
🎵 Pitch Shift: Granular overlap-add pitch shifting. Presets: ±1, ±5, ±7, ±12 semitones plus custom input. Uses 50ms Hann-windowed grains at 50% overlap for time-independent shifting. Level-matched to input peak.
⏱ Remove Time Stretch: Appears only on retimed regions. Resets playback rate to 1.0× and restores the original region duration.
〰 Warp...: Opens the warp editor for non-destructive, per-region time manipulation. Place markers on the waveform and drag to stretch or compress specific sections while preserving pitch. See Warp Editor for full details.
🎵 Detect Pitch...: YIN pitch detection across the region with chord suggestions. Reports up to 6 detected pitch classes and scores 180 chord templates from the Harmonic Engine vocabulary. See Pitch Detection.
Non-Destructive Time Stretching
Audio regions can be retimed non-destructively by holding Shift and dragging either gold edge (left or right). The original WAV file is untouched — only the playback rate changes. Two playback modes are available, switchable at any time from the Inspector sidebar:
Pitch Shift (Varispeed): Changes playback speed and pitch together, like speeding up or slowing down a record. Stretching a region to 2× its original length plays it at half speed, one octave lower. The region label shows ⏩ and the current rate (e.g., "⏩0.50×").
Granular (Pitch-preserving): Changes playback speed while maintaining the original pitch using real-time granular overlap-add synthesis. The region label shows ⏱ and the rate (e.g., "⏱0.50×"). Good for tempo-matching loops and samples.
Switching modes: The retime method dropdown in the Inspector sidebar changes how the region plays back — not how it was stretched. You can retime a region with one method, then switch to the other to hear it differently. The same applies to warped regions: warp markers define the timing, and the retime method controls whether pitch shifts naturally or is preserved.
Composability: Retiming composes correctly with all other non-destructive operations. Warp markers scale proportionally on retime. Looping uses the retimed duration as the loop iteration size. Slicing preserves the playback rate and calculates correct NaturalBeats for each half. Remove retiming (right-click menu or Inspector button) scales warp markers back and restores the original duration.
The audio engine selects the correct playback path automatically based on the region's state:
Warped + Pitch-preserving: Granular OLA through the warp map. Grains read at native speed from warp-mapped source positions.
Warped + Varispeed: Direct read through the warp map. Pitch shifts naturally with the timing changes.
Rate only + Pitch-preserving: Granular OLA at the playback rate (no warp markers).
Rate only + Varispeed: Simple resampling at the playback rate.
Warp Editor
Double-click an audio region to open the warp editor. The editor is a central hub for both timing and pitch correction, controlled by the Edit Layer dropdown.
Warp markers allow per-region, non-destructive time manipulation — stretch or compress specific sections of audio while preserving pitch, without modifying the original file.
Visual waveform: The full waveform is displayed through the warp map — as you drag markers, the waveform visually stretches and compresses in real-time.
Click to add markers: Click anywhere on the waveform to place a warp marker. Flanking markers are automatically created at the nearest transient peaks when needed.
Drag to adjust: Drag any marker left or right to retime that section. Markers are constrained between their neighbors to prevent crossing.
Right-click to delete: Remove any marker except the start/end anchors.
16th note grid: Grid overlay with bar numbers and beat markers for precise alignment.
Switch to Pitch mode via the Edit Layer dropdown for per-segment pitch correction.
Async analysis: On first switch to Pitch mode, the audio is analyzed in the background. A progress bar shows three phases: transient detection (0–30%), YIN pitch tracking (30–80%), and bucket construction (80–100%). A Cancel button aborts the analysis and closes the warp editor. For short clips (<10 seconds), analysis is nearly instant. Results are cached — switching back to Timing and returning to Pitch does not re-analyze.
Pitch buckets: The audio is divided into segments (buckets) at transient boundaries and pitch changes. Each bucket shows its detected pitch as a note name (e.g., A4, F#2) and a horizontal orange line at its current pitch offset. Dashed vertical lines mark bucket boundaries.
Drag pitch lines: Hover over an orange pitch line (N/S cursor appears) and drag vertically to adjust the pitch. Snaps to 0.5 semitone increments, ±12 semitone range. The semitone offset is displayed as a label (e.g., "+3.0st", "−1.5st").
Right-click context menu:
• ✂ Split Bucket Here — divides the bucket at the click position. Both halves inherit the pitch shift.
• ⟶ Merge with Next / ⟵ Merge with Previous — combines adjacent buckets.
• ↺ Reset Pitch — sets the bucket's pitch shift back to 0.
Pitch method: Controlled by the "Pitch Method" dropdown in the Inspector sidebar. Granular (default) shifts pitch without changing timing using OLA synthesis. Varispeed shifts pitch by reading faster/slower, subtly changing timing within each bucket.
Timing and pitch corrections compose correctly: the warp map resolves timing first (beat → source sample position), then pitch bucket adjustments are applied at that position. Both are fully non-destructive — original samples are never modified.
Pitch buckets are stored in absolute sample space, so they survive retime, slice (buckets split at the cut point), copy/paste (deep copied), and serialization. All warp editor changes push a single undo action when Done is clicked.
Pitch Detection & Chord Suggestions
Right-click an audio region → 🎵 Detect Pitch... to analyze the harmonic content using the YIN algorithm (2048-sample chunks with parabolic interpolation).
The analyzer scans the region and builds a 12-bin pitch class histogram weighted by detection confidence. The top 6 pitch classes are reported. Then every chord template in the Harmonic Engine vocabulary (15 types × 12 roots = 180 chords) is scored against the detected pitches using fit ratio (60%) and chord-tone coverage (40%). The top 8 chord suggestions are shown with percentage match scores — useful for identifying the key of a sample or finding compatible chords for the harmonic engine.
Stereo Audio Support
Phonon natively handles stereo WAV files. When a stereo file is imported, left and right
channels are stored separately (SampleData and SampleDataR). Mono
files keep SampleDataR = null for zero memory overhead. All audio operations —
reverse, normalize, pitch shift, quantize, change BPM, slice, copy/paste, time stretch, and
warping — process both channels independently. Playback renders L/R through all paths including
normal, rate-changed, pitch-preserved, and warped.
Snippet Arranger
The Snippet Arranger is a specialized region type on audio tracks for drum programming and sample chopping. It provides a layered timeline view where you place short audio clips — the way breakbeats were traditionally chopped and rearranged. Right-click an audio track lane → Create Snippet Region to get started.
A snippet region contains 8 independent layers, each holding any number of placed audio clips (snippets). Drag WAV files up to 5 seconds long into the snippet arranger to place them on a layer. Each layer can be labeled (e.g. "Kick", "Snare", "Hat"), muted, and has its own gain control. During playback, all non-muted layers are mixed together — each snippet's sample data is read at the correct beat offset and summed into the track's audio output.
Placement: Snippets snap to 16th notes by default. Hold Ctrl to snap to 32nd notes. Hold Shift+Ctrl to move freely with no grid snap.
Right-click: Right-click a snippet to open a context menu with 💾 Save to Audio Bank... (saves the snippet's audio to the shared library) and 🗑 Delete.
📦 Bank button: Opens a file picker pointed at the audio bank folder. Select one or more WAV files to load them as snippets at beat 0.
Selection: Hold Shift and click to multi-select snippets. Copy and paste groups of selected snippets.
Duration: Drag the left or right edge of a snippet to trim its duration. Hold Ctrl and drag the left or right edge to time-stretch the snippet (changes playback rate without affecting pitch).
Velocity: Drag the top edge of a snippet to adjust its gain (0–2×). Per-snippet velocity gives you natural dynamics — accent a snare hit, ghost a kick.
Playback rate: Each snippet stores its own playback rate multiplier (1.0 = normal, 2.0 = double speed / pitch up, 0.5 = half speed / pitch down). Ctrl-drag the edges to set this.
Stereo support: Mono and stereo WAVs are both supported. Stereo snippets are mixed to their respective channels.
When a snippet region is created, a Snippet MIDI module is automatically added to the track's module chain. This module watches snippet positions during playback and emits MIDI note events, so snippets can also trigger downstream synths and effects.
Per-layer MIDI note: Each of the 8 layers has an assignable MIDI note (0–127, or −1 to disable). When a snippet's start position crosses the playhead, the module fires a NoteOn at the assigned pitch with the snippet's gain as velocity.
Per-layer decay: A decay multiplier (0.01–1.0) per layer scales the snippet duration for both audio envelope and NoteOff timing. At 1.0, the note sustains for the full snippet length. At lower values, the audio fades out early — the last 20% of the decay window is a linear fade to zero. This lets you create staccato hits from longer samples without editing each snippet individually.
Layer independence: MIDI note assignments and decay settings live on the Snippet Module (not on the region data), so they're shared across all snippet regions on the same track. Changing the kick layer's decay affects every snippet region on that track.
Audio Region Display
Audio regions display their waveform overview with min/max aggregation. The waveform correctly reflects the current playback rate, reverse state, loop wrapping, and warp markers.
Pattern Bank (MIDI & Audio)
The Pattern Bank is a persistent library of MIDI patterns and audio clips
stored in %APPDATA%/Phonon/Library/. Patterns and clips are saved as standard
files (MIDI Format 0 / 16-bit WAV) and are accessible across all projects.
Press B to open the bank window.
Save: Right-click any MIDI region → 💾 Save to Bank... — enter a name, saved as a standard MIDI file (480 PPQ, Format 0). Stored in Library/MidiBank/.
Browse: The bank window shows cards with name, date, BPM, note count, and a horizontal MIDI note preview strip. Newest files appear first.
Drag to arrange: Drag a card from the bank window onto any non-audio track lane. A ghost preview with note visualization appears during drag, snapping to the beat grid. Drop creates a new MIDI region with deep-cloned notes.
Delete: Click the ✕ button — confirmation dialog before deletion.
Save: Right-click any audio region → 💾 Save to Audio Bank... — saves just the region's slice (SampleOffset to duration), not the entire source file. 16-bit WAV. Stored in Library/AudioBank/. Also available from the snippet arranger: right-click a snippet → Save to Audio Bank.
Browse: The bank window has MIDI and Audio tabs. Audio cards show name, date, duration (seconds/ms), sample rate, mono/stereo, and a waveform peak preview strip.
Drag to arrange: Drag an audio card onto any track lane. Ghost preview with waveform visualization during drag. Drop creates an audio region via AddRegionFromFile.
Load into Snippet Arranger: The snippet arranger has a 📦 Bank button that opens a file picker pointed at the audio bank folder. Select WAVs to load them as snippets.
Normal: Green-tinted region with waveform and filename label.
Muted: Dark grey fill with dimmed waveform, subdued border, and 🔇 prefix on the label.
Broken (missing file): Red-tinted region with diagonal hash lines, red border, and a ⚠ warning showing the missing filename.
Selected: Blue highlight border (Ctrl+A to select all). Drag any selected region to move all selected regions together.
Looping: Dashed lines at each loop boundary with ↻ markers. Loops update in real time as you resize the base content.
Gold edge markers: Both ends of the base audio content are marked with gold lines (#D0A840). For looping regions, the right gold edge marks the end of the first loop iteration, not the end of the total region. Three grabbable edges on looping regions: left gold (trim start), right gold (resize content), and loop end (extend/shorten total duration).
Stereo zoom: Press Z to double track height. Stereo regions show L and R channels stacked with a subtle divider line. The R channel uses a slightly different blue (#5090B0) for visual distinction. Mono regions get a taller single waveform.
Bounce to Audio
Right-click any MIDI region → 🔊 Bounce to Audio to render a track's output to a stereo WAV file in real time. A modal dialog shows progress and provides a Cancel button — the main window is locked during bounce to prevent accidental changes.
The bounce captures the source track's audio output as it plays through the normal audio engine, including all effects in the track's chain. Other tracks are temporarily muted to prevent bleed. A 1-beat pre-roll lets synths and filters settle before capture begins.
When complete: the bounced stereo WAV is saved to the project's /samples/
folder, a new audio track is created with the audio placed at the original position, and the
source region is muted. The original region stays visible (dimmed) so you can unmute it to
go back to the live version.
📂 Show in Folder: Right-click any audio region → 📂 Show in Folder to open the containing folder in your file manager with the file selected. Works on Windows (Explorer), macOS (Finder), and Linux (xdg-open).
MIDI Editing
Double-click a MIDI region in the arrangement to open the Piano Roll editor. The piano roll provides a full-featured MIDI note editing experience.
Note editing: Click to place notes. Drag note body to move. Drag edges to resize. Right-click to delete. Notes snap to the selected grid (1/4, 1/8, 1/16, 1/32). Hold Ctrl for free (unsnapped) mode.
Multi-selection: Click to select a single note. Shift+click to add/remove from selection. Shift+drag on empty space for box select. Ctrl+A to select all. Delete removes all selected notes.
Arrow keys: ↑/↓ transpose selected notes by 1 semitone. ←/→ move by one grid step. Shift+←/→ for fine nudge (1/64th note).
Velocity editing: Ctrl+drag on a note body to adjust velocity vertically. Note color reflects velocity: blue (quiet) → red (loud). Multiple selected notes adjust by the same delta from their original values.
Multi-note resize: Select multiple notes, then drag the edge of any selected note to resize all of them by the same amount. Works for both left and right edges.
Copy/paste: Ctrl+C copies selected notes. Ctrl+V pastes at the playhead position (or after the last note if stopped). Relative positions are preserved.
Live sync: Changes to region length, loop settings, or notes from outside the piano roll are reflected immediately — no need to close and reopen the editor.
Harmonic highlighting: When the Harmonic Engine is active, scale/chord tones are highlighted in the grid. Press ♯ Refresh Key to update after chord changes.
Convert Loops to Regions: Right-click a looping MIDI region → 🔀 Convert Loops to Regions to expand each loop iteration into its own independent MIDI region, editable separately.
Per-note expression curves: Draw pitch bend and volume curves directly on individual notes — no separate automation lane needed. Alt+drag on a note body draws pitch bend (±12 semitones, shown as a gold line through the note center). Alt+Shift+drag draws volume curves (0–1 multiplier, shown as a green line from the note bottom). Alt+right-click clears all expression from a note. Curves are evaluated during playback: pitch bends retrigger at semitone boundaries, volume changes retrigger at 5% threshold. Points merge within proximity to avoid clutter. Full serialization — expression curves save with the project.
Big Mode: Click 🔍 Big Mode in the toolbar to toggle 5× taller notes with 2× horizontal zoom. Designed for precision expression curve editing — the pitch and volume lines become full-size editable curves instead of tiny squiggles on a sliver.
Variant generation: Right-click a MIDI region → 🧬 Generate Variant After... to create a new region placed after the source with melodic, rhythmic, or combined variation. Scale-aware (detects key from the notes). 4 melodic strategies, 6 rhythmic strategies. Undoable.
Per-Note Expression Curves
Phonon lets you draw pitch bend and volume curves directly on individual MIDI notes in the piano roll — no separate automation lane, no MIDI CC editing, no MPE configuration. Each note carries its own expression data.
Alt+drag on a note: draw pitch bend (gold line, ±12 semitones from center)
Alt+Shift+drag: draw volume curve (green line, 0–1 from bottom)
Alt+right-click: clear all expression from a note
🔍 Big Mode: 5× taller notes with 2× zoom for precise curve drawing
During playback, pitch curves retrigger notes at semitone boundaries and volume curves retrigger at 5% threshold changes. Expression data serializes with the project and is preserved through copy/paste and variant generation.
MIDI Output
The MIDI Out module sends MIDI to external hardware synths via Windows MIDI (winmm.dll). Supports channel remap, transpose, velocity scaling, MIDI clock, and transport messages. Place the module in a track's chain after whatever generates notes (MIDI Region, Piano Roll, sequencer, or arpeggiator) and configure the output device in Settings.
A few details worth knowing: clock pulses are timed by beat position rather than wallclock, so they stay locked to tempo through BPM changes and loop wraparound. Retrigger handling sends an implicit NoteOff before a new NoteOn on the same pitch, which is important for hardware synths that track gate state and would otherwise drop the retrigger. Transport stop silences all active notes plus sends All-Notes-Off as a safety net. The Panic button triggers the same cleanup on demand.
Pitch to MIDI
The Pitch → MIDI module uses the YIN algorithm to detect pitch from audio input and convert it to MIDI notes in real time. Features chord quantization (snaps to current Harmonic Engine chord), time quantize (quarter/eighth/sixteenth grid), and configurable smoothing. Sing a melody and it becomes MIDI notes.
Microtonal Tuning
Phonon supports full microtonal compatibility through a global TuningTable. Every synthesizer module references the tuning table instead of hardcoding 12-tone equal temperament. Change the tuning and every synth in the project retunes instantly. The tuning system is serialized with the project file.
Access via right-click Master → 🎵 Tuning submenu.
9 built-in presets: 12-TET (standard), Just Intonation (5-limit), Pythagorean (3-limit), 19-TET, 22-TET, 24-TET (quarter-tone), 31-TET (excellent just intonation approximation), 53-TET (Turkish music), and Bohlen-Pierce (13 equal divisions of the tritave — a non-octave-repeating scale).
Scala file import: Load any .scl file — the standard
microtonal tuning format with thousands of scales available online. Supports both
cents and ratio pitch definitions, and non-octave-repeating periods.
Reference pitch: Adjustable A4 reference (432 Hz, 440 Hz, etc.). The tuning table stores 128 frequency entries and is serialized with the project.
Combined with the Harmonic Engine, microtonal tuning creates chord progressions that use the actual interval relationships of the selected tuning — a major chord in 31-TET uses genuinely different intervals than in 12-TET.
The piano roll dynamically adapts to the active tuning system. It is not a 12-TET grid with microtonal notes crammed between the cracks — the grid itself restructures.
Grid rows = scale degrees. In 19-EDO you get 19 rows per octave. In 31-EDO, 31. Octave boundary lines appear at the correct period boundary for any tuning, including non-octave scales like Bohlen-Pierce.
Color-coded rows: Root notes are highlighted in blue and perfect-fifth equivalents (~702¢) get a subtle highlight. Seven degrees show as "white keys" and the rest as "black keys," giving visual orientation in unfamiliar tunings.
White-key scheme: For any non-12 tuning, a Keys dropdown appears in the piano-roll toolbar with two ways of choosing those seven white keys:
· Classic — the degrees nearest the familiar major-scale intervals (0, 200, 400, 500, 700, 900, 1100¢). A direct approximation of the 12-tone layout — handy for getting your bearings.
· Regular Diatonic — takes whichever degree is closest to a pure 3/2 fifth (~702¢) and stacks seven of them from F (F–C–G–D–A–E–B), revealing the tuning's own diatonic structure instead of approximating 12-TET. In a tuning like 22-EDO this lays out the true diatonic scale where direct approximation would distort it. The choice is saved with the project.
Tuning-aware labels: Root notes show degree and octave (e.g., 0:4 in
non-12 tunings, standard note names in 12-TET). Note labels on MIDI events update to match.
11 Visuals & Video
Phonon integrates a real-time visual engine and hardware-accelerated video playback into a unified system. Press the V key to open the Visualizer — a real-time audio-reactive visual display powered by OpenGL. The visualizer renders in a separate window that defaults to topmost (press T to toggle).
Visual Node Graph
The visual node graph provides a shader patching environment where you combine multiple visual generators and effects into complex compositions. Each node generates or transforms a visual signal. Connect nodes with cables to build effect chains — for example, feed a video clip through a Kaleidoscope node, a Color Map, and a Feedback node for endlessly evolving processed imagery.
Visual patches are saved and restored with the project.
Visual Generator Nodes
Visual Effect Nodes
Video Track
Phonon includes a dedicated video track at the bottom of the arrangement view. Video playback is hardware-accelerated — via Windows Media Foundation (DXVA) on Windows and AVFoundation / VideoToolbox on macOS — and feeds directly into the visual node graph through the Video In node.
Adding clips: Drag .mov, .mp4, .avi,
.mkv, or .webm files from your file explorer onto the video track.
Clips appear as regions with filmstrip thumbnail previews. A loading dialog appears while
audio is extracted from the video file.
Moving clips: Click and drag a clip to reposition it on the timeline. Snaps to beat grid.
Resizing clips: Drag the gold handles on the left or right edge. Resizing adjusts the portion of video the region covers — the playback speed scales proportionally.
Minimum clip size: 1/16th note (0.25 beats).
Video regions are beat-locked — their size in beats never changes when BPM changes. A 1-bar video region is always 1 bar (4 beats), regardless of tempo.
When BPM changes, the video playback speed adjusts automatically to fill the same number of beats. At half the original BPM, the video plays at half speed. At double BPM, double speed. This happens per-frame with no artifacts.
Slicing a region divides its video portion proportionally — each slice plays exactly its share of the original video at whatever speed the current tempo demands.
Right-click a video region for:
✂ Slice at Playhead: Splits the region into two at the current playhead position. Both halves reference the same video file with correct video offsets and durations.
📋 Copy / Paste: Copy a region to the clipboard, then right-click empty space and paste at the playhead position. Audio data and thumbnails are preserved.
⎘ Duplicate: Creates an identical copy placed immediately after the original.
🔇 Mute Audio: Mutes the audio for an individual video region.
🗑 Delete: Removes the region from the timeline.
Video Audio Track
Below the video track, a dedicated Video Audio lane displays and controls the audio embedded in video files. Audio is extracted automatically when a video file is loaded using NAudio (via Media Foundation).
Waveform display: Each video region shows its extracted audio waveform — blue min/max rendering, clipped to region bounds. Muted regions appear dimmed with a 🔇 icon.
M (Mute) button: Mutes all video audio on the track.
Gain slider: 0–2× range (default 0.7). Drag to adjust. Unity gain is marked at center. Shows dB readout. Orange tint when gain exceeds unity.
Per-region mute: Right-click a waveform region → 🔇 Mute Audio / 🔊 Unmute Audio.
BPM-synchronized: Video audio playback speed matches the video — when tempo changes, audio stretches proportionally using linear interpolation for pitch-preserving playback.
Video Playback Engine
Video decoding runs on background threads that stay a few seconds ahead of the playhead, pre-seeking upcoming clips and pre-wrapping the loop point so playback and looping stay seamless.
Video clips are beat-synced — they play in time with the transport. Scrubbing the playhead (even when stopped) updates the visual display in real time. When the playhead is outside any video region, the display goes black.
The visuals window preserves the video's aspect ratio regardless of window size — letterboxing (black bars left/right) or pillarboxing (top/bottom) is applied automatically.
When two video regions overlap on the timeline, Phonon automatically crossfades between
them on the GPU. The blend is computed per-frame using a dual-texture shader —
mix(frameA, frameB, blend) — which runs in microseconds.
The Video In node outputs to the visual node graph just like any generator node. This means you can route video through any combination of shader effects — Kaleidoscope, Color Map, Feedback, Distort, Edge Detect, and more. Effects process in real time at the video's native frame rate.
In DJ Performance Mode each deck carries its own visual graph, so crossfading between decks blends both the music and the video processing chain simultaneously.
This creates a unified audiovisual performance instrument where every system is a force multiplier on every other system.
Export & Bounce
Phonon supports three export modes, accessed via the Record button:
Arms the transport — press Play to begin capturing the master output to a WAV file. Press Stop or reach the End of Song marker to finalize. Audio is captured exactly as it sounds during playback, including all effects, VSTs, and video audio.
Renders the master output to WAV faster than real time — a 5-minute song can export in under a minute. The audio engine is stopped during bounce to prevent interference. Requires an End of Song marker (right-click a region → 🏁 Set End of Song Here).
⚠ VST instruments may be unstable during offline bounce.
Renders synchronized video + audio to an H.264 + AAC MP4 file using Media Foundation. A resolution picker lets you choose:
1280×720 (720p) · 1920×1080 (1080p) · 2560×1440 (1440p) · 3840×2160 (4K)
Frame rate options: 24, 30, or 60 fps.
The visual node graph is rendered offscreen at the target resolution — the visuals window opens automatically if needed, and rendering is independent of the window size. A progress bar with cancel button shows rendering status.
Requires an End of Song marker. Video output includes the full shader effects chain — whatever the visuals window shows during playback is what gets encoded.
12 DJ Performance Mode
DJ Performance Mode is in beta. Everything described here is expected to work, but we're still gathering data on how people actually perform with it — which controls, transitions, and workflows matter most in a live set. Expect this area to evolve, and let us know what you'd want from it. Your feedback directly shapes where it goes.
Phonon includes a full DJ performance system where each "song" is an entire Phonon project — synths, effects, video, visual shaders, and all. Click the DJ button (two circles icon, pinned to the bottom of the drawer column), or press Ctrl+P, to enter DJ mode. A confirmation dialog appears; clicking "Yes" activates performance mode.
Layout
In DJ mode, the arrangement view splits into two side-by-side timelines: Deck A (left, blue) and Deck B (right, orange). Each has its own playhead, scroll position, and ruler. The Preview Drawer switches to a centered DJ control layout.
Vinyl A (spinning platter) — DJ Mixer (center, with embedded visuals preview) — Vinyl B (spinning platter) — DJ Control Panel (right side). The mixer is 1.6× wider than the vinyl spinners and contains a 16:9 visuals preview between the control columns.
Dual Deck System
Each deck is a fully independent song state — its own tracks, clock, CV, video, and visual graph. Deck A is the currently loaded project. Deck B loads via the LOAD button in the background, with video decoders deferred until playback starts to eliminate loading stutter.
LOAD A re-opens a project file as the main project. LOAD B loads a second .phonon file
in the background, so the current deck keeps playing without interruption. Video decoders warm up
when the deck starts playing, and Deck B runs on its own audio thread.
DJ Mixer
The center module provides full DJ mixing controls, all custom-drawn:
3-band EQ per deck (HI/MID/LOW mini knobs) — Volume faders (vertical, per deck) — Crossfader (horizontal, equal-power curve, A/B color gradient) — Play/Pause buttons (per deck) — SYNC (copies BPM from Deck A to Deck B) — LOAD buttons (per deck, opens file picker) — BPM display (per deck).
Audio & Video Crossfade
The crossfader controls both audio mixing and video blending simultaneously.
Audio uses an equal-power crossfader curve. Video crossfade uses VideoInNode.SetCrossfade
to GPU-blend between Deck A and Deck B video frames. When only one deck has video,
it displays that deck's video regardless of crossfader position.
Vinyl Scratching
Click and drag the vinyl platters to scratch. The system uses an offline pre-rendered audio buffer for instant, artifact-free scratching:
When a track is loaded, Phonon renders the entire song offline into a stereo buffer on a background thread. The buffer becomes available for scratching progressively as it renders.
During scratch, playback reads from that pre-rendered buffer at a variable rate set by the vinyl rotation speed. Forward rotation = forward playback (pitch up with speed), reverse = reverse playback. The vinyl position smoothly interpolates toward the target to eliminate clicks.
Video scrubbing uses a 90-frame circular scrub cache. Recently displayed frames are copied and stored by frame index. During scratch, cached frames are served instantly for backward/forward movement. If the cache misses, the last good frame is held rather than going black. Seek throttle is reduced to 100ms during scrub.
Performance Zones
A dedicated Performance Track sits at the bottom of the arrangement view. It holds Performance Zones — named, colored regions that mark sections of your song for DJ navigation.
Right-click on the performance lane → "Add Performance Zone" → enter a name in the dialog. Zones are created at the clicked position (snapped to grid) with a default duration of 4 bars and auto-rotating colors.
Right-click an existing zone for: Rename, Change Color (8 presets), Enable/Disable Loop (shown as dashed border), Delete.
Gold drag handles on left and right edges for resizing. Click body to select (gold outline) and drag to move. Minimum duration: 1 bar.
DJ Control Panel
Separate module to the right of the decks. Two columns (Deck A blue, Deck B orange) with grouped buttons:
PZ SYNC A→B / B→A — sync zone position between decks (bar-level matching with fallback). PZ LOOP (toggle, default ON) — loop within the active performance zone.
MUTE (toggle) — zero deck gain while active. AUTO MUTE — schedules a one-beat silence starting at the next beat boundary. Beat-quantized timing with sample-counted duration (immune to PZ loop resets).
PZ CUE NEXT — cue the next zone (blinks when pending). PZ NEXT BAR — transition at next bar boundary (blinks when pending). PZ NEXT NOW — immediate jump.
AUTO FADE — crossfader fades toward the target deck over remaining zone duration or 4 bars (blinks during fade). Cancel by touching crossfader or pressing again.
RAMP BPM — linear BPM ramp from current to root over 4 bars (sample-counted). ROOT BPM — instantly set deck BPM to root (region tempo override or project BPM). Cancels any ramp.
DJ Effects Chain
Each deck has an independent effects chain processed in the audio callback. The effects module sits to the right of the DJ control panel with 4 knobs per deck. The entire DJ drawer scrolls horizontally via vertical mouse wheel.
Source → 3-Band DJ EQ (kill EQ, 250/2500 Hz crossover, 0=kill, 0.5=unity, 1=+6dB) → LP/HP Sweep Filters (resonant biquad, exponential freq mapping, Q=1.2) → Grain Delay (beat-synced, 16 simultaneous Hann-windowed grains, feedback loop) → Plate Reverb (8 comb filters, 4 allpass diffusers, 12ms pre-delay, smoothed send) → Volume × Crossfader → Mute → Output.
DJ EQ: On the mixer. RBJ biquad with complementary mid extraction (mid = input − low − high). Sweep Filters: LP sweeps 20kHz→60Hz, HP sweeps 20Hz→16kHz. Auto-bypass when fully open. Grain Delay: Scales from quarter-note echoes (low) to 32nd-note granular wash (high) with pitch randomization and occasional octave shifts. 3-second capture buffer. Plate Reverb: Per-comb damping, stereo spread via offset buffer lengths, smoothed send amount with always-running tail (no pop on on/off). All knobs double-click to reset to default (LP=1, HP=0, Grain=0, Reverb=0, EQ=0.5).
DJ Info Bars
The top info bar splits into two deck panels in DJ mode, matching the normal position display style (Consolas monospace, rounded border shell, vertical dividers). Each panel shows: Deck letter (A blue, B orange) | BAR (bar.beat.sub) | BPM with base BPM in parentheses when synced to a different tempo (e.g. "125.0 (120)") | ZONE name | TIME (min:sec.tenths). Base BPM = region tempo override if set, otherwise project root BPM.
DJ Mode Notes
Disabled in DJ mode — use per-deck Play/Pause buttons or double-click the vinyl platters.
Click the DJ button, press Ctrl+P, or press Escape. The arrangement view restores to single-timeline mode, Deck B stops, and the drawer returns to normal tabbed layout.
13 Blocks
Blocks is Phonon's visual patching environment — a modular synthesizer canvas where you build instruments, effects, and signal processors from individual nodes connected by cables. Add a Blocks module via the top-level ⬡ Add Blocks item in the track right-click menu. The node library currently ships with 124 nodes across 13 categories (I/O, Source, CV Source, Modulator, Operator, Comparator, Converter, Effect, Filter, Gate, MIDI, Utility, SubBlocks).
Overview
Nodes are rounded boxes with input ports (left) and output ports (right). Cables are bezier curves between ports. Right-click the canvas to add nodes. Click+drag ports to create cables. Click+drag node headers to move them. Left-click drag empty background or middle-mouse drag anywhere to pan. Every Blocks module starts with a MIDI In node (gate/pitch/velocity/trigger outputs) and an Audio Out node (L/R inputs). These cannot be deleted.
Inline parameter sliders — drag horizontally to adjust values displayed on the node. Custom header colors — right-click → 🎨 Header Color with 12 preset colors or reset to category default. Custom labels — right-click → ✏ Set Label to add an italic annotation below the node name. Both persist with the project file.
SubBlocks
SubBlocks is a node that contains an entire nested patching canvas. Add via right-click → ⬡ SubBlocks. The node has 7 input and 7 output ports: Audio L/R, Gate, Pitch, Velocity, Trigger, CV In/Out. Inside the sub-canvas, an ⬡ Input bridge node provides incoming signals and an ⬡ Output bridge node collects outgoing signals. Double-click a SubBlocks node to open its canvas in a child window. SubBlocks can be nested recursively. Deep copy/paste via right-click menu duplicates the entire sub-graph including all internal nodes and cables.
Node Reference
124 nodes across 13 categories. Each category has its own menu submenu and a distinct header color on the canvas.
MIDI In — receives note events from the track. Outputs: Gate, Pitch (MIDI note number), Velocity, Trigger (1-sample pulse on note-on). Legato note stack with retrigger support.
Audio Out — final stereo output. Inputs: Left, Right.
CV In — reads a value from the Meadow CV bus system. Params: Bus (0–63).
Audio Bus In — reads audio from a shared audio bus. Tracks can route their output to buses 1–12; this node reads from them. One buffer latency. Outputs: Left, Right. Params: Bus (1–12).
SubBlock Input / Output — I/O ports for SubBlocks patches. 7 ports each side.
Visual Send — sends any signal to the Blocks→Visual bridge bus (64 channels). See Blocks→Visual Bridge.
Oscillator — anti-aliased oscillator with PolyBLEP. Continuous waveshape morphing (0=Saw, 1=Sine, 2=Triangle, 3=Pulse with variable pulse width). FM input for frequency modulation.
ADSR Osc — oscillator with built-in ADSR envelope. Accepts Gate, Pitch, Velocity directly from MIDI In. Stereo output.
Unison — multiple detuned oscillators mixed with stereo spread. Built-in ADSR envelope.
Noise — white noise generator.
Sample — WAV sample player with per-note triggering, pitch CV, and sample rate reduction.
Script — user-written Glyph code executing per-sample. 8 inputs, 8 outputs. Port names defined by the script. Double-click to open the code editor.
FM Operator — single sine-wave FM operator with configurable ratio and feedback. Chain several to build classic DX-style FM patches.
Karplus-Strong — plucked-string physical model. Short delay line + lowpass feedback. Trigger input excites the string; pitch input sets the delay length.
Waveguide — bidirectional delay-line physical model with configurable L/R reflection coefficients and damping. Blank slate for tuned tube/string sounds.
Tube — Waveguide with built-in breath noise + envelope. Three modes: Flute, Clarinet (negative reflection → square-wave timbre), Brass (tanh nonlinearity for embouchure).
LFO — low-frequency oscillator (Sine, Triangle, Saw, Square, S&H). Free or tempo-synced rate.
Constant — outputs a fixed value. Useful for setting frequencies, bias voltages, etc.
CV Trig→Pitch — outputs a fixed MIDI pitch when triggered by CV. Configurable gate duration.
Clock — generates trigger and gate pulses at a configurable rate (Hz). Adjustable pulse width.
Step Sequencer — step sequencer with configurable pattern.
CV Sequencer — CV-driven step sequencer.
Is Playing — outputs 1 when transport is playing, 0 when stopped. No inputs.
Beat — outputs trigger and gate pulses synced to musical divisions (whole, half, quarter, 8th, 16th, 32nd, 64th notes). Adjustable gate width. Syncs to the transport clock.
CV Noise — random CV signal generator. Speed controls how often a new random target is picked. Smooth controls interpolation between targets. Outputs −1 to +1.
Rand CV — outputs a random value in a configurable range on each trigger rising edge. Holds value until next trigger.
Rand Pitch — outputs a random MIDI pitch (integer) in a configurable note range on each trigger. Holds value until next trigger.
Rand Hz — outputs a random frequency (Hz) on each trigger. Logarithmic distribution for perceptually even spread across octaves. Configurable range (default 20–20000 Hz).
Chord Builder — builds 4-voice chords from a root note. 14 chord types (maj/min/7/9/sus2/sus4/dim/aug…) × 9 scales, or Direct chord-type selection. Inversions, Change trigger output for arpeggiation.
Euclidean — Euclidean rhythm generator. Distributes N pulses evenly across M steps. Params: Pulses, Steps, Rotation. Triggers fire on the active steps.
Turing Machine — 16-bit shift register after the Music Thing module. Length 2–16, Probability for bit flips. Outputs: Pitch (quantized), CV (0–1), Trigger, Gate. Preset defaults for a usable starting pattern.
Pattern Recorder — beat-synced CV capture and playback. Records up to 1.5M samples of incoming CV. Params: Rate, Reverse, One-Shot. Monitor-through when not recording.
Envelope — ADSR envelope generator. Gate input triggers Attack/Decay/Sustain; gate release triggers Release. Direct retrigger from NoteOn events.
Complex Envelope — multi-point envelope with configurable curve types. Gate and trigger inputs. Looping support.
Harmonic Quantizer — quantizes pitch to the current harmonic progression from the GlassEngine/Song Structure system.
Add — A + B. Subtract — A − B. Multiply — A × B (B defaults to 1). Divide — A / B (safe; returns 0 if B ≈ 0).
Min / Max — outputs smaller / larger of A and B.
Abs / Negate — absolute value / sign flip of input.
Clamp — constrains input to a Min/Max range.
Map Range — remaps input from one range to another. Params: In Min, In Max, Out Min, Out Max.
Math (Legacy) — dropdown-based operator node. Kept for backward compatibility with existing patches.
Trig: Sin, Cos, Tan, Asin, Acos, Atan2 — all measured in turns (0–1 = one full cycle) rather than radians, so they compose neatly with LFO / phase inputs.
Exp / Log — natural exponential / logarithm (guards x ≤ 0 → 1e-9).
Pow — A to the B power. Signed-negative-base handling for bipolar curves.
Sqrt — square root of |input|.
All comparator nodes output 1.0 for true, 0.0 for false. Logic inputs treat ≥ 0.5 as true.
Equal — A ≈ B (configurable tolerance). Not Equal — A ≉ B.
Greater — A > B. Less — A < B.
Greater/Eq — A ≥ B. Less/Eq — A ≤ B.
And — both true. Or — either true. Not — inverts.
XOR — one or the other, not both. XNOR — both same.
NAND — not both. NOR — neither.
Audio→Trig — fires a CV trigger pulse when audio amplitude crosses a threshold. Rising edge detection. Configurable gate duration (1–200ms).
Amp→CV — envelope follower. Converts audio amplitude to a 0–1 CV signal with separate attack/release smoothing. Gain parameter for scaling quiet signals.
Pitch→CV — maps MIDI pitch (0–127) to 0–1 CV. Configurable low/high note range for the mapping.
Uni→Bi — converts unipolar (0 to 1) to bipolar (−1 to +1). Formula: out = in × 2 − 1.
Bi→Uni — converts bipolar (−1 to +1) to unipolar (0 to 1). Formula: out = (in + 1) × 0.5.
CV→Hz — maps 0–1 CV to frequency using exponential/logarithmic scaling. Configurable range (default 20–20000 Hz). Equal CV distances = equal musical intervals.
Hz→Pitch — converts frequency in Hz to MIDI note number. Standard formula: 69 + 12 × log₂(hz / 440). Fractional output for microtonal precision.
Delay — audio delay line with time (up to 2s) and feedback controls.
Waveshaper — nonlinear waveshaping with multiple curve modes (Tanh, Fold, Clip, etc.).
Phaser — 4-stage all-pass filter chain with feedback. LFO sweeps center frequencies (200–4000 Hz). Stereo phase offset for width. Params: Rate, Depth, Feedback, Mix, Stereo.
Chorus — modulated delay line with sub-sample interpolation. Center delay (1–30ms) with LFO modulation. Stereo offset for width. Params: Rate, Depth, Mix, Delay ms, Stereo.
Ring Mod — multiplies audio by an internal oscillator for metallic/bell tones. CV-controllable frequency. Shape crossfades sine→square carrier. Params: Freq, Mix, Shape.
Flanger — short modulated delay (0.1–5ms) with feedback for comb filter sweeps. Negative feedback allowed for hollow sound. Stereo. Params: Rate, Depth, Feedback (−0.95 to +0.95), Mix, Delay ms, Stereo.
Grain Stretch — granular time-freeze effect. When Gate CV ≥ 0.5, captures audio and loops it with two overlapping grains. Mix input controls wet/dry. Params: Grain ms (10–200), Scatter (randomize grain position), Pitch (playback speed 0.25–4×).
Filter — resonant state-variable filter (Lowpass, Bandpass, Highpass). Stereo. L/Mono input mirrors to R if R is not connected. Cutoff and resonance inputs.
High Pass — dedicated high-pass filter.
Ladder — Moog-style 4-pole ladder filter with tanh saturation. Self-resonates at high Q.
Prism — SEM-style filter that morphs continuously Lowpass → Notch → Highpass via a Shape knob.
Formant — 3-band formant filter for vocal-tract simulation. Params: Q (1–40), Gender (−1 male → +1 female).
Comb — comb filter (feedback delay with pitched coloration). Frequency-tuned.
Allpass — all-pass filter for phase shifting without amplitude change. Useful for building reverbs and phasers from primitives.
Biquad — general-purpose RBJ biquad. Modes: Peak, Notch, LowShelf, HighShelf. Params: Freq (Hz), Q, Gain (for Peak/Shelf). Coefficient caching to avoid recompute on every sample.
CV Gate — passes signal through only when it exceeds a threshold. Modes: Zero (output 0 below threshold) or Hold (hold last above-threshold value).
If-Else — conditional signal routing. If Cond ≥ 0.5, outputs A; otherwise outputs B.
Prob Gate — probabilistic gate. Outputs the input gate with a configurable pass-through probability.
Trig Chance — randomly passes or blocks trigger pulses. On each rising edge, rolls against a Chance parameter (0–1). 1.0 = always pass, 0.0 = always block.
Gate Length — holds the gate open for a fixed duration after a trigger (ms).
Gate Delay — delays incoming gates by a configurable amount, in milliseconds or beats.
Swing — applies per-division swing timing to triggers. Auto-detects incoming interval; ±0.5 swing amount.
Ratchet — subdivides each incoming gate into N rapid subdivisions. Useful for trap hats and drill'n'bass patterns.
T Flip-Flop — toggles output state on each rising edge of input.
SR Flip-Flop — Set/Reset flip-flop. Reset-dominant (S+R simultaneous → R wins).
Counter — counts trigger rising edges. Max parameter wraps. Outputs: Count (current value), Overflow (trigger on wrap).
MIDI In — (also listed under I/O; lives in the MIDI menu for discoverability.) Gate/Pitch/Velocity/Trigger outputs from the track's MIDI input.
MIDI CC — receives a live MIDI CC value. Params: CC number, Smoothing (one-pole), Initial value. Outputs: Value (0–1), Bipolar (−1 to +1), Trigger (on value change). MIDI Learn: right-click → “🎚 Learn CC” and move a knob on your controller to bind. Amber outline while armed. Values arrive via LiveMidiDispatcher — zero-latency, no track-chain stamping.
CC → Bipolar — convenience wrapper: converts an incoming CC (0–127) directly to −1..+1 bipolar CV.
CC → Pitch — maps a CC to a MIDI pitch (with optional scale snap). Params: Min note, Max note, Snap.
CC → Hz — maps a CC to a frequency using exponential/logarithmic scaling. Params: Low Hz, High Hz.
VCA — voltage-controlled amplifier. Multiplies audio by a CV signal. Volume parameter.
Mixer — 4-channel stereo mixer with per-channel gain and pan, plus master gain.
Splitter — 1 input, 8 outputs (all identical passthrough).
Selector — 8 inputs + Select CV → 1 output. Crossfade or hard-cut between inputs.
Crossfader — A/B crossfade with Curve knob blending between Linear and Equal-Power crossfade shapes.
S+H — sample and hold. Samples the input value on the rising edge of the trigger signal. Output holds until next trigger.
Slew Limiter — limits how fast a signal can change. Single Rate parameter (seconds). Low rate = slow glide, high rate = nearly instant. Exponential smoothing.
Lag — like slew limiter but with separate Rise and Fall times. Fast rise + slow fall = percussive follower. Slow rise + fast fall = swell in, snap off.
Attenuverter — scale, invert, and offset a signal. Amount (−1 to +1): negative inverts, zero silences, positive passes. Offset added after scaling.
Quantize — snaps input values to a grid of N evenly-spaced steps.
SR Reducer — sample-rate reducer. Holds input value at a configurable output rate (Hz) — aliasing and grit below audio-rate.
Bit Crush — quantizes signal to 2^Bits levels over [−1, +1]. Fractional bit depths allowed for fine-grained grit.
Delta — outputs the per-sample change in input. First derivative, useful for edge detection and envelope analysis.
Integrator — leaky integrator with optional reset input. dt-scaled, so the time constant is sample-rate independent.
Peak — peak detector with VU-style decay. Reset input clears held peak.
RMS — windowed RMS (loudness) over a configurable window in milliseconds.
SubBlocks — nested patching canvas. 7 I/O ports each side. Orange header color. See SubBlocks above.
Right-click the Blocks canvas → ⬡ Full Patches to instantiate a complete starter graph atomically. 8 included presets: Plucked Strings (Karplus-Strong bell), DX Bass (FM Operator chain), Formant Pad (unison + formant filter), Acid Lead (ladder filter + envelope), Turing Sequence (generative CV pattern), Ratcheted Bass (gate-subdivision groove), Chord Progression (ChordBuilder + ADSR), Comb Drone (detuned comb filter harmony). Confirmation dialog before replacing an existing graph.
14 Glyph Scripting
Glyph is Phonon's built-in audio-rate scripting language. Write text code that executes at 48,000 samples per second inside the Blocks visual patching environment. Glyph scripts live inside Script nodes — add one via right-click → Source → Script, or choose a preset from the ⬡ Script Presets submenu. Double-click a Script node (or right-click → ⬡ Edit Script) to open the code editor. Press Ctrl+Enter to compile.
Overview
Glyph uses strict typing and mandatory semicolons for code clarity. All variables persist their values between audio samples — this is how oscillator phases accumulate and filter states are maintained. Variables reset on note-on events or when the script is recompiled.
Scripts have 8 input ports and 8 output ports. Port names are defined
by the script itself: writing in("Pitch") creates an input port called "Pitch" on the node.
Writing out("Left", sample) creates an output port called "Left". Unused ports remain
with default names and carry zero signal.
A Volume knob on every Script node attenuates all outputs (default 0.5) to prevent accidental clipping while developing.
Source code passes through four stages: Lexer (text → tokens) → Parser (tokens → AST, recursive descent) → Compiler (AST → bytecode with constant pooling and jump patching) → VM (stack-based execution with 256-element float stack, zero allocation per sample). The entire pipeline runs when you click Compile or press Ctrl+Enter. Errors display with line and column numbers.
Types & Variables
float — 32-bit floating point. The primary type for audio signals,
frequencies, gains, and most values. This is the workhorse of Glyph.
int — 32-bit integer. Use for counters, MIDI note numbers, array indices,
and bitwise operations.
bool — true/false. Use for gates, flags, and conditional logic.
Internally represented as float (1.0 = true, 0.0 = false).
buffer[N] — fixed-size float array of N elements.
Use for delay lines, wavetables, and sample storage. Declared with a size:
buffer[2048] delay;. See Buffers.
All variables must be declared with a type. Variables persist their values between samples — this is essential for audio DSP where you need state (oscillator phases, filter memories, counters).
float phase = 0.0; // oscillator phase int counter = 0; // sample counter bool triggered = false; // flag buffer[4096] delayLine; // 4096-sample delay buffer
Variables declared without an initializer start at zero. Variables reset to zero on note-on events and when the script is recompiled, but buffer contents are preserved across resets (delay lines keep their audio data).
I/O Ports
Use in("name") to read a value from an input port. The string becomes the port label
on the node. Each unique port name creates one input port, up to 8 total.
float pitch = in("Pitch"); // MIDI note number
float gate = in("Gate"); // 0 or 1
float velocity = in("Velocity"); // 0 to 1
float cutoff = in("Cutoff"); // custom modulation input
If nothing is connected to a port, it reads the port's default value (typically 0).
Use out("name", value) to write a value to an output port. The string becomes the port label.
Each unique port name creates one output port, up to 8 total.
This is a statement, not an expression — it must end with a semicolon and cannot
be used inside an expression.
out("Left", sample); // stereo audio left
out("Right", sample); // stereo audio right
out("Trigger", trigger); // CV trigger pulse
out("Envelope", envValue); // modulation output
All outputs are clamped to ±10 and multiplied by the node's Volume knob before reaching the connected cable.
Operators
+ add, - subtract, * multiply, / divide,
% modulo. Division by zero returns 0 (no crashes in the audio thread).
== equal, != not equal, < less than,
> greater than, <= less or equal, >= greater or equal.
All return 1.0 (true) or 0.0 (false).
&& AND, || OR, ! NOT.
Values above 0.5 are considered true.
& AND, | OR, ^ XOR, ~ NOT,
<< shift left, >> shift right.
Operands are truncated to int before the operation.
= assign, += add-assign, -= subtract-assign,
*= multiply-assign, /= divide-assign.
phase += freq * dt; // equivalent to: phase = phase + freq * dt;
condition ? valueIfTrue : valueIfFalse
float vol = gate > 0.5 ? 1.0 : 0.0;
(float)x, (int)x, (bool)x.
Float-to-int truncates. Bool clamps to 0 or 1.
int index = (int)phase; // truncate to integer float normalized = (float)count; // int to float
Control Flow
Standard if/else with braces required. Supports else if chaining.
if (gate > 0.5) {
env += (1.0 - env) * dt * 10.0;
} else {
env -= env * dt * 5.0;
}
if (mode == 0) {
// sine
} else if (mode == 1) {
// saw
} else {
// pulse
}
Use for iterating over buffers or running fixed-count operations. A safety limit of 4096 iterations per sample prevents infinite loops from locking the audio thread. If your loop exceeds this, execution silently stops for that sample.
int i = 0;
while (i < 64) {
delayLine[i] = delayLine[i] * 0.99;
i += 1;
}
Performance note: every instruction inside a while loop runs 48,000 times per second per iteration. A loop over 1024 samples means ~49 million operations per second for that loop alone. Keep loop bodies lean.
Built-in Functions
sin(x) cos(x) tan(x) atan2(y, x)
Arguments are in radians. For a full cycle sine oscillator:
sin(phase * 6.283185) where phase goes 0→1.
abs(x) absolute value,
floor(x) round down,
ceil(x) round up,
round(x) round to nearest.
min(a, b) max(a, b) clamp(x, lo, hi)
float safe = clamp(value, -1.0, 1.0); // prevent clipping float louder = max(left, right); // peak of stereo pair
pow(x, y) x raised to power y,
sqrt(x) square root (clamped to ≥0),
log(x) natural logarithm (returns −100 for ≤0),
exp(x) e^x (clamped to prevent overflow).
lerp(a, b, t) — linear interpolation from a to b. When t=0 returns a, t=1 returns b.
Essential for crossfading, parameter smoothing, and mixing.
smoothstep(lo, hi, x) — smooth Hermite interpolation. Returns 0 when x≤lo,
1 when x≥hi, and a smooth S-curve between. Useful for soft thresholds and transitions.
mtof(note) — MIDI note number to frequency in Hz. Middle C (note 60) = 261.6 Hz.
A4 (note 69) = 440 Hz. Supports fractional notes for microtuning.
ftom(freq) — frequency in Hz to MIDI note number. The inverse of mtof.
tanh(x) — hyperbolic tangent. The workhorse of soft clipping and saturation.
Gently compresses values toward ±1. Drive into it for warm distortion:
tanh(signal * 3.0).
wrap(x, lo, hi) — wraps value into range (like modulo, but works cleanly with floats).
Essential for oscillator phases: wrap(phase, 0.0, 1.0).
fold(x, lo, hi) — folds value at boundaries (bounces back instead of wrapping).
Creates triangle-like shapes from ramp signals and interesting waveshaping effects.
rand() — white noise sample, uniformly distributed from −1 to +1.
Returns a new random value every sample.
rand_range(a, b) — random float uniformly distributed between a and b.
Useful for randomized timing, pitch variation, and generative patterns.
Special Variables
These variables are injected by the runtime before each sample executes. They cannot be assigned to.
dt — time per sample in seconds (1/sampleRate). At 48kHz, dt ≈ 0.0000208.
This is the fundamental unit of time in Glyph. Multiply frequency by dt
to get phase increment: phase += freq * dt;
sr — sample rate in Hz (typically 48000). Use for calculating buffer sizes
or converting between seconds and samples.
beat — current beat position from the transport clock.
bpm — current tempo in beats per minute.
note — last received MIDI note number (0–127). Persists until the next note-on.
velocity — last received MIDI velocity (0–1). Persists until the next note-on.
Buffers
Buffers are fixed-size float arrays. Declare with a size in brackets:
buffer[4096] delay; // 4096 samples ≈ 85ms at 48kHz buffer[48000] longDelay; // 1 second at 48kHz
Buffer contents are preserved across variable resets (note-on, recompile).
This means delay lines keep their audio data between notes.
Use length(buf) to get the buffer size.
Use array syntax to read and write:
// Write to buffer delay[writePos] = inputSample; // Read from buffer float delayed = delay[readPos]; // Index wrapping is automatic — negative indices and // indices beyond the buffer size wrap around. // delay[-1] reads the last element. // delay[length(delay) + 5] wraps to index 5.
buffer[24000] delay; // 500ms delay at 48kHz
float input = in("Audio");
float feedback = in("Feedback");
float time = in("Time");
// Calculate delay in samples
int delaySamples = (int)(time * sr);
// Read delayed signal (auto-wrapping)
float delayed = delay[writeIdx - delaySamples];
// Write input + feedback
delay[writeIdx] = input + delayed * feedback;
writeIdx += 1;
if (writeIdx >= length(delay)) {
writeIdx = 0;
}
out("Left", input + delayed * 0.5);
out("Right", input + delayed * 0.5);
Examples
The simplest possible instrument. Wire Gate and Pitch from MIDI In.
float pitch = in("Pitch");
float gate = in("Gate");
float freq = mtof(pitch);
phase += freq * dt;
if (phase >= 1.0) {
phase -= 1.0;
}
float sample = sin(phase * 6.283185) * gate;
out("Left", sample);
out("Right", sample);
Raw saw wave with a simple attack/release envelope and velocity sensitivity.
float pitch = in("Pitch");
float gate = in("Gate");
float vel = in("Velocity");
float freq = mtof(pitch);
phase += freq * dt;
if (phase >= 1.0) {
phase -= 1.0;
}
float saw = phase * 2.0 - 1.0;
// Smooth envelope
if (gate > 0.5) {
env += (1.0 - env) * dt * 20.0;
} else {
env -= env * dt * 5.0;
}
if (env < 0.0001) { env = 0.0; }
float sample = saw * env * vel;
out("Left", sample);
out("Right", sample);
Pass audio through and apply adjustable distortion. Tanh gives warm saturation.
float inputL = in("Left");
float inputR = in("Right");
float drive = in("Drive");
// Default drive if nothing connected
if (drive < 0.01) { drive = 1.0; }
// Scale drive: 1 = clean, 10 = heavy distortion
float scale = 1.0 + drive * 9.0;
out("Left", tanh(inputL * scale));
out("Right", tanh(inputR * scale));
Passes gate signals through with a random probability. Wire between MIDI In and a synth for stochastic rhythms. Outputs a trigger on accepted gates.
float gateIn = in("Gate");
float pitchIn = in("Pitch");
float prob = in("Probability");
if (prob < 0.01) { prob = 0.5; }
// Detect rising edge
float trigger = 0.0;
if (gateIn > 0.5 && prevGate < 0.5) {
// Roll the dice
if (rand_range(0.0, 1.0) < prob) {
active = 1.0;
trigger = 1.0;
} else {
active = 0.0;
}
}
if (gateIn < 0.5) {
active = 0.0;
}
prevGate = gateIn;
out("Gate", gateIn * active);
out("Pitch", pitchIn);
out("Trigger", trigger);
Script Presets
Right-click the Blocks canvas → ⬡ Script Presets to add pre-written Script nodes. Each spawns with the code loaded and the custom label set. Open the script editor to study the code and modify it — presets are designed as both useful instruments and teaching examples.
[script] Raindrops — self-generating ambient texture. Random pitched drops from a pentatonic scale with fast exponential decay, random stereo pan, and variable density. No input needed — creates sound on its own. Outputs stereo audio plus CV trigger and envelope signals for driving other modules.
[script] Soft Pad — warm detuned stereo pad from three sine oscillators with ±0.3% detune and smooth attack/release envelope. Wire Gate, Pitch, Velocity from MIDI In.
[script] Acid Bass — squelchy 303-style monosynth. Saw oscillator through a resonant one-pole filter with envelope-driven cutoff sweep. External Cutoff and Resonance inputs for modulation.
[script] Bit Crusher — lo-fi audio effect. Stereo pass-through with adjustable bit depth reduction and sample rate decimation. Inputs for Bits (1–16) and Rate.
[script] Ring Mod — ring modulator effect. Multiplies stereo input by a sine carrier oscillator. Adjustable carrier frequency and dry/wet mix.
Glyph supports single-line comments (// comment) and multi-line comments
(/* comment */). Preset scripts are heavily commented — read them
to learn patterns for oscillators, envelopes, filters, effects, and generative algorithms.
15 GlyphVis Shaders
GlyphVis is Phonon's visual shader scripting language — a companion to Glyph (audio scripting) that runs on the GPU. Write fragment shaders using familiar Glyph-style syntax and they render in real-time inside the Visual Graph. GlyphVis scripts can react to audio, read CV buses, receive signals directly from Blocks patches, and be composited with video through the visual node graph's blend and effect nodes.
Overview
Add a GlyphVis Script node via right-click → Generator in the Visual Graph Editor. Double-click the node (or right-click → ◆ Edit Script) to open the shader editor. Write your visual code, press Ctrl+Enter to compile. The script is transpiled from Glyph syntax to GLSL and compiled as a GPU fragment shader. It renders at full frame rate into the visual graph's texture pipeline.
GlyphVis nodes have a texture input (for compositing with upstream nodes), a texture output (for downstream effects), and two float inputs (Audio and CV) for receiving signals from the audio engine. Script presets are available via right-click → ◆ Script Presets.
Every GlyphVis script has three pre-declared variables:
uv (vec2, pixel coordinates 0→1),
color (vec3, output RGB), and
alpha (float, output opacity).
The shader wraps your code inside void main() and assembles the final output as
fragColor = vec4(color, alpha). You just write the math that fills color.
GlyphVis scripts compile to native GLSL and run on the GPU at full speed — there is no interpreter overhead. The transpiler adds helper functions (noise, fbm, hsv2rgb, etc.) to the shader header automatically. Disconnected GlyphVis nodes are automatically skipped during rendering — only nodes in the dependency chain leading to the Screen node are processed.
Syntax & Types
GlyphVis uses native GLSL types directly — no translation needed:
float, int, bool,
vec2, vec3, vec4.
Swizzling works natively: color.rg, p.xy, v.xyzw.
Constructor functions work: vec2(0.5, 0.3), vec3(1.0).
Same strict syntax as audio Glyph — semicolons required, braces for blocks.
Comments use // single-line and /* */ multi-line.
All GLSL operators work natively: arithmetic (+ - * / %),
comparison (== != < > <= >=),
logical (&& || !), ternary (? :).
GLSL vector operations work on component types: vec3(1,0,0) * 0.5,
p * scale, color += vec3(0.1).
GlyphVis transpiles your code to GLSL and injects helper functions into the shader header. If you use any of these names as variable names, the shader will silently fail to compile (black screen, no error in the script editor). Avoid these as variable names:
GLSL ES reserved words:
active, attribute, buffer, centroid,
coherent, common, filter, flat,
image, input, output, partition,
patch, precise, resource, restrict,
sample, shared, smooth, subroutine,
varying, volatile — and many others.
If your shader is black, a reserved variable name is the first thing to check.
GlyphVis helper functions (injected by the transpiler — don't shadow these with variables):
audio, bass, mids, treble,
audio_in, cv_in,
noise, fbm, rand,
hsv2rgb, rgb2hsv.
Pre-declared in main():
uv, color, alpha — these are already declared.
Don't redeclare them with float or vec3.
Safe practice: Use descriptive variable names like cellActive instead of
active, audioLevel instead of audio,
noiseVal instead of noise.
Audio Reactivity
Every GlyphVis shader has access to the audio analyzer's output:
bass() — low frequency energy (kick drums, sub bass). Returns a small float —
multiply by 20–50 for visible effect.
mids() — midrange energy (vocals, synths, melody).
treble() — high frequency energy (hi-hats, cymbals, sibilance).
audio(index) — raw 256-bin FFT spectrum. Index 0 = deepest bass, 255 = highest treble.
// Make a circle pulse with the kick drum float kick = bass() * 30.0; float d = length(uv - 0.5); float ring = smoothstep(0.3 + kick * 0.05, 0.28 + kick * 0.05, d); color = vec3(ring);
GlyphVis nodes have two float input ports: Audio and CV. Wire source nodes (Audio Bus, CV Bus, Blocks In) to these ports, then read them in the script:
audio_in() — reads the Audio float input port.
cv_in() — reads the CV float input port.
// Wire an Audio Bus (bus 0 = bass) to the Audio port float kick = audio_in() * 30.0; // Wire a CV Bus (LFO) to the CV port float lfo = cv_in() * 5.0; // Use both to drive visuals color = hsv2rgb(vec3(lfo * 0.1 + time, 0.8, kick));
Blocks→Visual Bridge
A dedicated 64-channel bridge bus connects the Blocks audio patching system directly to the Visual Graph. Any signal in a Blocks patch — an oscillator's output, an envelope's shape, an LFO's value, a Glyph script's custom modulation — can be sent to the visual system.
The bus is thread-safe: the audio thread writes per-sample values at 48kHz, the render thread reads smoothed per-frame values at 60fps. One-pole smoothing prevents jitter.
In the Blocks editor, add a Visual Send node (Utility category). Wire any signal to its input and set the bus number (0–63). The signal passes through to the output so Visual Send can be inserted mid-chain without breaking the audio path.
Blocks patch:
Oscillator → Filter → Visual Send (Bus 0) → Audio Out
↓
(Bus 0 carries the filtered signal
to the visual system)
In the Visual Graph, add a Blocks In node (Source category). Set it to the same bus number. Wire its float output to a GlyphVis node's Audio or CV input. The signal from your Blocks patch is now driving your GPU shader.
Visual Graph:
Blocks In (Bus 0) → GlyphVis "Audio" input
↓
audio_in() in the shader reads
the filtered oscillator signal
Send an envelope follower on bus 0 to make visuals pulse with the kick. Send an LFO on bus 1 to smoothly rotate a kaleidoscope effect. Send a step sequencer output on bus 2 to drive color changes per beat. Send the raw oscillator output on bus 3 to visualize the actual waveform. With 64 buses, you can make the interaction between audio and visuals as intricate as the music itself.
Built-in Functions
All standard GLSL functions work natively — no transpilation needed:
sin, cos, tan, asin, acos, atan,
abs, floor, ceil, round, fract, mod,
min, max, clamp, mix, step, smoothstep,
pow, sqrt, log, exp,
length, distance, dot, cross, normalize,
reflect, refract, sign, radians, degrees.
The transpiler automatically includes these helper functions in every shader:
noise(vec2 p) — 2D value noise. Returns 0–1. Use for organic textures.
fbm(vec2 p) — fractal Brownian motion (5 octaves of noise). Richer, more detailed noise.
hsv2rgb(vec3 c) — convert HSV (hue 0–1, saturation 0–1, value 0–1) to RGB.
Essential for colorful procedural visuals.
rgb2hsv(vec3 c) — convert RGB back to HSV for color manipulation.
rand(vec2 co) — pseudo-random hash from 2D coordinates. Deterministic per pixel.
audio(int index) — raw FFT bin (0–255).
bass(), mids(), treble() — frequency band energy.
audio_in(), cv_in() — float input port values.
Parameters
Use param("Name", min, max, default) to create inline sliders on the GlyphVis node.
The function returns the current slider value. Each unique param name creates one slider.
float speed = param("Speed", 0.1, 5.0, 1.0);
float glow = param("Glow", 0.0, 2.0, 0.8);
float count = param("Ring Count", 2.0, 20.0, 8.0);
Params compile to GLSL uniforms and are set per-frame. They persist with the project. Slider values are preserved across recompiles if the param name matches.
Source Nodes
Feeds video frames into the visual graph as a texture. Receives frames from the video track or a loaded video file.
Reads audio analysis data and outputs it as a float. Bus 0 = bass, 1 = mids, 2 = highs, 3 = RMS (overall loudness), 4–63 = raw spectrum bins. Params: Bus (0–63), Gain (0.1–50), Smooth (0.01–1.0).
Reads a CV bus value from the audio engine's CV system (LFOs, envelopes, sequencers). The per-sample CV values are averaged to a single per-frame float. Params: Bus (0–63), Gain (0.1–10), Offset (−1 to +1), Smooth (0.01–1.0).
Reads from the Blocks→Visual bridge bus. Receives signals sent by Visual Send nodes in Blocks patches. 64 independent channels. Params: Bus (0–63), Gain (0.1–50).
Utility Nodes
One texture input, 8 texture outputs (all identical). Fan out a single visual source to multiple downstream nodes.
8 texture inputs + Select float input → 1 texture output. CV selects which input passes through. Crossfade or hard-cut mode. 0.0 = Input 1, 1.0 = Input 8.
CV Nodes
CV nodes output float values that can be wired to any float input on other visual nodes (shader uniforms, selector CVs, etc.). They enable animation and modulation without audio input.
Low-frequency oscillator. Outputs a cycling float value. Waveforms: Sine, Triangle, Saw, Square, Sample & Hold. Beat sync toggle uses the transport BPM (rate becomes beats-per-cycle). Params: Rate (0.01–20), Amplitude (0–1), Offset (−1 to +1), Wave (0–4), Sync (Free/Beat).
Random float output with smoothing. Three modes: White (stepped random at speed rate), Smooth (interpolated random walk), Drift (multi-frequency sinusoidal wander for organic slow movement). Params: Speed (0.01–50), Smooth (0–0.999), Amplitude (0–1), Offset (−1 to +1), Mode (White/Smooth/Drift).
Examples
// Simplest possible GlyphVis script color = vec3(uv.x, uv.y, 0.5); alpha = 1.0;
float radius = param("Radius", 0.1, 0.5, 0.3);
vec2 center = vec2(0.5 + sin(time) * 0.2, 0.5 + cos(time * 0.7) * 0.2);
float d = distance(uv, center);
float circle = smoothstep(radius, radius - 0.01, d);
color = hsv2rgb(vec3(time * 0.1, 0.8, circle));
alpha = 1.0;
// Vertical bars driven by the FFT spectrum
float barCount = param("Bars", 8.0, 64.0, 32.0);
float barIdx = floor(uv.x * barCount);
int specIdx = int(barIdx * 256.0 / barCount);
float amp = audio(specIdx) * 30.0;
float barHeight = clamp(amp, 0.0, 1.0);
float bar = step(1.0 - barHeight, uv.y);
float hue = barIdx / barCount;
color = hsv2rgb(vec3(hue + time * 0.05, 0.8, bar * 0.9));
alpha = 1.0;
// Sample the upstream texture and apply a color effect
// Wire another node's output to this node's texture input
float amount = param("Warp", 0.0, 0.1, 0.02);
vec2 warpedUV = uv + vec2(noise(uv * 5.0 + time), noise(uv * 5.0 + time + 100.0)) * amount;
vec3 source = tex(0, warpedUV).rgb;
color = mix(source, source.gbr, 0.3); // subtle color shift
alpha = 1.0;
// Wire a Blocks In node (reading an envelope on bus 0) to Audio input float envelope = audio_in() * 20.0; vec2 p = uv - 0.5; float d = length(p); float glow = exp(-d * (3.0 + envelope * 2.0)); color = hsv2rgb(vec3(time * 0.1, 0.6, glow * (0.5 + envelope))); alpha = 1.0;
Visual Presets
Right-click the Visual Graph canvas → ◆ Script Presets to add pre-written GlyphVis shaders. Each spawns a compiled GlyphVisNode with inline param sliders. Open the script editor to study the code and customize.
[script] Confetti — procedural falling rectangular particles with per-particle hue, flutter rotation, and size variation. Params: Density, Speed, Flutter, Size.
[script] Audio Rings — concentric rings where each ring maps to a frequency band. Inner rings = bass, outer = treble. Audio drives radius wobble and brightness. Params: Reactivity (1–100), Rings, Thickness, Hue Shift.
[script] Neon Grid — retro synthwave perspective grid scrolling toward camera. Magenta grid lines, cyan audio-reactive horizon glow. The iconic Phonon visual. Params: Scroll speed, Glow, Line Width.
[script] Liquid Warp — organic flowing color field from layered fbm noise cross-modulating itself. Params: Complexity, Speed, Saturation, Contrast.
[script] Star Field — parallax star layers with twinkle and depth. Multiple scroll speeds create the illusion of flying through space. Params: Speed, Density, Brightness, Layers.
[script] Pulse Tunnel — demonstrates the audio_in() and cv_in() bridge. The LFO (via CV port) physically rotates the tunnel and morphs it between circular and polygonal. Bass (via Audio port) drives ring intensity. Includes full setup instructions in the code comments. Params: Depth, Color Speed, Audio Scale, CV Amount.
uv — pixel coordinates, 0→1 in both axes.
time — elapsed time in seconds (maps to uTime uniform).
beat — current beat position from the transport.
bpm — current tempo.
resolution — viewport size in pixels (vec2). Use for aspect correction:
vec2 p = (uv - 0.5) * vec2(resolution.x / resolution.y, 1.0).
mouse — mouse position (vec2, 0–1).
16 GlyphSDF 3D Shapes
GlyphSDF is Phonon's user-scriptable 3D generator: you write one GLSL distance function, and the node wraps it in the house raymarcher — camera, tumble, lighting, four CV-modulatable knobs, a violet Warp input for 3D Transformer chains, and a gold Shape output that drops your scripted geometry straight into Blend 3D, Cloner, Shatter, Shape Sequencer, and every presentation renderer (Studio, Glass, Museum, Cosmos, …). This section is the complete reference for the scripting contract.
The Contract
A GlyphSDF script must define exactly one entry point:
float sdf(vec3 p)
p is a point in the shape's local space. The return value is the
signed distance from p to your surface: negative inside,
positive outside, zero on the surface. Helper functions, global variables, and
const globals are all allowed.
That's the whole interface. Everything else — marching the rays, shading, spinning, zooming, compositing — is supplied by the node.
Design your shape centered on the origin at roughly unit scale (a bounding
radius of about 0.5–0.9 reads best). The preview camera sits at z = -2.5;
presentation renderers place their floors at about y = -1.3 and frame a subject
of that size. The Zoom knob rescales your shape without touching the script
(space is divided by Zoom and the returned distances are corrected automatically), so favor
readable numbers over exact framing.
The Environment Your Script Sees
These are in scope inside sdf and any helper:
| Name | Type | Meaning |
|---|---|---|
uTime | float | Seconds since playback started. The animation clock. |
uBass | float | Low-band energy follower, ~0–1. |
uMid | float | Mid-band energy follower, ~0–1. |
uHigh | float | High-band energy follower, ~0–1. |
uBeat | float | Beat impulse: spikes on detected beats, decays fast. |
uAudioTex | sampler2D | The shared 512×2 audio texture (see below). |
pU1 … pU4 | float | The node's P1–P4 sliders, 0–1. Each has a CV input port, so any LFO/envelope/probe in the graph can drive them. |
The audio texture is 512×2, single channel (.r):
Spectrum row: texture(uAudioTex, vec2(bin, 0.25)).r —
bin in 0–1 runs from bass (0) to treble (1). Values are FFT magnitudes;
multiply up and clamp for visible effect.
Waveform row: texture(uAudioTex, vec2(phase, 0.75)).r —
the raw time-domain window.
The Spectral Urchin preset shows the idiomatic pattern: derive bin
from a direction or position, so different parts of the shape ride different frequencies.
P1–P4 — yours. They arrive as pU1–pU4 and mean
whatever your script says they mean. Comment the meanings at the top of the script —
future-you will thank you.
Hue — house shading tint. Preview only — when your shape is consumed through the Shape output, the consumer does the shading and Hue is ignored.
Zoom — rescales the shape (distance-corrected, always safe).
Spin — two-axis tumble applied outside your function. Your
sdf always sees unrotated local space — don't add your own tumble unless you
want both.
Step — march step damping, 0.3–1.0. The safety valve for imperfect distance fields — see Honest Distances.
Zoom, Spin, and Step travel with the shape through the gold Shape output; P1–P4 stay live and CV-modulatable inside any consumer, no matter how deeply the shape is nested.
Language Rules
Scripts are GLSL ES 3.00 fragments (ANGLE-translated on Windows). The usual GLSL toolbox
applies: length, dot, cross, mix,
clamp, smoothstep, min/max,
abs, mod, floor/fract,
sin/cos/atan, pow/exp,
swizzles, vec2/3/4, mat2/3/4, constant-bound for
loops with break.
Never name a function or global any of these:
init, map, main — the node
generates functions with these names around your script.
pal, domainWarp, domainDamp —
house functions that share the shader with your script in preview mode.
GLSL reserved words that are easy to reach for accidentally:
layout, sample, filter, input,
output, union, buffer, half.
Everything else is fair game — and thanks to namespacing (see Graph Integration) you don't have to worry about other scripts' names, only these.
Declare helpers and globals in the ordinary way:
float wob(vec3 p) { ... } // helper function ✓
const float TAU = 6.28318; // const global ✓
vec3 gOffset = vec3(0.0); // mutable global ✓ (persists per-pixel only)
Stick to float, int, bool, vec2/3/4,
and mat2/3/4 for top-level declarations. Global arrays,
structs, and #define macros are not
namespaced when the shape is composed into a shared shader — they work in a lone node but
can collide if two scripts using the same names meet inside one Blend. If you need them,
give them names unlikely to collide.
Keep loop bounds constant (for (int i = 0; i < 6; i++)
with an early break is fine; a loop bound computed from a uniform is not).
Avoid mutable arrays indexed by a variable — ANGLE compiles these to indexable temp registers, roughly 10× slower. Unroll or restructure.
Remember your sdf runs per pixel per march step — up to
~100 times per pixel. A texture() fetch or sin chain you'd never
notice once adds up fast. Hoist what you can into constants.
Distance-Field Craft
length(p) - r // sphere length(max(abs(p) - b, 0.0)) // box (b = half-extents) length(vec2(length(p.xz) - R, p.y)) - r // torus (abs(p.x) + abs(p.y) + abs(p.z) - s) * 0.57735 // octahedron p.y - h // floor plane length(p - clamp(p, a, b)) - r // capsule from a to b
min(a, b) // union max(a, b) // intersection max(a, -b) // subtraction: carve b out of a abs(d) - t // onion: turn a solid into a shell of thickness t d - r // rounding: inflate with soft corners
Smooth union (the "weld" — the single most useful operator in the language):
float weld(float a, float b, float k) {
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
return mix(b, a, h) - k * h * (1.0 - h);
}
k is the gooeyness. See the Metaball Trio preset.
p = abs(p); // mirror symmetry across all axes q = mod(p.xz + s * 0.5, s) - s * 0.5; // infinite repetition, cell size s vec2 cell = floor((p.xz + s * 0.5) / s); // which cell (hash it for variety) p.xz = mat2(c, -s, s, c) * p.xz; // rotate around Y
Per-cell hash for varying repeated elements:
float h = fract(sin(dot(cell, vec2(127.1, 311.7))) * 43758.5453);
See Endless Columns for repetition + hashing, Nested Shells for onioning and cutaways.
Anything can move: positions by uTime, radii by uBass, weld
factors by pU1. The house pattern for audio-reactivity:
uBass/uMid/uHigh for smooth
breathing and swelling.
uBeat for accents (add it to a size or displacement).
uAudioTex when different regions of the shape should follow
different frequencies.
Honest Distances (or: Why Your Shape Has Holes)
The raymarcher trusts your return value: it steps forward exactly that far. If you ever return a distance larger than the true distance, rays overshoot thin features and you get holes, flicker, or a shape that comes apart while rotating.
Displacement (d += sin(...)), non-uniform scaling, twisting or bending
space by hand, and domain repetition near cell borders.
1. Scale the return: return d * 0.5; — halves the step size
for just this shape. The presets do this wherever they displace
(* 0.45, * 0.6, …).
2. Lower the Step knob — same effect, dialable live without editing, and it travels with the shape into consumers.
Rule of thumb: heavy displacement wants * 0.4–0.6; mild
rounding and welding needs nothing.
Playing with the Rest of the Graph
3D Transformer chains (Twist, Fractalize, Mirror XYZ, Stereo 4D, …) cable into the
Warp input and bend space before your function sees it —
p arrives pre-warped, in world orientation, before Spin and Zoom are applied.
Your script needs no changes to be twistable, foldable, or repeated.
Cabling Shape into a consumer (Blend 3D, Cloner, Shatter, Sequencer, or any presentation renderer) splices your script into that consumer's shader at compile time:
Your P1–P4 stay live and CV-driven inside the consumer.
Hue is ignored (the consumer shades); Zoom/Spin/Step still apply.
When only the Shape output is cabled, the GlyphSDF node's own preview pass is skipped entirely — a scripted shape feeding a Blend costs nothing extra.
Nesting depth (blends of blends of …) is capped at 4.
At composition time, every top-level function and global your script declares is renamed
into a slot namespace via #define/#undef pairs. Two GlyphSDF
nodes can both define weld and ball and meet in one Blend without
conflict. This is why the reserved-name and top-level-declaration rules exist: the renamer
recognizes ordinary function and scalar/vector/matrix declarations, and leaves exotic
ones alone.
Add a GlyphSDF from the 3D category — the plain node, or one of the
[sdf] preset entries with a teaching script preloaded.
Edit via right-click → Edit SDF Script. Apply
(or Ctrl+Enter) performs a structural check — the source must contain
float sdf(vec3 and have balanced braces — then hands the script to the node,
which recompiles itself and every consumer downstream of its Shape output.
Script edits are undoable, and the script is saved inside the project (and travels with copied/pasted nodes).
| Symptom | Cause | Fix |
|---|---|---|
| Node renders black | GLSL compile error | Details are in the debug log ([VisualGraph] … shader log). Usual suspects: missing semicolon, reserved name, non-constant loop bound. |
| Holes / flicker / crumbling edges | Overstated distances | Scale the return down, or lower Step. |
| Shape clips or vanishes in renderers | Too large for the stage | Keep the shape inside ~1.1 radius of the origin; use the node's Zoom rather than building it huge. |
| Runs hot | Per-step cost | Constant loop bounds, no variable array indexing, fewer texture() calls per step. |
| Works alone, breaks inside a Blend | Colliding un-namespaced construct | Rename global arrays / structs / macros to something unique. |
The Presets, as a Syllabus
Each [sdf] preset in the add-node menu teaches one technique:
| Preset | Teaches |
|---|---|
| Pulsing Gem | The minimal script: one primitive, rounding, a uBeat accent. Start here. |
| Spectral Urchin | Sampling uAudioTex so geometry maps the spectrum spatially. |
| Metaball Trio | Smooth-min welding, orbital motion, per-band followers. |
| Endless Columns | Domain repetition with mod(), per-cell hashing. |
| Nested Shells | Onioning with abs(), boolean subtraction cutaways. |
A good learning path is to open each, twist P1–P4 while reading the comments, then break something on purpose and watch what happens.
A Complete Worked Example
Everything above in ~20 lines — an audio-reactive gear ring with a knob-driven tooth count feel, safe stepping, and a beat accent:
// GEAR RING — P1 = tooth depth, P2 = ring thickness, P3 = spin rate.
const float TAU = 6.28318;
float sdf(vec3 p) {
// rotate the ring with P3 (this is *inside* the shape's own space,
// independent of the node's Spin tumble)
float a = uTime * (0.2 + pU3 * 1.5);
float c = cos(a), s = sin(a);
p.xz = mat2(c, -s, s, c) * p.xz;
// torus body, breathing with the bass
float R = 0.62 + uBass * 0.08;
vec2 q = vec2(length(p.xz) - R, p.y);
float d = length(q) - (0.10 + pU2 * 0.10);
// teeth: displace by the angle around the ring
float ang = atan(p.z, p.x);
d += sin(ang * 16.0) * (0.02 + pU1 * 0.04) * (1.0 + uBeat * 0.8);
// displaced field → step gently
return d * 0.6;
}
Cable a Twist 3D into Warp, its Shape output into a Studio Render, an LFO into P1, and a Light node into Studio's Light A — nothing in the script changes, and all of it composes.
17 Project
Save / Load
Projects are saved as .phonon files containing the full hierarchy,
all module states, arrangement regions, BPM, performance zones, visual graph data,
and global settings. Additional data is stored in sidecar files:
| File | Contents |
|---|---|
MySong.phonon | Full project state — hierarchy, modules, regions, automation lanes, BPM, zones |
MySong.phonon.studer | Tuber console channel strip settings |
MySong.phonon.midi | MIDI parameter bindings (CC → knob/slider) |
MySong.phonon.zones | Performance zone MIDI trigger assignments |
samples/ | Project sample directory — WAV files used by audio tracks, One-Shot Sampler, Tracker, etc. Copied automatically on save for portability. |
The first time you save, Phonon creates a project directory (e.g., MySong/MySong.phonon)
to keep sidecar files organized. If you've already saved into a matching directory, it detects this.
| Action | Shortcut |
|---|---|
| New Project | Ctrl+N — confirmation dialog, then clears everything |
| Save | Ctrl+S — first save prompts for location |
| Open | Ctrl+O — opens file dialog |
| Extract to New Project | Ctrl+E — select tracks to clone into a fresh project. Deep-clones selected tracks with all modules, regions, and settings. |
Undo / Redo
Phonon uses a command-based undo system. Each undoable operation is recorded as a discrete, reversible action — not a full project snapshot. This means undo reverses exactly one operation (e.g., "delete this region" or "move this track"), not the entire project state. Up to 200 actions are stored in the history.
Audio regions: Delete, add, paste, move, slice, cross-track drag, loop toggle, mute/unmute, resize (left and right edges), retime (left and right edges), loop duration change.
Non-destructive audio: Reverse toggle, Change BPM, quantize (warp markers), retime method change, remove retiming. All operations store before/after snapshots including warp markers, sample offset, and playback rate.
Audio processing: Normalize, pitch shift. Undo restores the original sample data and file path.
MIDI transforms: Transpose, velocity mod, quantize grid (via Inspector sidebar). All non-destructive — undo restores the original transform values.
MIDI regions: Delete, create, paste, move.
Tracks & modules: Add track, add audio track, add audio bus, add module, delete track/module, mute/unmute module.
Audio import: Drag-and-drop file import.
| Action | Shortcut |
|---|---|
| Undo | Ctrl+Z |
| Redo | Ctrl+Y |
The undo stack is cleared when loading or creating a new project. Knob and slider edits are not recorded in the undo history — they are considered real-time performance actions.
History Panel
Press Ctrl+H to show or hide a side panel on the right edge of the window showing the complete undo/redo history as a clickable list.
Each action is displayed with a descriptive label (e.g., "Delete track 'Drums'", "Slice 'beat.wav' at beat 12.0", "Pitch shift +7 semitones"). The current state is highlighted — actions above are the undo history, actions below are redo-able.
Click any entry to jump directly to that point in history. Multiple undo/redo steps are applied automatically. This is equivalent to pressing Ctrl+Z or Ctrl+Y multiple times, but with precise visual targeting.
The panel header shows the current position (e.g., "↶ HISTORY (5/12)"). A Clear button resets the entire history.
© 2026 Phonon Music Software