Skip to content

Repository files navigation

MIDI Orphan & Sustain Fixer

A web-based tool and piano roll editor for inspecting, repairing, and adjusting MIDI files generated by audio-to-MIDI transcription models (such as Transkun or Onsets and Frames).

MIDI Orphan & Sustain Fixer Interface


The Problem

Audio-to-MIDI transcription models frequently produce timing and dynamic range artifacts:

  • Orphaned Notes: Due to polyphonic masking or slight timing estimation offsets, individual notes in a chord often release 20–100ms before a sustain pedal (CC64) onset occurs. Because their note-off precedes the pedal-on event, these notes are not held by the sustain envelope and cut off prematurely.
  • Duration Truncation: Transcription models can underestimate note durations, producing clipped or overly staccato note-offs.
  • Velocity Compression: Transcriptions often map velocities to a narrow dynamic range.

Features

Sustain Healing

  • Identifies notes that release within a configurable lookback window ($N$ ms) prior to a sustain pedal (CC64 $\ge$ 64) onset.
  • Extends the note-off timestamp to overlap with the pedal onset, ensuring the note is sustained through the pedal hold segment.
  • Visualizes repaired notes in green on the piano roll.

CC64 Sustain Lane Editing

  • Displays CC64 pedal events and active sustain hold segments below the piano roll.
  • Drag nodes horizontally to adjust timing or vertically across the threshold (64) to toggle between pedal ON (127) and OFF (0).
  • Double-click empty space to insert a new node, or double-click an existing node to delete it.

Canvas Piano Roll & Overview Minimap

  • HTML5 2D canvas piano roll rendering an 88-key layout with pitch labels and measure/beat grid lines.
  • Visualizes sustained resonance tails indicating the sounding duration until pedal release or the next note of the same pitch.
  • Includes a minimap overview of the full piece with a draggable viewport window.
  • Supports horizontal and vertical zoom, panning, and trackpad gestures.

Velocity Levels

  • Displays a 128-bin velocity histogram with transfer curve mapping.
  • Adjustable input black point (minimum threshold), gamma (midtone power curve), and white point (maximum threshold).
  • Auto-levels button detects the minimum and maximum velocities in the file and normalizes them across the 1–127 range.

Note Selection, Editing & Marquee Tool

  • Click to Select: Click any note to select and highlight it with a high-contrast white outline.
  • Rectangular Marquee Selection: Drag across the piano roll canvas to select multiple notes within a marquee box.
  • Shift-Modifiers: Shift + Click toggles individual notes; Shift + Drag adds notes to the existing selection.
  • Live Sound Preview: Newly selected notes automatically sound through the active SoundFont on click, shift-click, and marquee sweep. Clicking keys on the left vertical piano keyboard also sounds that pitch.
  • Nudge Position: / nudges start time back or forward by 4 ticks (40 ticks with Shift).
  • Nudge Duration: ⌥← / ⌥→ (Alt / Option + Arrow keys) lengthens or shortens note duration by 4 ticks (40 ticks with Shift, minimum 1 tick).
  • Delete Notes: Press Delete or Backspace to remove selected notes with full undo/redo history support.
  • Configurable Increments: Hotkeys and nudge tick increments are centralized in src/config/editorConfig.ts.

Note Info & Inspector Panel

  • Dedicated 4th card in the bottom inspector panel replacing floating hover cards.
  • Single Note Mode: Displays pitch name/MIDI #, start position (ticks & seconds/ms), duration (ticks & seconds/ms), velocity (current & original), sustain status, orphan gap, and hotkey legend.
  • Multi-Note Selection Mode: Displays note count badge, pitch range (C3 – G5), total time span, velocity range, tick span, and multi-note editing guide.

Note Duration Adjustments

  • Constant Duration Offset: Adds or subtracts a fixed millisecond offset across all note durations.
  • Minimum Note Duration: Sets a lower bound on note duration to remove micro-duration artifacts.

SoundFont Synthesizer & Audio Playback

  • Audio playback powered by spessasynth_lib running in a Web Audio Worklet.
  • Streams SoundFont presets on-demand from https://gifx.co/soundfonts/ (Yamaha Grand, Chateau Grand, Abbey Steinway D, SC-55, TimGM6mb, etc.) with support for loading custom local .sf2 files.
  • Transport controls include play/pause, loop, return to zero, playback speed multiplier (0.5x–2.0x), follow playhead mode, active voice counter, and timeline scrubbing.

Non-Destructive Pipeline & History

  • Original MIDI data remains unmodified in memory; modifiers are applied non-destructively to a derived note list.
  • Bypass toggle allows A/B comparison between raw input and modified output.
  • Full undo/redo history stack (Cmd/Ctrl + Z, Cmd/Ctrl + Shift + Z) supporting note deletions, nudges (coalesced), CC64 edits, and modifier updates.

Import & Export

  • Drag-and-drop support for .mid and .midi files, plus a built-in demo file.
  • Exports standard Type 0/1 binary MIDI files with updated note durations and CC64 events.

Keyboard Shortcuts & Interactions

Action Shortcut / Interaction
Play / Pause Space
Rewind to Start Home or 0
Toggle Looping L
Undo Cmd / Ctrl + Z
Redo Cmd / Ctrl + Shift + Z (or Cmd / Ctrl + Y)
Select & Sound Note Click note in piano roll
Toggle Note Selection Shift + Click note
Marquee Box Select Click & drag on empty canvas grid (sounds newly swept notes)
Extend Marquee Selection Shift + Click & drag on canvas grid
Deselect All Notes Click empty space on canvas grid
Nudge Note Position / (±4 ticks; hold Shift for ±40 ticks)
Nudge Note Duration ⌥← / ⌥→ (Option / Alt + Arrows; hold Shift for ±40 ticks)
Delete Selected Note(s) Delete or Backspace
Sound Piano Key Click key on left vertical keyboard ruler
Zoom Horizontal Cmd / Ctrl + Mouse Wheel / Pinch
Scroll Timeline Shift + Mouse Wheel / Two-finger horizontal swipe
Add Sustain Node Double-click empty space in the Sustain lane
Delete Sustain Node Double-click an existing sustain node
Move / Toggle Node Drag sustain node horizontally (time) or vertically (ON/OFF)
Scrub Playhead Click or drag on the timeline ruler

Getting Started

Prerequisites

  • Node.js (v18 or higher)
  • npm

Installation

# Clone the repository
git clone https://github.com/mmontag/miditool.git
cd miditool

# Install dependencies
npm install

# Start the development server
npm run dev

Open http://localhost:3088 in your browser.


Scripts

  • npm run dev: Starts the Vite development server on port 3088.
  • npm run build: Type-checks and builds the production bundle in dist/.
  • npm run preview: Previews the production build locally.
  • npm run test: Runs unit tests for history and storage modules.
  • node deploy.mjs: Builds and deploys the production bundle to https://gifx.co/miditool.

Tech Stack


License

MIT

Releases

Packages

Contributors

Languages