Eine schlanke Browser-Variante des Projekts: Tempo-Erkennung (BPM) mit
stabiler MIDI-Clock-Ausgabe (24 PPQN), optional auch die Grundtonart
(mit Paralleltonart). Ein Datei-Modus taktet eine geladene Audiodatei
driftfrei zur Wiedergabe (Offline-Beat-Map), ein Noten-Modus sendet
erkannte Tonhöhen direkt als MIDI-Noten (mono- oder polyphon). Als Quelle
dient ein Audio-Eingang oder die mitgehörte Wiedergabe
(Tab-/System-Audio). Keine Installation, kein Python, kein Server -- die ganze
App steckt in einer einzigen Datei: index.html.
Online ausprobieren: https://codekoch.github.io/AudioWizard/webapp/
- Lokal:
index.htmleinfach im Browser öffnen (Doppelklick im Datei-Explorer oder im BrowserStrg+O). Kein Server nötig. - Online: über den GitHub-Pages-Link oben (siehe unten „Veröffentlichung").
Dann:
- Quelle wählen: „Audio-Eingang" (Mikrofon/Line-In) oder „Wiedergabe mithören" (siehe Abschnitt unten). Bei „Audio-Eingang" zusätzlich „Eingänge laden" klicken und den Mikrofon-Zugriff erlauben – erst danach zeigt der Browser alle Eingänge mit Namen (Datenschutz) – und den gewünschten Eingang wählen.
- MIDI-Ausgang: die Liste öffnen (fragt den MIDI-Zugriff an) und einen Port wählen, z. B. „loopMIDI Port". „Kein MIDI" zeigt nur an.
- Optional BPM-Bereich anpassen (Standard 70–140) und über die Buttons „Tonart" bzw. „Akkord" die jeweilige Anzeige einblenden.
- Start drücken.
Die große Zahl zeigt das erkannte Tempo; die MIDI-Clock startet automatisch
mit der ersten stabilen Schätzung (MIDI start) und hält bei Stille an
(stop).
Tonart & Akkord (optional, parallel): Über „Tonart" wird die Grundtonart (mit Paralleltonart) eingeblendet, über „Akkord" zusätzlich der aktuell erkannte Akkord daneben (gröberer Eindruck aus dem Vollmix; unsichere Erkennung wird gedimmt). Sind beide aus, läuft nur die BPM-Erkennung – das spart die teure Chroma-FFT und gibt maximale Performance (wichtig auf Handy/Raspberry Pi).
Hold (Anzeige einfrieren): Der Button „Hold" friert BPM/Tonart/Akkord ein und lässt die MIDI-Clock konstant weiterlaufen – ideal für lange Breaks oder Übergänge, in denen die Live-Analyse sonst „abreißen" würde. Erneuter Klick setzt fort; die bisherige Tempo-/Tonart-Historie bleibt erhalten.
Über „Modus" stehen mehrere Betriebsarten zur Wahl: „Tempo & MIDI-Clock" (live, oben beschrieben), „Datei/Aufnahme → MIDI-Clock (driftfrei)", die Noten-Modi (monophon/polyphon/Akkorde) sowie der DJ-Modus (zwei Decks, Audio-Crossfade, Clock folgt) – alle siehe unten.
Statt live mitzuhören lässt sich eine Audiodatei laden und ihre MIDI-Clock driftfrei zur Wiedergabe ausgeben – ideal, wenn man zu einem fertigen Track einen Drumcomputer/Sequenzer/Arpeggiator dauerhaft synchron laufen lassen will.
So geht's: Modus auf „Datei/Aufnahme → MIDI-Clock (driftfrei)" stellen, mit „Datei wählen…" eine Audiodatei laden (oder per „Aufnehmen" mitschneiden, siehe unten), MIDI-Ausgang wählen und „Abspielen & senden" drücken. Das Audio wird hörbar abgespielt; Pegel, Position und Momentantempo werden angezeigt.
Aufnehmen statt laden: Audio lässt sich auch direkt aufnehmen und dann wie eine Datei analysieren – so bekommt man auch ohne Datei (z. B. von einem Stream) eine stabile Clock. Ablauf:
- Quelle wählen (oben „Quelle"): „Wiedergabe mithören" (Tab/System) oder „Audio-Eingang" (Mikrofon/Line-In – Gerät über „Eingänge laden" wählen).
- „Quelle bereitstellen" – bei „Mithören" erscheint vor der Aufnahme der Freigabe-Dialog, in dem Inhalt/Tab gewählt wird („Systemaudio/Tab-Audio teilen" ankreuzen).
- „● Start" / „■ Stopp" – Aufnahme manuell starten und beenden. Danach wird sie automatisch analysiert (Beat-Map) und ist abspielbar.
Schon ab „Quelle bereitstellen" und während der Aufnahme laufen Pegel, BPM und Tonart live mit (dieselbe Analyse wie im Clock-Modus, nur ohne MIDI) – so sieht man sofort, ob Audio ankommt und was erkannt wird.
Speichern (mit Namensvorschlag): Nach der Aufnahme öffnet „Speichern…"
ein Panel. Die Aufnahme wird automatisch in Stücke zerlegt (Indiz: kurze
Stille + BPM/Tonart-Wechsel); jedes Stück erscheint mit Start–Ende, Dauer,
BPM und Tonart und einem frei editierbaren Dateinamen – vorbelegt aus
BPM + Tonart (z. B. 120BPM_C_Dur). Unsichere Grenzen sind gedimmt
markiert. Du kannst jedes Stück einzeln oder „Alle speichern", alles „Als
ein Stück" zusammenfassen oder „Nach Zeit trennen…" (feste
Minuten-Abstände). Format WAV (auch je Stück) oder WebM-Original (klein,
aber nur die ganze Aufnahme, da komprimierte Streams nicht verlustfrei
geschnitten werden können). Der Speichern-Dialog erlaubt freie Namens-/Ortswahl
(Chrome/Edge); „Alle speichern" (WAV) lässt einmal einen Ordner wählen
und legt alle Stücke dort ab. Der zuletzt genutzte Ordner wird gemerkt und
beim nächsten Speichern wieder vorgeschlagen.
Aufnahme/Mithören gibt es nur, wo der Browser es unterstützt (Windows/Chrome/Edge mit Systemaudio, sonst Tab-Audio bzw. Audio-Eingang); auf Android/Mobil ist die Aufnahme deaktiviert.
- Einmalige Offline-Analyse: Die Datei wird dekodiert und vorab zu einer Beat-Map analysiert (Onset-Hüllkurve → globales Tempo → lokale Tempokurve → DP-Beat-Tracking), mit Fortschrittsanzeige. Das passiert nur einmal beim Laden, nicht während der Wiedergabe.
- Driftfreie Clock: Jeder 24-PPQN-Tick wird gegen die laufende Web-Audio-
Wiedergabe terminiert (Audio-Kontextzeit →
performance.now()pergetOutputTimestamp(), als MIDI-Zeitstempel ausgegeben). Es gibt keine zweite, unabhängige Uhr mehr, deren Fehler sich aufsummieren könnte – die Clock bleibt dauerhaft am Song. - Konstant vs. variabel – automatisch: Konstantes Tempo (≤1,5 % Streuung) ergibt ein mathematisch perfektes Raster; bei variablem Tempo folgt die Clock den gemessenen Beat-Abständen. Der Status zeigt an, welcher Fall erkannt wurde.
- Robust: Sub-Frame-genaue Beat-Verfeinerung, oktav-fester Tempo-Prior (kein Halb-/Doppeltempo-Fehler), „24 Ticks pro Viertel" überbrücken einen übersprungenen Beat (kein kurzes Halbtempo), robuste Tempo-Anzeige.
- MIDI optional: Vorhören geht auch ohne MIDI-Ausgang. „MIDI Start/Stop ·
senden" setzt – wenn aktiv – den
startauf den ersten Beat (undstopam Ende). Der BPM-Bereich steuert die Analyse; ändert man ihn, wird die geladene Datei automatisch neu analysiert.
Im Datei-Modus werden Quelle, Audio-Eingang und Tonart ausgeblendet (sie sind hier ohne Funktion). Grenze: groove-genau, nicht sample-genau – es bleibt die übliche MIDI-Quantisierung von rund 1 ms. Den Tab im Vordergrund lassen.
Über „Modus" lässt sich von „Tempo & MIDI-Clock" auf einen Noten-Modus umschalten, der erkannte Tonhöhen direkt als MIDI-Noten (Note On/Off) an den gewählten Ausgang sendet. In diesem Modus laufen BPM-/Tonart-/Clock- Schritte bewusst nicht mit – für möglichst geringe Latenz.
- Monophon: erkennt jeweils EINE Note (Gesang, Bass, Lead, einzelnes Instrument, Pfeifen) per YIN-Tonhöhenerkennung. Geringe Latenz, gute Treffsicherheit – braucht aber eine klar einstimmige Quelle.
- Polyphon: erkennt mehrere Noten gleichzeitig per harmonischer Salienz-Analyse mit iterativer Oberton-Auslöschung – die stärkste Note wird erkannt, ihre Obertonreihe aus dem Spektrum entfernt und neu gesucht, damit Obertöne (z. B. bei Gitarre) nicht als eigene Noten auftauchen. Etwas höhere Latenz und begrenzte Genauigkeit; bei dichter Musik ein grober Eindruck. Es werden alle erkannten Töne einzeln gesendet – auch Fehlerkennungen. Wer saubere Akkorde triggern will, nimmt den Akkord-Modus.
- Akkorde: erkennt aus dem Klang den wahrscheinlichsten Akkord und sendet ihn als sauberes MIDI-Voicing – ideal, um z. B. mit einer Gitarre MIDI-Akkorde zu triggern. Aus dem Spektrum wird ein Chroma (12 Tonklassen) gebildet und per Template-Matching (Cosinus-Ähnlichkeit gegen Dur-, Moll-, 7-, maj7-, m7-, sus- und dim/aug-Vorlagen, Grundton-Gewichtung) klassifiziert; ein Mehrheits-/Abstandskriterium verwirft Unklares. Töne, die nicht zum Akkord gehören (meist Fehlerkennungen), fallen weg – gesendet werden nur die Akkordtöne, als Grundstellung in der gespielten Lage. Der Akkord wird gehalten, bis sicher ein anderer erkannt wird oder es still wird (kein Geflacker). Angezeigt wird der Akkordname groß und darunter klein/grau in Klammern die gesendeten Noten (z. B. „E" mit „(E2 G#2 B2)").
Velocity wird aus dem Pegel abgeleitet, gesendet wird auf MIDI-Kanal 1. Beim Stoppen/Umschalten werden alle offenen Noten beendet (Note Off).
Eine gehaltene Note bleibt über das Ausklingen stehen (Pegel-Hysterese + entprelltes Note-Off), statt bei jedem kurzen Erkennungsaussetzer neu getriggert zu werden. Mit „Oktave ±" lassen sich die erkannten Töne für die MIDI-Ausgabe um ganze Oktaven nach oben/unten verschieben (z. B. eine tief gespielte Bassline eine Oktave höher an einen Synth schicken).
In den Noten-/Akkord-Modi blendet „Kalibrierung" ein Panel mit Schiebe- reglern ein, die sofort (auch während des Spielens) wirken – ideal, um das Tracking auf das eigene Instrument einzustellen, z. B. eine Gitarre an einen monophonen Synth:
- Latenz (Audioblock): Größe des Audioblocks (256 / 512 / 1024 / 2048 Samples ≈ 6 / 12 / 23 / 46 ms). Kleiner = schnellere Reaktion zwischen Spiel und gesendeter MIDI-Note, aber mehr CPU; sehr kleine Werte können das Tracking unruhiger machen. Das Tonhöhen-Fenster bleibt davon unberührt, die Erkennungsqualität sinkt also nicht – nur die Eingangs-Latenz. Standard 512 (mono/poly) bzw. 1024 (Akkorde, etwas stabiler).
- Anschlag-Schwelle: ab welchem Pegel eine neue Note/ein Akkord startet (gegen Nebengeräusche/Übersprechen hochsetzen, für leises Spiel runter).
- Halte-Schwelle: wie weit ein ausklingender Ton fallen darf, bevor er losgelassen wird (mono/Akkord).
- Note-Aus-Verzögerung: wie viele leise Frames bis zum Note-Off – klein = knackiger/kürzer, groß = klebt länger (gut gegen Zappeln beim Ausklingen).
- YIN-Schwelle (nur mono): Strenge der Tonhöhenerkennung – kleiner = strenger (weniger Oktavfehler, aber verpasst evtl. leise Töne).
- Wechsel-Reaktion: wie schnell auf einen neuen Ton/Akkord umgeschaltet wird – 1 = sofort (geringste Latenz, aber empfindlicher), höher = stabiler.
Die Regler-Werte zeigen neben dem Frame-Wert die ungefähre Zeit in Millisekunden (abhängig von der gewählten Latenz). „Zurücksetzen" stellt die für den Modus sinnvollen Standardwerte wieder her.
Über „Modus" → „DJ (2 Decks, Clock folgt)" lassen sich zwei Tracks nebeneinander laden und mischen – die MIDI-Clock folgt automatisch dem Track, zu dem übergeblendet wird.
- Laden & analysieren: Mit „Datei A…" und „Datei B…" je eine Audiodatei laden. Jedes Deck wird – wie der Datei-Modus – einmalig offline zu einer Beat-Map analysiert (BPM + Tonart werden angezeigt). Das geht auch, während das andere Deck schon läuft.
- Abspielen & faden: Je Deck mit ▶ starten (beide können gleichzeitig laufen). Übergeblendet wird mit dem Crossfader, den Tasten „◀ A"/„B ▶" oder per Klick auf ein Deck – das Audio wird (gleiche Leistung, equal-power) hörbar überblendet.
- Clock folgt: Die MIDI-Clock taktet driftfrei den Track, zu dem geblendet wird (ihre 24-PPQN-Ticks werden gegen dessen Wiedergabeposition terminiert). Sobald ein Deck dominiert (Crossfader über der Mitte), übernimmt die Clock dessen Tempo – das angeschlossene Gerät läuft also synchron zum gerade gehörten Track. Ohne „Sync" springt das Tempo beim Wechsel auf das neue Songtempo; mit „Sync" (siehe unten) bleibt es konstant.
- EQ-Isolator: Je Deck lassen sich Bass / Mitte / Höhen über drei
senkrechte Slider stufenlos regeln (von +6 dB bis praktisch aus –
z. B. den Bass herunterziehen, während übergeblendet wird; der aktuelle
dB-Wert steht klein über dem Fader, Doppelklick setzt auf 0 dB zurück).
Das ist schlanke
Frequenzfilterung (native
BiquadFilterNode-Kette), kein echtes Heraustrennen einzelner Instrumente. - Sync (Tempo-Match): Per „Sync" rastet ein Deck tonhöhen-erhaltend auf das Tempo des anderen Decks ein (mit Beat-Phasen-Ausrichtung). Die Clock bleibt dann beim Überblenden konstant. Die Zeitdehnung läuft in Echtzeit (WSOLA als AudioWorklet) und wirkt sofort – ohne Vorberechnung.
- Übergang (Tempo-Glide): Mit „Übergang" gleitet ein Deck vom Master-Tempo allmählich auf sein Eigentempo – die Dehnungsrate wird live gerampt, und die MIDI-Clock gleitet automatisch mit.
Tipp: Den BPM-Bereich vor dem Laden grob passend setzen (steuert die Analyse). Den Tab im Vordergrund lassen.
Statt eines Mikrofons lässt sich auch die laufende Wiedergabe analysieren
(z. B. was gerade in Spotify spielt). Quelle auf „Wiedergabe mithören"
stellen und Start drücken – dann erscheint der Freigabe-Dialog des
Browsers (Screen-Capture API, getDisplayMedia):
- Windows, Chrome/Edge: „Gesamter Bildschirm" wählen und unten „Systemaudio teilen" ankreuzen → die komplette Systemausgabe wird mitgehört (auch Desktop-Apps wie Spotify). Alternativ einen Tab wählen und „Tab-Audio teilen" ankreuzen (z. B. den Spotify-Web-Player).
- macOS: System-Audio ist hier nicht erfassbar – nur Tab-Audio (Spotify/YouTube als Browser-Tab). Safari unterstützt es nicht.
- Android/Mobil: nicht möglich – mobile Browser stellen
getDisplayMedianicht bereit. Die Option wird dort automatisch deaktiviert; als Quelle bleibt nur das Mikrofon. (Der Noten-Modus monophon funktioniert auf Android mit dem Mikrofon.)
Wichtig: Das Audio-Häkchen muss aktiv sein, sonst kommt kein Ton an (die App weist dann darauf hin). Beendet man die Freigabe über die Browser-Leiste, stoppt die Sitzung automatisch. Die Wiedergabe ist weiterhin normal hörbar.
- Browser mit Web MIDI: Chrome, Edge oder Opera (Chromium). Firefox unterstützt Web MIDI nur mit Erweiterung; Safari unterstützt es nicht – dort gibt es keine MIDI-Ausgabe (Anzeige funktioniert trotzdem).
- Virtueller MIDI-Port, um eine DAW/Hardware auf demselben Rechner zu
erreichen: Windows
loopMIDI,
macOS der IAC-Treiber (Audio-MIDI-Setup), Linux ALSA/
snd-virmidi. Ein USB-MIDI-Interface geht direkt.
Jeder Clock-Tick wird mit output.send([0xF8], zeitstempel) im Voraus
geplant – der Zeitstempel liegt in der performance.now()-Domäne, und das
MIDI-Subsystem des Browsers/Betriebssystems gibt den Tick dann zeitgenau aus.
Die Tick-Stabilität hängt damit nicht am (ungenauen) JavaScript-Timer,
sondern an der OS-MIDI-Schicht – derselbe Gedanke wie bei CoreMIDI auf dem
Mac. Ein Lookahead-Scheduler füllt die Tick-Warteschlange laufend ein Stück
in die Zukunft. Tempoänderungen werden mit Totband (gegen Mess-Zittern) und
begrenzter Slew-Rate sanft nachgeführt – kein Tick-Burst.
Beat-Sync gegen Drift (optional): Ohne Sync läuft die Clock im geschätzten Tempo – das liegt aber oft minimal daneben (z. B. 120,1 statt 120 BPM), wodurch sie nach einigen Takten hörbar vom Song wegdriftet. Mit aktivem „Beat-Sync" (Standard an, in den Steuerelementen abschaltbar) wird die Clock laufend auf das erkannte Beat-Raster nachgeführt:
- Aus einer Phasenfaltung der Onset-Hüllkurve eng ums geschätzte Tempo wird – über das ganze Analysefenster – die echte Beat-Periode und -Phase sehr genau bestimmt (gemessen <0,03 % Tempofehler bei klarem Beat); diese Periode dient als Clock-Rate, sodass kaum noch Drift entsteht.
- Zusätzlich wird der Beat-Tick (Tick 1 von 24) mit max. wenigen Millisekunden pro Beat sanft auf das Raster nachgezogen (Phasenregelung), was Restdrift laufend ausgleicht. Das Einrasten dauert nach dem Start ein paar Sekunden.
Eingerastet wird nur bei deutlichem, kohärentem Beat – bei undeutlichem Rhythmus läuft die Clock einfach im zuletzt gemessenen Tempo frei weiter (kein Reißen). Wer das nicht will (oder ungewöhnliches Material hat), schaltet „Beat-Sync" ab; dann läuft die Clock wie zuvor im geglätteten Schätztempo.
MIDI Start/Stop (Option): Standardmäßig sendet die App kein Start/Stop, sondern nur durchgehende Clock-Pulse – du startest dein Gerät selbst (auf den gewünschten Taktanfang), die Clock hält dann das Timing. Wer das klassische Verhalten will (Start mit der ersten Tempo-Schätzung, Stop bei Stille), hakt „MIDI Start/Stop · senden" an.
Tipp: Den Tab im Vordergrund lassen. Hintergrund-Tabs werden vom Browser gedrosselt; durch den Lookahead bleibt die Clock zwar eine Weile stabil, für den Live-Betrieb sollte der Tab aber sichtbar bleiben.
Über den Button „Tonart" lässt sich die erkannte Grundtonart mit Paralleltonart einblenden (z. B. „C Dur (A Moll)"). Die Erkennung ist aus dem Python-Kern portiert: Sha'ath-Profile, Bass-Evidenz zur Unterscheidung von Dur und Mollparallele, zweistufige Mittelung mit Hysterese; unsichere Erkennung wird gedimmt angezeigt. Das Chroma stammt aus einer (für den Bass extra hochaufgelösten) STFT statt der CQT des Python-Projekts.
ScriptProcessorNodestattAudioWorklet: Der Worklet lädt ein Modul nach, was der Browser unterfile://(Origin „null") blockiert. Der ScriptProcessor lädt nichts nach und läuft daher auch beim direkten Öffnen der Datei. Etwas älter/deprecated, für diese leichte Analyse aber völlig ausreichend; die MIDI-Clock ist davon ohnehin unabhängig.- MIDI-Clock-Timer im Hauptthread (kein Blob-Worker – der wäre unter
file://ebenfalls gesperrt). Tab sichtbar lassen.
- Kürzere Geräteliste: Der Browser zeigt eine logische Eingangsliste – einen Eintrag pro echtem Gerät. Die Python-App (PortAudio) listet dasselbe Interface mehrfach (MME, DirectSound, WASAPI, WDM-KS). Namen erscheinen erst nach der Mikrofon-Freigabe („Eingänge laden").
- Mithören der Wiedergabe ist möglich, aber über die Screen-Capture-API (siehe oben) statt eines WASAPI-Loopback-Geräts: Es muss pro Sitzung im Browser-Dialog freigegeben werden, und vollständiges System-Audio gibt es nur unter Windows (Chrome/Edge). Unter macOS nur Tab-Audio.
- Vereinfachte Analyse: Spektralfluss-Onset-Hüllkurve statt HPSS; Tonart aus STFT-Chroma statt CQT (etwas weniger treffsicher, vor allem bei der Dur/Moll-Unterscheidung). Eine separate Akkord-/HMM-Analyse wie im Python-Kern gibt es nicht; im Noten-Modus (polyphon) wird aus den erkannten Tönen lediglich ein Akkordname abgeleitet. Beat-Sync gibt es live als Phasenkopplung der Clock und im Datei-Modus als volle Offline-Beat-Map.
- Teste die Webversion direkt unter https://codekoch.github.io/AudioWizard/webapp/
