No description
  • TypeScript 47.9%
  • Vue 31.1%
  • JavaScript 20.5%
  • Dockerfile 0.3%
  • CSS 0.2%
Find a file
Acaua Montiel 3743896a08
All checks were successful
Build & Push / build-push (push) Successful in 1m37s
Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI)
A browser editor for the Casio Privia PX-330, talking to the instrument
over Web MIDI with Casio's Individual Parameter Transfer messages.

- Protocol layer (app/lib/midi/casio.ts) and the Web MIDI connection, with
  per-parameter throttling, requests with timeout and retry, and a wake-up
  request that works around the instrument dropping the first messages
  after its port is opened.
- A 2796-parameter registry covering the master, effect, part, tone, DSP
  and scale tune tables, plus the 250-tone list extracted from the manual.
- Setup mode (Layer & Split, keyboard parts, effects, tuning) and Mixer
  mode (accompaniment and MIDI parts), with a local library, combos and
  JSON export/import.
- Tones are written through the panel's own Setup parameter, so the
  instrument loads them the way its buttons do and the display follows.
- docs/: what the instrument exposes over MIDI, the document contract and
  how the three test layers are run.
- Forgejo CI builds and pushes the image; compose.prod.yml runs it behind
  the shared reverse proxy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 18:23:32 -03:00
.forgejo/workflows Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
app Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
docs Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
public/icons Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
tests/e2e Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
.dockerignore Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
.editorconfig Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
.env.example Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
.gitignore Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
compose.prod.yml Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
compose.yaml Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
Dockerfile Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
eslint.config.mjs Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
nuxt.config.ts Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
package.json Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
PLAN.md Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
README.md Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
tsconfig.json Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00
yarn.lock Initial commit: Casio PX-330 editor (Nuxt 4 PWA + Web MIDI) 2026-09-14 18:23:32 -03:00

PX-330 Editor

A self-hosted, browser-based editor for the Casio Privia PX-330 digital piano. It talks to the instrument over Web MIDI + Casio SysEx (Individual Parameter Request / Send) using the coordinates from Casio's official MIDI Implementation, and works offline as a PWA.

Stack: Nuxt 4 · Nuxt UI v4 (Pug templates) · Pinia · @vite-pwa/nuxt.

Status

Early development. What exists today:

  • Researchdocs/research.md documents the PX-330's SysEx format, every parameter it exposes (master tuning, mixer, system chorus / reverb / acoustic resonance, brilliance, 48 parts, per-part tone / vibrato / LFO / DSP parameters, scale tune), the 48-part layout, tone numbering and what is not reachable over MIDI (registrations, rhythms, songs) — all verified against the hardware.
  • Protocol layerapp/lib/midi/casio.ts builds and parses IPR / IPS messages (7-bit packing, arrays, names); app/composables/useMidi.ts owns the Web MIDI connection, throttled parameter sends, requests with timeout / retry and applies every incoming value to the stores.
  • Layer & Split — the three parts the keyboard plays in one card: pick the tone of Upper 1, Upper 2 (the layer) and Lower 1 (the split) from a searchable browser of the 250 tones, set each one's octave, level, pan and mute, and dose the layer against the main tone with a balance that keeps the pair's loudness. Copy or swap parts, save a combination and recall it in one click (only those parts are sent, so the effects and tuning stay put), and re-apply it after the panel has overwritten a tone. Tones are written through the panel's own parameter, so the piano loads them the way its buttons do and the display follows.
  • Setup mode — the keyboard parts (Upper 1 / Upper 2 / Lower 1 / Harmonize): tone, enable, volume, pan, reverb / chorus / acoustic resonance sends, tuning, bend range, octave shift, level, touch sensitivity, vibrato and LFO offsets, and the tone's DSP effect with its parameters named per algorithm (Rotary, Drive Rotary, EQs, Enhancer, Distortion, Tremolo / Auto Pan, Early Reflection); system reverb, chorus, acoustic resonance, brilliance and master mixer; master tune / transpose and the two scale tune tables. Read from / send to the piano per scope, local library, JSON export / import, tracking of tone changes made on the panel.
  • Mixer mode — the eight accompaniment parts and the 16 MIDI parts: tone, enable, volume, pan, reverb and chorus sends.
  • App shell — MIDI connection badge, virtual keyboard (drives MIDI part C01 / C10), Drums and System placeholders.

Verified against the instrument: every parameter of both scopes reads back (287 + 1368 requests answered), a tone picked in the editor is loaded by the piano through the panel, and edits are applied live. Planned next: the Drums step sequencer with SMF export for the piano's Song mode, and the System page (device id, user song list).

Layer and Split are switched on and off from the panel — the piano exposes no parameter for them, nor for the split point (see docs/research.md).

Requirements

  • A Casio Privia PX-330 connected over USB (class-compliant, appears as CASIO USB-MIDI; the piano must be in normal mode, not USB storage mode).
  • A browser with Web MIDI + SysEx support: Chrome / Chromium / Edge, or Firefox with the MIDI permission granted.
  • A secure context: http://localhost works out of the box; when served from another host it must be over HTTPS.

Running

With Docker:

docker compose up
# http://localhost:7330 — set PORT in a .env file (see .env.example) to use another port

With a local Node.js (24+):

yarn
yarn dev        # dev server at http://localhost:3000
yarn lint       # eslint
yarn typecheck  # vue-tsc
yarn build      # production build (generates the PWA service worker/manifest)

The production build is a fully static SPA (ssr: false) — serve .output/public from any static host or reverse proxy (HTTPS required for Web MIDI outside localhost).

How it works

  • Parameter registry (app/lib/params/): every parameter is a declarative ParamDef (id, label, section, type, range / enum, default, display formatter and its SysEx coordinates: category, parameter set, block, parameter id, bit width, array index, bias). Components render parameters from their ids; the registry alone decides what is sent to the piano.
  • Tests: docs/testing.md — unit tests of the pure modules, an end-to-end run against a fake instrument, and one against the real piano.
  • State (Pinia): one store per editor document, all built on useParamState(registry), the single write funnel — every change goes through setParam(id, value), which coerces the value, persists it and, when MIDI is connected, emits the IPS.
  • MIDI (app/lib/midi/casio.ts, app/composables/useMidi.ts): pure protocol builders / parsers on one side, the Web MIDI connection on the other. Values received from the piano (replies and spontaneous sends) are applied to the stores with an echo guard.
  • Persistence (app/composables/usePatchStorage.ts): all localStorage access in one composable.

Reference documents

The SysEx coordinates, parameter ranges / enums and lists in this project were derived from Casio's official documentation:

  • PX-330 / AP-620 MIDI Implementation (Casio, 2009)
  • PX-330 User's Guide (tone list, drum assignment list, rhythm list)

The PDFs themselves are Casio's and are not redistributed in this repository (they live in the git-ignored ref/ directory).

This is an independent project and is not affiliated with or endorsed by CASIO COMPUTER CO., LTD. Privia is a trademark of Casio.