—DRUM SYNTH
ONLY 15€ / $16.30 / 60zł
All news
tomicupdatereleasev0.7.0poly-lanechordsthrough-zero-fmring-modulationmesh-2dmod-matrixfilterslanczosguibuild-1f4c1117

TOMiC 0.7.0 Update: POLY Per-Step Chord Lane (46 Shapes), Through-Zero FM, Mod-to-Mod Routing, Interactive Filter Graphs & 1:1 Lanczos Knobs

Engineering changelog for TOMiC v0.7.0 Build 1f4c1117 (23 commits since e42cb7cf): paraphonic POLY sequencer lane with 46 chord shapes and Polyphonic host MIDI, Engine + Mod split with Linear/Phase/Through-Zero FM and Ring Modulation across Plaits/Cluster/Harmonics/Mesh 2D, 1,348 modulate-a-modulator targets with live panel rings, draggable cutoff/resonance filter graphs, and per-DPI 1:1 Lanczos3 two-layer knob rendering.

November 11, 2026 TOMiC Team
TOMiC 0.7.0 Update: POLY Per-Step Chord Lane (46 Shapes), Through-Zero FM, Mod-to-Mod Routing, Interactive Filter Graphs & 1:1 Lanczos Knobs

Version: 0.7.0 | Build: 1f4c1117 (Upgraded from e42cb7cf, 23 commits)


1. POLY Step Sequencer Lane (46 Chord Shapes & Voice-Leading Tools)

Commits: 71c32ca0, 1f4c1117

A dedicated POLY lane sits alongside PITCH in the step sequencer (LaneKey::Poly, paint mode 17). It runs on its own clock (linked to PITCH step indices by default), allowing short harmonic loops such as 4-step chord progressions to cycle beneath any TRIG pattern length.

Chord Engine & Root-Top Voicing

  • 46 Chord Shapes (ChordKind): Initially introduced with 21 core intervals/triads/sevenths and expanded by 24 additional voicings in 1f4c1117 — dyads (M3, m3, 4th, tritone), add2/add11, 6/9, m6/9, 7sus2, maj7sus2, 7b5, +7, +maj7, 9/maj9/m9/9sus4 (no 5th), m11, 13 shell, maj7#11, 7b9, 7#9, quintal, and a semitone cluster. Every shape is capped at root + 3 notes.
  • Step Picker & Scale Awareness: Clicking a POLY step opens a six-group chord picker modeled on the COND popup. CHORD_POOL is ordered by harmonic complexity; shapes containing tones outside the channel pitch scale are dimmed. Scroll wheel cycles shapes, right-click clears back to a single note, and the RND half selects an in-scale chord dynamically per trigger.
  • Inversions Keep Top Root Fixed: Chord inversions shift upper intervals downward below the PITCH note so step_pitch stays fixed as the voicing ceiling. Sub-oscillators, noise layers, and pitch-tracking targets continue tracking the pitch shown on the PITCH lane.
  • Paraphonic Internal DSP (OSC 1 / OSC 2): When a step triggers a chord, render_osc1_core and render_osc2_core swap per-note OscCore state copies to render up to four notes per step across every SynthesisType arm, equal-power summed before shared envelopes, filters, granular processing, and FX. Mesh 2D and the standalone Granular engine remain monophonic root-only; steps without chords execute the original path unchanged.
  • Polyphonic Hosted Instrument Output: Hosted CLAP, VST3, and .omniplugin synths receive stacked polyphonic MIDI events (note_on for the root, note_on_stacked bypassing release-first even in mono mode for upper tones), released together on the subsequent trigger.

POLY Lane Tool Row & Auto-Randomize (engine/sequencer/poly_ops.rs)

  • Step & Inversion Transforms: Shift < > (rotates chord shapes together with RND flags), + / - (shifts all active chords up or down one inversion), x2, /2, Reverse, Invert (parallel quality toggles: major/minor, sus2/sus4, dim/aug), and Clear.
  • Spring-Back Global Knobs (spring_knob):
    • Cmp: compresses/expands voicings toward simpler or denser entries in CHORD_POOL.
    • Ofs: shifts each chord up to 12 in-scale steps along the pool.
    • Rnd: replaces a fraction of steps with random in-scale shapes from the AR range window.
    • Slw: applies voice-leading smoothing by picking the inversion closest to the preceding step.
  • Auto-Randomize & Serialization: POLY integrates directly into the AR Rack (after PITCH) with dedicated range bounds, Re-roll, Drift/Elastic, Shuffle/Rotate, and Mix-to-Home. Default chordless steps omit the new Step fields so existing patches save and load unchanged.

