No description
  • JavaScript 84.7%
  • CSS 11.7%
  • HTML 2.7%
  • Python 0.6%
  • Shell 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jonas 70a73db0a0 WIP: Sicherungsstand vom 27.09.2026
Uncommittete Änderungen gesichert (Sammel-Commit), damit der Stand auf
Forgejo liegt — ggf. noch halbfertige Arbeit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nis4Pzds5rZXdAQ8VBxKqP
2026-09-27 00:00:59 +00:00
deploy Review-Fixes Server: Backup gerettet, Verlängern öffnet den Code 2026-08-27 20:53:33 +00:00
public WIP: Sicherungsstand vom 27.09.2026 2026-09-27 00:00:59 +00:00
server Filmclips pro Klasse, Admin-Panel breiter, Namens-Ellipse repariert 2026-09-06 23:57:04 +00:00
tools WIP: Sicherungsstand vom 27.09.2026 2026-09-27 00:00:59 +00:00
.gitignore node_modules-Symlink aus dem Repo entfernt, .gitignore fängt auch Symlinks 2026-09-05 07:10:06 +00:00
package-lock.json Favicon in allen Größen und Playwright für UI-Checks 2026-08-03 21:03:28 +00:00
package.json Favicon in allen Größen und Playwright für UI-Checks 2026-08-03 21:03:28 +00:00
README.md V13: Aufnahmen sitzen auch mit Bluetooth-Kopfhörern auf dem Beat 2026-08-27 20:30:01 +00:00
SPEC-V2.md Initial commit: Dawtastic Mini-DAW 2026-07-15 21:26:53 +00:00
SPEC-V3.md Initial commit: Dawtastic Mini-DAW 2026-07-15 21:26:53 +00:00
SPEC-V4.md Initial commit: Dawtastic Mini-DAW 2026-07-15 21:26:53 +00:00
SPEC-V5.md Initial commit: Dawtastic Mini-DAW 2026-07-15 21:26:53 +00:00
SPEC-V6.md Initial commit: Dawtastic Mini-DAW 2026-07-15 21:26:53 +00:00
SPEC.md Filmclips pro Klasse, Admin-Panel breiter, Namens-Ellipse repariert 2026-09-06 23:57:04 +00:00

Dawtastic — Mini-DAW für den Musikunterricht

Eine kleine Web-DAW für Schul-iPads und Desktop-Browser. Schüler legen ein Projekt an und bekommen eine eindeutige Projekt-URL (/p/<token>) — das ist ihr einziger „Login“. Alles wird automatisch auf dem Server gespeichert.

Setup

Voraussetzung: Node.js ≥ 22 (wegen des eingebauten node:sqlite).

cd /var/www/dawtastic
npm install
npm start

Der Server läuft danach auf Port 3007 (änderbar über die Umgebungsvariable PORT):

PORT=8080 npm start

Beim ersten Start wird das Verzeichnis data/ automatisch angelegt, darin:

  • data/dawtastic.sqlite — Datenbank (Projekte + Audio-Metadaten)
  • data/audio/<token>/… — hochgeladene Audiodateien
  • data/config.json — hier steht das generierte Admin-Passwort

Admin-Panel

Unter /admin erreichbar. Das Passwort findest du in data/config.json (Feld adminPassword, wird beim ersten Start automatisch generiert).

Im Admin-Panel kannst du:

  • alle Projekte sehen (Name, URL, Größe, letzte Änderung)
  • Projekt-URLs sperren/entsperren (gesperrte Schüler sehen eine Hinweisseite)
  • Projekte löschen (inkl. aller Audiodateien)

Betrieb hinter Nginx

Eine Beispiel-Konfiguration liegt in deploy/nginx.example.conf (Reverse Proxy auf 127.0.0.1:3007, client_max_body_size 60m für Audio-Uploads). Kopiere sie nach /etc/nginx/sites-available/, passe Domain und Zertifikate an und aktiviere sie. Nicht unverändert übernehmen.

Module

  • Steps — Step-Sequencer: bis zu 8 Spuren, 1/2/4 Takte, Swing, Built-in-Drumsounds oder eigene Aufnahmen pro Spur.
  • Sampler — 8 Pads zum Antippen: eigene Aufnahmen oder Dateien importieren, trimmen, pitchen, Lautstärke einstellen.
  • Recorder — Audiospuren aufnehmen und mit Offset/Lautstärke zu einem Mini-Arrangement zusammensetzen.

