@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 0.2.0 - 2026-09-02
|
||||
|
||||
- Moved bounded MIDI parsing, transforms and export into cancellable worker jobs
|
||||
with progress and stale-result suppression.
|
||||
- Added paired-note editing/deletion, transposition and quantization controls.
|
||||
- Added explicit opt-in, sysex-disabled Web MIDI output and bounded local
|
||||
SoundFont metadata inspection without claiming SoundFont synthesis.
|
||||
- Declared MIDI/SoundFont input, export and optional browser capability profiles
|
||||
for Toolbox handoff.
|
||||
|
||||
## 0.1.0 - 2026-09-01
|
||||
|
||||
- Added bounded Standard MIDI type 0/1 parsing and deterministic MIDI export.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
==============================================================================
|
||||
@add-ideas/toolbox-contract@0.2.3
|
||||
@add-ideas/toolbox-contract@0.3.0
|
||||
Declared licence: Apache-2.0
|
||||
==============================================================================
|
||||
--- LICENSE ---
|
||||
@@ -198,7 +198,7 @@ Declared licence: Apache-2.0
|
||||
|
||||
|
||||
==============================================================================
|
||||
@add-ideas/toolbox-helpers@0.1.0
|
||||
@add-ideas/toolbox-helpers@0.2.0
|
||||
Declared licence: GPL-3.0-or-later
|
||||
==============================================================================
|
||||
--- LICENSE ---
|
||||
@@ -879,7 +879,7 @@ Public License instead of this License. But first, please read
|
||||
|
||||
|
||||
==============================================================================
|
||||
@add-ideas/toolbox-shell-react@0.2.3
|
||||
@add-ideas/toolbox-shell-react@0.3.0
|
||||
Declared licence: Apache-2.0
|
||||
==============================================================================
|
||||
--- LICENSE ---
|
||||
|
||||
+10
-4
@@ -5,21 +5,27 @@ Parse, visualize, edit, audition and export Standard MIDI files locally in the b
|
||||
## Features
|
||||
|
||||
- Strict, bounded Standard MIDI file type 0 and type 1 parsing with running status, canonical VLQs, channel events, metadata and bounded SysEx.
|
||||
- Disposable module-worker parsing, editing and MIDI/CSV/JSON export with
|
||||
progress, explicit cancellation and stale-result suppression.
|
||||
- Track/event inspection, tempo, time-signature and key-signature timelines, a piano roll and pitch-class keyboard.
|
||||
- Immediate-stop Web Audio timing preview using a small built-in sine synthesizer.
|
||||
- Transpose, note quantize, constant-tempo, crop and channel remap/remove operations with twenty-step undo.
|
||||
- Immediate-stop Web Audio timing preview using a small built-in sine synthesizer,
|
||||
plus explicitly enabled Web MIDI output without SysEx permission.
|
||||
- Click-to-edit paired notes, transpose, note quantize, constant-tempo, crop and
|
||||
channel remap/remove operations with twenty-step undo.
|
||||
- Bounded local SF2/SF3 RIFF structure inspection. SoundFont rendering is
|
||||
deliberately not claimed until a vetted local synthesizer is bundled.
|
||||
- Deterministic valid MIDI export plus spreadsheet-safe CSV and descriptive JSON reports.
|
||||
- Offline PWA and shared Toolbox system/light/dark shell.
|
||||
|
||||
## Limits and editing semantics
|
||||
|
||||
Input and output are capped at 8 MiB, 256 tracks and 250,000 events; aggregate SysEx is capped at 1 MiB. Only PPQN timing is supported. Playback schedules at most 2,000 notes, considers the first 900 seconds and caps any sounding note at 30 seconds. It is a timing preview, not a General MIDI instrument or soundfont renderer.
|
||||
Input and output are capped at 8 MiB, 256 tracks and 250,000 events; aggregate SysEx is capped at 1 MiB. Only PPQN timing is supported. Playback schedules at most 2,000 notes, considers the first 900 seconds and caps any sounding note at 30 seconds. Web MIDI is an explicit browser permission and sends only channel note messages to the selected output. SF2/SF3 inspection is capped at 128 MiB and never loads a remote bank. The built-in player is a timing preview, not a General MIDI instrument or SoundFont renderer.
|
||||
|
||||
Transpose updates note, note-off and poly-pressure pitches but deliberately does not rewrite key signatures. Quantize moves paired note boundaries to ticks. Crop clips overlapping paired notes, retains the latest tempo/time/key, program and controller setup, then shifts to tick zero. MIDI export writes full status bytes, canonical VLQs and one end-of-track event per track.
|
||||
|
||||
## Development
|
||||
|
||||
Use Node.js 22+ and npm 11. Run `npm ci`, `npm run check`, `npm run test:browser`, then `npm run package:release -- --force`. The deterministic artifact is `release/midi-tools-0.1.0.zip` with a SHA-256 sidecar.
|
||||
Use Node.js 22+ and npm 11. Run `npm ci`, `npm run check`, `npm run test:browser`, then `npm run package:release -- --force`. The deterministic artifact is `release/midi-tools-0.2.0.zip` with a SHA-256 sidecar.
|
||||
|
||||
## Licence
|
||||
|
||||
|
||||
+12
-2
@@ -1,5 +1,15 @@
|
||||
# Security policy
|
||||
|
||||
Report vulnerabilities privately to the repository owner. Supported version: 0.1.x.
|
||||
Report vulnerabilities privately to the repository owner. Supported version: 0.2.x.
|
||||
|
||||
MIDI Tools makes no uploads, telemetry or third-party requests. JSON is parsed as inert data under text, depth, node and token-count bounds. Exporters escape Android XML and quote Swift strings. Generated source remains an input to another toolchain and must be reviewed before production use.
|
||||
MIDI Tools makes no uploads, telemetry or third-party requests. MIDI and
|
||||
SoundFont files are treated as untrusted binary data under the documented size,
|
||||
track, event, SysEx and RIFF-chunk bounds. Worker results are revision-scoped so
|
||||
cancelled or superseded jobs cannot replace newer state.
|
||||
|
||||
Web MIDI access is requested only after an explicit click and always with SysEx
|
||||
permission disabled. The app does not subscribe to MIDI inputs; playback sends
|
||||
only bounded channel messages to the output selected by the user, and Stop
|
||||
clears queued messages and sends all-notes-off on every channel. SoundFont files
|
||||
are inspected locally for bounded RIFF metadata and are never synthesized,
|
||||
executed, fetched remotely or sent to a device.
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
# Source identity
|
||||
|
||||
- Project: MIDI Tools
|
||||
- Version: 0.1.0
|
||||
- Version: 0.2.0
|
||||
- Repository: https://git.add-ideas.de/lotobo/midi-tools
|
||||
- Licence: GPL-3.0-or-later
|
||||
- Build: Node.js 22+, npm 11, `npm ci && npm run release:artifact`
|
||||
- Artifact: `midi-tools-0.1.0.zip`
|
||||
- Artifact: `midi-tools-0.2.0.zip`
|
||||
|
||||
The lockfile pins dependencies exactly. Generated release manifests repeat this source identity and releases include detected runtime licence texts under `LICENSES/`.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Third-party notices
|
||||
|
||||
MIDI Tools is GPL-3.0-or-later. Runtime dependencies are React, React DOM and the add·ideas Toolbox Contract, Shell and Helpers packages. Exact versions and declared licences are recorded in `package-lock.json`; detected runtime licence texts are generated into release archives at `LICENSES/npm-runtime-licenses.txt`.
|
||||
MIDI Tools is GPL-3.0-or-later. Runtime dependencies are React and React DOM
|
||||
(MIT), add·ideas Toolbox Contract and Shell React 0.3.0 (Apache-2.0), and
|
||||
Toolbox Helpers 0.2.0 (GPL-3.0-or-later). Exact versions and declared licences
|
||||
are recorded in `package-lock.json`; detected runtime licence texts are
|
||||
generated into release archives at `LICENSES/npm-runtime-licenses.txt`.
|
||||
|
||||
“MIDI” refers to the Standard MIDI File data format. This project is independent and does not imply endorsement by the MIDI Association.
|
||||
|
||||
@@ -2,6 +2,20 @@
|
||||
|
||||
`core/midi.ts` turns a bounded SMF byte stream into inert tracks and absolute-tick events. Chunk boundaries, four-byte VLQs, running status, event counts, SysEx size, PPQN division and known fixed-length meta events are validated before data is exposed. Editing functions clone this model and preserve stable event ordering.
|
||||
|
||||
`Workbench.tsx` keeps the last valid document during failed imports or operations. The SVG piano roll renders at most 5,000 notes. Playback maps ticks through the tempo map, creates fixed application-owned sine oscillators and can stop immediately by closing the active `AudioContext`; imported bytes never become code or remote references.
|
||||
`Workbench.tsx` keeps the last valid document during failed imports or
|
||||
operations. Parsing, transforms and exports execute through a disposable module
|
||||
worker; progress messages are revision-scoped, cancellation terminates the
|
||||
worker and late messages cannot replace newer state. A no-Worker fallback exists
|
||||
for test and older-browser resilience, while the shipped browser path stays
|
||||
off-main. The SVG piano roll renders at most 5,000 notes. Playback maps ticks
|
||||
through the tempo map, creates fixed application-owned sine oscillators and can
|
||||
stop immediately by closing the active `AudioContext`; imported bytes never
|
||||
become code or remote references.
|
||||
|
||||
Paired notes can be selected in the SVG piano roll and edited through the same
|
||||
worker protocol as bulk transforms. Web MIDI access is requested only after an
|
||||
explicit click, without SysEx permission; scheduled output is bounded and Stop
|
||||
sends all-notes-off on every channel. The local SoundFont inspector validates
|
||||
RIFF `sfbk` structure and reports INFO/pdta counts but does not render the bank.
|
||||
|
||||
All Vite assets use relative paths for nested portal mounting. Release packaging fixes ZIP ordering, timestamps and permissions.
|
||||
|
||||
@@ -2,4 +2,16 @@
|
||||
|
||||
MIDI bytes are read into browser memory only. The application has no telemetry, account, database, remote asset or network client. CSP restricts connections and media to the application origin or local blobs.
|
||||
|
||||
Parsing and export enforce an 8 MiB file bound, 256 tracks, 250,000 events, a 1 MiB aggregate SysEx bound, four-byte VLQs and signed-safe absolute ticks. Playback is explicitly user started, schedules at most 2,000 notes and is stopped by closing its audio context. Imported text appears only as escaped React text and is never interpreted as markup, script, URL or shader.
|
||||
Parsing and export enforce an 8 MiB file bound, 256 tracks, 250,000 events, a
|
||||
1 MiB aggregate SysEx bound, four-byte VLQs and signed-safe absolute ticks.
|
||||
Worker messages are revision-scoped, and cancellation terminates the disposable
|
||||
worker before stale results can update the document.
|
||||
|
||||
Web Audio and Web MIDI playback are explicitly user started and schedule at most
|
||||
2,000 notes over the first 900 seconds. Web MIDI permission is requested with
|
||||
SysEx disabled; the app does not subscribe to MIDI inputs and sends only channel
|
||||
note messages to the selected output. Stop clears scheduled output and sends
|
||||
all-notes-off on every channel. Local SoundFont inspection is capped at 128 MiB,
|
||||
validates bounded RIFF structure and reports metadata only; it neither
|
||||
synthesizes the bank nor resolves remote resources. Imported text appears only
|
||||
as escaped React text and is never interpreted as markup, script, URL or shader.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const CACHE_PREFIX = "midi-tools-shell-";
|
||||
const CACHE_NAME = CACHE_PREFIX + "0.1.0";
|
||||
const CACHE_NAME = CACHE_PREFIX + "0.2.0";
|
||||
const CORE = ["./", "./manifest.webmanifest", "./favicon.svg"];
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(
|
||||
|
||||
+24
-2
@@ -3,12 +3,19 @@
|
||||
"schemaVersion": 1,
|
||||
"id": "de.add-ideas.midi-tools",
|
||||
"name": "MIDI Tools",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Inspect, edit and play MIDI locally.",
|
||||
"entry": "./",
|
||||
"icon": "./favicon.svg",
|
||||
"categories": ["audio", "media", "developer"],
|
||||
"tags": ["midi", "piano roll", "tempo", "sequencer", "web audio"],
|
||||
"tags": [
|
||||
"midi",
|
||||
"piano roll",
|
||||
"tempo",
|
||||
"sequencer",
|
||||
"web audio",
|
||||
"soundfont"
|
||||
],
|
||||
"integration": {
|
||||
"contextVersion": 1,
|
||||
"launchModes": ["navigate", "new-tab"],
|
||||
@@ -21,6 +28,21 @@
|
||||
"crossOriginIsolated": false,
|
||||
"topLevelContext": false
|
||||
},
|
||||
"io": {
|
||||
"accepts": [
|
||||
{ "mediaType": "audio/midi", "extensions": [".mid", ".midi"] },
|
||||
{ "mediaType": "audio/x-soundfont", "extensions": [".sf2", ".sf3"] }
|
||||
],
|
||||
"produces": [
|
||||
{ "mediaType": "audio/midi", "extensions": [".mid"] },
|
||||
{ "mediaType": "text/csv", "extensions": [".csv"] },
|
||||
{ "mediaType": "application/json", "extensions": [".json"] }
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"required": [],
|
||||
"optional": ["workers", "web-audio", "web-midi"]
|
||||
},
|
||||
"privacy": {
|
||||
"processing": "local",
|
||||
"fileUploads": true,
|
||||
|
||||
Reference in New Issue
Block a user