2. Oscillator Architecture Split, Through-Zero FM (TZ) & Ring Mod Expansion

Commits: 33697702, 250704cd, e11d1371, 810f8660, 29b7e0fd, c0519cd2, d0cda332, 4d737093

Engine + Mod Split (33697702)

The single combined Type menu has been split into two controls mapped bijectively onto the existing synthesis_type storage field (decompose_synth / compose_osc_synth):

  • Engine Selector: Oscillator, Harmonics, Cluster, Mesh 2D (and legacy Granular when opening older projects).
  • Mod Switch (Off / FM / Ring): Preserves the chosen carrier waveform when switching modulation modes. Unsupported engine/mode combinations grey out with an explicit reason instead of silently dropping selection. Colliding carrier labels were disambiguated (Braids SineKick/SqrHats, Plaits VA/Shaper/WTMorph, Morph Wavetable).

FM & Ring Across Plaits, Cluster, Harmonics & Mesh 2D (250704cd, e11d1371)

  • Added SynthesisType variants PlaitsRing, ClusterFm, ClusterRing, HarmonicsFm, HarmonicsRing, and MeshRing.
  • Cluster and Harmonics support Linear FM on their internal frequency buffers (add_linear_fm).
  • Plaits, Cluster, Harmonics, and Mesh 2D pickups now share the ring_mix_block dry/ring stage across both OSC 1 and OSC 2. At Amount = 0, unit tests verify bit-exact parity with plain unmodulated engines.
  • Under Mesh 2D, the FM/Ring box now remains visible above the plate editor, factory plate presets move from dual miniature button rows into a single full-name Factory combo box (29b7e0fd), and the Granulate panel widens below Timbre | P.Mod to 226 pt with all eight knobs (Position..Density, Texture..Reverb) arranged in one row (810f8660).

Through-Zero FM (FmEngine::ThroughZero, c0519cd2) & Modulator Display (4d737093)

  • Standard Linear FM clamps a carrier near 0 Hz once deviation exceeds the carrier frequency (Amt above ~10% at the FM envelope peak), creating hard waveform stalling.
  • ThroughZero integrates the linear deviation into a bidirectional phase offset (tz_step, per-voice tz_phase / tz_phase2, reset on trigger) so the carrier reverses direction cleanly through zero phase.
  • Cycled via the Eng switch (Lin / Phs / TZ), supported on Wave, BraidsFm, and PlaitsFm algorithms with a phase input; algorithms without a phase input fall back to Linear delay/filter/noise modulation and display an FM: texture badge in the picker.
  • For non-standard-wave carriers on OSC 1, the FM header now surfaces mod [Sin|Tri|Sqr|Saw|Nse] (Noise highlighted) because a hidden Noise modulator raises spectral flatness ~10x compared to Sine (verified via added fm_ spectral diagnostics in d0cda332).

3. Modulate-a-Modulator (1,348 Targets) & Panel Modulation Rings

Commits: 202f780e, c0878d58

Continuous parameters inside modulators can now be modulated by any modulation source:

  • Expanded LfoTarget (models/mod_param_targets_gen.rs): Appended 1,348 generated targets (leaving the original 80 routes intact for saved patches) covering continuous parameters on:
    • LFO: phase, pulse width, curve, depth, drift, bias, smooth, delay, fade.
    • Mod Env: delay, hold, sustain, release, velocity amount, vel-to-attack, sustain fade, depth (with block-rate synchronization for hold/delay/sus-fade/vel>atk).
    • All 10 Omni Sources: continuous parameters from Lorenz through Step Seq, including RND and SEQ.
  • Routing UI & Rings: Context menus group targets under "MOD: <family> <n>" (568 per-slot targets), modulator panel knobs accept drag-and-drop cables via ModParamCtx.slot, and Macro owner groups shifted 12 -> 14 to resolve a collision with RND's MOD IN. Channel view evaluates ModParamHighlights per frame so LFO, ENV, REC, and Omni panel knobs display animated modulation indicator rings and "modulated by" tooltips matching synthesis knobs.

4. Interactive Filter Graph Dragging & Panel Layout

Commits: eb104db2, f7a0fd6b, 5331a4d3, 63a670c7, d89515b1

  • Direct Graph Editing (f7a0fd6b): Clicking and dragging inside the frequency-response curve in any filter slot (Mix FX 1–8, Master bus, Noise 1, Noise 2) sets cutoff horizontally along the log frequency axis and resonance vertically (normalized to cover Noise slot 1's legacy Q range). Holds Shift for fine adjustment, supports double-click reset, and commits one undo action per drag gesture.
  • Stacked Caption Column & Full-Width Mix FX (eb104db2, 5331a4d3): Filter index, mode, and model stack in a compact left column so the response curve fills the remaining width (560 pt max across the Mix FX panel; compact column width preserved in Noise layers).
  • Routing & Tab Removal (d89515b1, 63a670c7): For filter slots 2..8 (Mix FX and Noise), the Serial/Parallel routing selector sits in the knob row below the graph in the same position occupied by the drive selector on slot 1. Closing the currently viewed filter slot (e.g. F8) now steps selection to the nearest active neighbor below rather than jumping back to F1.

5. Two-Layer 1:1 Pixel-Grid Lanczos Knobs & Linux Atlas Fix

Commits: 3c6313fe, 4fa68052, 33adf316, 457ce59b

  • Linux OpenGL Texture Limit Fix (3c6313fe): Repacked the legacy 100x12800 filmstrip into a 16x8 (1600x800) atlas to prevent first-frame black windows/panics on Linux OpenGL drivers capped at 8192 px max texture dimension.
  • Two-Layer Texture Architecture (4fa68052): Replaced the 128-frame (~5 MB) sprite filmstrip with two lightweight textures — static knob_base (baked scale and shadow) and rotating knob_body (12:00 pointer drawn across a 240° 8:00..4:00 travel shared across vector fallback and modulation rings).
  • 1:1 Per-Pixel-Size Lanczos3 Caching (33adf316, 457ce59b): Removed hardcoded 250 px source assertions to accept 1000 px source PNGs and eliminated GPU bilinear mipmap softening. Each rendered diameter (diameter * pixels_per_point) generates and caches a dedicated premultiplied-alpha Lanczos3 texture snapped directly onto the physical pixel grid.

Commit Reference (e42cb7cf..1f4c1117)

1f4c1117 POLY lane: 46 chord shapes and the tool row (shift, +/-, Global knobs, transforms)
71c32ca0 POLY lane: per-step chords on the internal oscillators and hosted synths
457ce59b Knob: per-pixel-size Lanczos textures drawn 1:1 on the pixel grid
33adf316 Knob layers: any PNG size (was a hard 250 px assert that would panic the GUI)
4fa68052 Knob: two-layer texture (static base + rotated body), 240° travel
3c6313fe Knob filmstrip: repack 100x12800 strip into 16x8 atlas (1600x800)
c0878d58 Modulator panels: modulation rings on their own knobs
202f780e Modulate a modulator: every continuous modulator parameter is a target
d89515b1 Filter slots 2-8: Serial/Parallel combo moves to the knob row
63a670c7 Filter tabs: removing the viewed slot steps to its neighbour below, not F1
5331a4d3 Mix FX filter: box spans the panel, graph takes the side margins
c8bd4887 Revert "Filter slots: F1..F8 tabs as a vertical strip beside the box, graph taller"
d273de0c Filter slots: F1..F8 tabs as a vertical strip beside the box, graph taller
f7a0fd6b Filter graph: drag to set cutoff (x) and resonance (y)
eb104db2 Filter face: type/kind stacked under the caption, response graph beside them
4d737093 FM box: show OSC 1's modulator shape for non-standard-wave sources
d0cda332 Ignored FM noise diagnostics: inharmonic share + spectral flatness per source/engine
c0519cd2 FM: through-zero engine (TZ) + "FM: texture" mark in the source picker
29b7e0fd Mesh 2D: factory plates in a combo instead of two button rows
810f8660 Mesh 2D: Granulate box full width, eight knobs in one row
e11d1371 Mesh 2D: Ring modulation + FM/Ring box above the plate box
250704cd Oscillator Mod stage 2: FM/Ring on Plaits, Cluster and Harmonics
33697702 Oscillator: Engine + Mod (Off/FM/Ring) instead of the combined Type list