Neue Module lassen sich leicht ergänzen: eine Datei in public/js/modules/ mit dem Standard-Interface ({ id, title, mount(rootEl, ctx), unmount() }) anlegen und in public/js/shell.js in die modules-Liste eintragen.

Built-in-Sounds neu erzeugen

node tools/gen-sounds.mjs

Erzeugt die 8 Drumsounds (Kick, Snare, Clap, Hi-Hat, Open-Hat, Tom, Rim, Shaker) als WAV-Dateien in public/sounds/.

Diagnose-Werkzeuge (Audio)

Nicht verlinkt, für Schüler unsichtbar — bei Audio-Problemen aber Gold wert:

  • /audiotest.html — spielt dreimal denselben Ton über den neutralen Signalweg (Master → Limiter) und misst die Spitzenpegel im Graphen. Zeigt außerdem, wie lange resume() braucht und wann die Audio-Uhr wirklich losläuft.
  • /chaintest.html — baut jeden Knotentyp einzeln in einem eigenen frischen AudioContext und vergleicht den ersten Ton mit den folgenden. Damit wurde gefunden, dass ein frischer DynamicsCompressor das erste Signal, das je durch ihn läuft, auf 44 % dämpft (auch im Bypass) — seitdem liegt er in fxchain.js parallel und stumm, solange er aus ist.
  • ?audiodbg=1 an der Projekt-URL — Overlay in der laufenden App: je Note die benutzten Werte (Pegel = Anschlag × Verstärkung, Attack, Rate) und die gemessenen Pegel an Quelle, Ketten-Eingang, Spur-Ausgang und Master.

Timing und Latenz (Bluetooth-Kopfhörer)

Kopfhörer geben den Ton verzögert aus — per Bluetooth 100–300 ms. Wer „auf das Gehörte" spielt, landet dann systematisch hinter dem Raster. Dagegen gibt es zwei Stufen:

  1. Automatisch: engine.outputLatencySec() liest AudioContext.outputLatency (Rückfall: baseLatency) bei jedem Zugriff frisch — der Wert springt, sobald ein Bluetooth-Gerät verbunden wird. Er verzögert Playhead, Steps-Lauflicht und Video-Sync auf den Hör-Zeitpunkt.
  2. Gemessen (Tap-Test): Der Knopf „Timing" in der Klaviatur-Leiste öffnet latcal.js: Metronom auf der Audio-Uhr, Schüler tippt mit, Median aus ≥ 8 Treffern = Ausgabe- + Touch-Latenz. engine.recordAheadSec() zieht diesen Wert von jedem Einspiel-Stempel ab. Für Bluetooth ist das der einzig verlässliche Weg — ob iOS-Safari die echte BT-Latenz in outputLatency durchreicht, ist offen, und ein Mikrofon-Loopback hört Kopfhörer nicht.

Gespeichert wird pro Gerät in localStorage (dawtastic-lat-play): Der Versatz gehört zu iPad + Kopfhörer, nicht zum Schüler. Ein Wechsel des Ausgabegeräts (devicechange oder ein Sprung im API-Wert) markiert die Messung als veraltet.

Session-Aufnahmen brauchen keine Messung: captureStart() legt einen unhörbaren 1-kHz-Marker in den Aufnahmezweig, der beim Ablegen wiedergefunden wird (findSyncMarkerSec) — das verortet den Take samplegenau und liefert nebenbei die MediaRecorder-Anlaufzeit des Geräts.

/audiotest.html protokolliert outputLatency live mit — zum Prüfen einfach während des Tests einen Bluetooth-Kopfhörer verbinden und trennen.

Sicherung

deploy/backup.sh macht einen konsistenten SQLite-Online-Snapshot und spiegelt data/ per rsync; deploy/dawtastic-backup.timer startet das täglich um 02:30. Standardziel ist /var/backups/dawtastic — das liegt auf derselben Platte und schützt damit nur gegen versehentliches Löschen und DB-Schäden. Gegen einen Plattenausfall hilft nur ein anderes Ziel: sudo DEST_DIR=/mnt/nas/dawtastic bash deploy/backup.sh (bzw. DEST_DIR in der Service-Unit setzen).

Technik

  • Kein Framework, kein Build-Schritt, keine CDNs — Vanilla-ES-Module.
  • Backend: Express + node:sqlite (einzige npm-Dependency: express).
  • Audio: Web Audio API, Aufnahme über MediaRecorder (Safari: audio/mp4, Chrome/Firefox: audio/webm).