182 create midi tracks#192
Merged
Merged
Conversation
Phases 1-3 of the MIDI tracks feature:
Phase 1 — Data model + Add MIDI Track:
- New src/types/midiClip.ts (MidiNote, MidiClipData, MidiInstrument)
- Widen TimelineSourceType + TimelineTrack.type to include 'midi';
midiInstrument on tracks, midiData on clips (+ SerializableClip)
- addTrack('midi') in trackSlice, TrackContextMenu entry
- MIDI tracks render in the audio section via isAudioSectionTrackType helper
- Ripple fixes across dock/project/clipboard types and reconcile maps
Phase 2 — Pencil tool:
- New 'midi-draw' tool registered across toolDefaults, registry, icons,
cursors, and shortcut presets (navigation group)
- addMidiClip action (midiClipSlice) + useMidiClipDraw hook: click-drag on
a MIDI lane paints a clip (free placement, no snap), viewport-fixed ghost
Phase 3 — Piano-roll detached window:
- PianoRollBoot (window.open popup, shared-heap, per-clip) + PianoRoll editor
- Note CRUD (add/update/remove) with single-snapshot drag history
- Draw/move/resize/delete notes, live playhead cursor, double-click to open
- Fix: drag listeners bound to the popup's ownerDocument (component runs in
the opener realm, so global `document` was the wrong window)
Tests: midiClipSlice note CRUD; updated navigation tool-cycle expectations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 4 (synth + playback): - MidiSynth: context-agnostic triangle/osc + ADSR, polyphonic scheduling - midiPlaybackScheduler: look-ahead scheduler anchoring timeline seconds to the AudioContext clock, 1x-forward, seek re-anchor, flush on stop Phase 4b / Step 2 (mixer parity): - Generalized audioRoutingManager to route arbitrary AudioNode sources (ensureSharedContext/applyNodeEffects/getNodeMeterSnapshot/removeNodeRoute) so MIDI reuses the same gain/FX/EQ/pan/meter chain + master bus as audio - createTrackLiveAudioRouteSettings for clip-less (track) sources - Properties panel: MIDI tracks get Controls + Instrument + Effects + Sends; AudioMixerPanel includes midi tracks - setTrackMidiInstrument action + MidiInstrumentTab Header UI: - MIDI tracks share the full audio mixer strip (vol/pan/solo/mute/rec/FX/ sends/meter) via a generalized "mixer track" concept (audio || midi); .track-header.audio CSS selectors renamed to .track-header.mixer - Track-type identifier glyphs above the name (waveform / piano-roll bars) - Instrument picker dropdown on its own full-width row, shared MIDI_INSTRUMENT_OPTIONS reused by header and properties tab Note: MIDI note/instrument persistence and offline export are Phase 5 (todo). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Persistence — MIDI note data now survives save/reload: - midiInstrument (track) was already persisted via track spread; the gap was midiData (notes), which clips serialize via explicit field lists - serializationUtils: add midiData to getSerializableState clip map + a new sourceType==='midi' restore branch in loadState (data-only clip, mirrors addMidiClip) - projectSave/projectLoad: add midiData to the on-disk clip mapping - test: midiPersistence round-trips serialize -> clear -> load Offline export — MIDI clips now render into exported audio: - MidiClipRenderer: pure planMidiClipNotes (clip-local note timing, dropped/ clamped at clip end) + renderMidiClipToBuffer (OfflineAudioContext + MidiSynth -> AudioBuffer) - AudioExportPipeline: getClipsWithAudio includes MIDI clips with notes; extractAllAudio renders the synth for MIDI clips instead of decoding a file. The rendered buffer flows through the same clip-fx -> track-fx -> mix -> master path as audio clips (full mixer parity, no separate MIDI export path) - test: midiClipRenderer covers the planner Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
@Sportinger the basic infrastructure for midi tracks is here. There are some things that should be tweaked, but I think this is a good point for merging since there already many changes. |
Resolved 5 conflicts (MIDI work vs. staging): - types/dock.ts: keep staging's trackTypeCounts/Layouts + new interface; extend trackTypeVisibility/Counts/Layouts to include 'midi' - timeline/trackSlice.ts: use staging's createTrackId(type) (widened to 'midi') with the MIDI-aware typeLabel for the track name - services/audioRoutingManager.ts: keep both nodeRoutes and routeCreateFailures - engine/audio/AudioExportPipeline.ts: run MIDI synth-render branch first, then staging's reusable cached/proxy-audio lookup - timeline/TimelineTracks.css: audio tracks adopt staging's single-column compact fader + audio-layer-advanced layout; MIDI keeps the original two-column mixer-parity layout (rules scoped to .midi) Build + lint clean. Pre-existing staging test failures in IssueCreditCampaignBanner.test.tsx (missing matchMedia polyfill) left as-is. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jsdom does not implement matchMedia, so components that query media features in passive effects (IssueCreditCampaignBanner, useTheme, DockContainer) threw a "matchMedia is not a function" error and failed the test suite. Add a standard no-op shim to the shared test setup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#182