Skip to content

feat: swing, master bus, synth editor, stems, live input, module dock, sample tools - #8

Merged
steady41 merged 6 commits into
mainfrom
testing
Aug 26, 2026
Merged

feat: swing, master bus, synth editor, stems, live input, module dock, sample tools#8
steady41 merged 6 commits into
mainfrom
testing

Conversation

@steady41

Copy link
Copy Markdown
Owner

Summary

Big feature drop for VOIDSTATION, developed and verified on the testing branch. Design language untouched — everything uses the existing hardware-panel tokens.

Audio engine

  • Swing/groove — odd 16th steps delay up to 1/3 step (SWING slider in the transport bar); live, offline render and persisted
  • Master bus — master volume + brickwall limiter (DynamicsCompressor toggle/threshold) + real output LED meter via AnalyserNode
  • Live voicesnoteOn/noteOff held-note synth API; transport stop kills all live voices
  • Sample tools — tape-style PITCH (-24..+12 semitones), REVERSE with trim-aware bounds swap
  • Pattern clipboard — COPY/PASTE full-pattern snapshots, element-wise paste keeps live refs linked
  • Row tools — clear / shift left/right / humanize accents per sequencer row

UI modules

  • SYNTH EDITOR — per-track waveform + ADSR editing (engine state existed, no UI before)
  • MASTER SECTION — volume, limiter, output meter
  • LIVE CONTROLLER — computer-keyboard mapping (Z S X D C V G B H N J M…, -/= octave) + Web MIDI with hot-plug
  • MODULES DOCK — slide-out sidebar listing every window: drag a chip onto the wall to place it, drag on-wall chips to relocate, click to locate/pan, puts a unit away, header double-click collapses the body; layout persists {positions, docked, collapsed}

Export

  • EXPORT STEMS — per-track WAV renders (fx chains + master included, silent tracks skipped)

Infra & fixes

  • CI runs on all branches: typecheck → build → 32 node:test suites → per-file syntax check → index.html asset-link check; Dependabot for npm/actions
  • Fixed local dev being a guaranteed 404 (index.html loaded non-existent src/main.js)
  • Fixed deserialize crash on saves whose patterns contain <5 track entries

Test plan

  • npx tsc --noEmit clean
  • npm run build clean, every compiled module passes node --check
  • 32/32 headless engine/WAV tests green locally and in CI

…dependabot

- CI now triggers on every branch push (not just main), cancels superseded
  runs, and runs the new node:test suite after build
- tests/: headless engine tests (patterns, playlist ops, loop wrap, swing,
  undo/redo, serialize round-trip incl. legacy saves) + WAV encoder tests,
  all via the built-in node test runner (zero new dependencies)
- fix engine deserialize crash on saves whose patterns contain fewer than
  five track entries; missing tracks are filled with empty pattern data
- fix index.html loading src/main.js which never exists (tsc emits to
  dist/main.js): local dev per README was a guaranteed 404; deploy.yml
  rewrite updated to match
- verify index.html asset links resolve in CI; dependabot keeps npm deps
  and github-actions versions fresh
…mple pitch

- EXPORT STEMS: renders every track playing in the export region to its
  own WAV (fx + master bus included); silent tracks are skipped
- LIVE CONTROLLER module: held-note synth voices via noteOn/noteOff,
  computer-keyboard mapping (Z S X D C V G B H N J M..., -/= octave),
  Web MIDI input with hot-plug, on-screen keys; transport stop kills
  all live voices
- COPY/PASTE pattern buttons in the arranger toolbar: full-track snapshot
  clipboard, element-wise paste keeps live pattern references linked
- Sample PITCH: tape-style semitone offset (-24..+12 -> playbackRate),
  applied live/in exports/persisted; sampler slider + reset

Note: shipped as one atomic commit because the four features interleave
inside engine.ts; splitting would risk non-building intermediates.
- REV toggle in the sampler actions row (disabled without a sample,
  waveform wrap gets a subtle accent outline when active)
- reversed playback uses a lazily built per-track reversed buffer cache
  (invalidated on load/clear/restore/toggle); the trim window is measured
  from the end of the audio while reversed, so trims stay meaningful
- applied at every trigger site: preview, live scheduler and offline
  render (stems/WAV export included); persisted as optional field
- slide-out sidebar (left edge, MODULES tab / HUD dock button) listing
  every registered module as a chip with an LED state marker
- drag a chip onto the wall to place its module at the drop point
  (restores it if it was put away); drag an on-wall chip to relocate;
  plain click auto-pans to the module and pulses its outline
- new header button puts a module away into the dock; double-click on a
  header collapses/expands the body
- wall layout persistence extended to { positions, docked, collapsed }
  with backwards-compatible parsing of the old flat format; RESET keeps
  docked units put away
…ound-trip

- master volume/threshold clamping + persistence, metronome preference
- setLoopRegion one-bar/inverted-input rules; clip assignment extends
  the region beyond its end
- shiftTrackPattern keeps accents glued to their steps;
  randomizeTrackAccents only re-rolls active steps
- _stepSourceForBar playlist/live/null-slot semantics
- v1 projects (pattern/pianoGrid on the track entries) still load
- insert-effect reorder/params survive serialize/deserialize
- clearProject factory reset; _effectiveVolume mute/solo matrix
@steady41
steady41 merged commit 223247b into main Aug 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant