Song: Routing der Tracks per Graph #350

Closed
opened 2026-10-07 19:36:24 +02:00 by meleki · 2 comments
Owner

Im Song bestimmt ein Graph, wohin die Tracks fließen. Jeder Track ist ein Node, dazu gibt es einen festen Node Output. Das ist der Song-Master, den es heute schon gibt: Im Editor ist es der Bus des Songs, im Spiel der Master der Wiedergabe. Von dort geht der Ton weiter an den Bus des Songs (#325).

Ein Track-Node nimmt mehrere Eingänge an (andere Tracks) und kann an mehrere Ziele gehen. Ein neuer Track hängt von Anfang an am Output.

Entscheidungen

1. Wo ist der Graph zu sehen? Im Song-Tab gibt es oben einen Umschalter Timeline | Routing. Das ist derselbe Graph-Editor wie bei Sound FX, mit Zoom, Snap und Undo.

2. Pegel pro Verbindung (Send). Jede Verbindung hat im Inspector ein eigenes Volume (dB, Standard 0 dB) und einen Mode, der sagt, wo im Track abgegriffen wird:

Mode Abgriff
Post volume (Post pan) nach FX, Volume und Pan. Standard, so klingt ein Song wie bisher
Pre volume (Post FX) nach dem FX, vor Volume und Pan
Pre volume (Pre FX) direkt am Eingang, vor dem FX

3. Track ohne Ausgang: Er ist stumm, und der Node zeigt eine Warnung „goes nowhere“. Was im Graph steht, ist das, was man hört.

4. Solo bei verketteten Tracks (A geht in B, B in den Output): Solo auf A lässt A hören. B reicht A durch, die eigenen Items von B bleiben stumm. Tracks, die in A gehen, klingen mit.

Weitere Festlegungen

  • Track-Nodes kommen und gehen mit den Tracks. Im Graph kann man sie weder anlegen noch löschen. Der Name kommt vom Track, Volume, Pan und FX bleiben im Track-Kopf.
  • Den Output gibt es genau einmal, man kann ihn nicht löschen.
  • Mute auf einem Track macht alles stumm, was durch ihn läuft: das, was hineinfließt, und jeden Send, auch die vor Volume oder FX.
  • Schleifen sind verboten. Eine Verbindung, die eine Schleife schließen würde, lässt der Editor nicht zu.
  • Alte Songs haben keinen Graph. Beim Laden gehen dort alle Tracks an den Output, ohne Migration.
  • Laufzeitausgleich pro Verbindung: Hängt auf einem Weg ein Pitch-Shifter (2048 Samples Verzögerung) und auf einem anderen nicht, wird der kürzere Weg verzögert. Ein Send vor dem FX läuft am Shifter vorbei und wird ebenfalls angeglichen. So kommt alles gleichzeitig am Output an, ohne Kammfilter.
  • Pattern-Items mit eigenem FX gehen wie heute in ihren Track.
  • Im Spiel gilt dasselbe Routing wie im Editor.

Technischer Plan

  1. Modell: Der Song bekommt einen graph (wie das Instrument) mit den Node-Typen Track und Output. Eine Verbindung trägt Volume und Mode. Beim Laden und bei jeder Änderung der Tracks gleicht eine reine Funktion den Graph an: ein Node je Track, genau ein Output, neue Tracks am Output, Kanten zu fehlenden Tracks fallen weg.
  2. Rechnung (rein, core/music):
    • welche Sends es gibt, mit Gain und Abgriff
    • Mute/Solo als Tor am Eingang und als Tor für die eigenen Items
    • Ankunftszeit je Bus und Verzögerung je Send für den Laufzeitausgleich
  3. SoundLibrary: Ein Bus kann statt eines Ziels (into) mehrere Sends haben, jeder mit Gain, Abgriff und Delay. busLatency rechnet über die Sends. Die Projekt-Busse aus #325 bleiben bei einem Ziel.
  4. Song-Tab: Umschalter Timeline | Routing, Routing über den Graph-Editor. Im Inspector Volume und Mode der gewählten Verbindung. Warnung am Track ohne Ausgang.
  5. Tests: Unit-Tests für Angleichen, Sends, Solo/Mute und Ausgleich, je mit Gegenprobe. Dazu ein e2e-Check im Song-Modul.
Im Song bestimmt ein Graph, wohin die Tracks fließen. Jeder Track ist ein Node, dazu gibt es einen festen Node **Output**. Das ist der Song-Master, den es heute schon gibt: Im Editor ist es der Bus des Songs, im Spiel der Master der Wiedergabe. Von dort geht der Ton weiter an den Bus des Songs (#325). Ein Track-Node nimmt mehrere Eingänge an (andere Tracks) und kann an mehrere Ziele gehen. Ein neuer Track hängt von Anfang an am Output. ## Entscheidungen **1. Wo ist der Graph zu sehen?** Im Song-Tab gibt es oben einen Umschalter *Timeline | Routing*. Das ist derselbe Graph-Editor wie bei Sound FX, mit Zoom, Snap und Undo. **2. Pegel pro Verbindung (Send).** Jede Verbindung hat im Inspector ein eigenes **Volume** (dB, Standard 0 dB) und einen **Mode**, der sagt, wo im Track abgegriffen wird: | Mode | Abgriff | |---|---| | *Post volume (Post pan)* | nach FX, Volume und Pan. **Standard**, so klingt ein Song wie bisher | | *Pre volume (Post FX)* | nach dem FX, vor Volume und Pan | | *Pre volume (Pre FX)* | direkt am Eingang, vor dem FX | **3. Track ohne Ausgang:** Er ist stumm, und der Node zeigt eine Warnung „goes nowhere“. Was im Graph steht, ist das, was man hört. **4. Solo bei verketteten Tracks** (A geht in B, B in den Output): Solo auf A lässt A hören. B reicht A durch, die eigenen Items von B bleiben stumm. Tracks, die in A gehen, klingen mit. ## Weitere Festlegungen - Track-Nodes kommen und gehen mit den Tracks. Im Graph kann man sie weder anlegen noch löschen. Der Name kommt vom Track, Volume, Pan und FX bleiben im Track-Kopf. - Den Output gibt es genau einmal, man kann ihn nicht löschen. - **Mute** auf einem Track macht alles stumm, was durch ihn läuft: das, was hineinfließt, und jeden Send, auch die vor Volume oder FX. - **Schleifen sind verboten.** Eine Verbindung, die eine Schleife schließen würde, lässt der Editor nicht zu. - **Alte Songs** haben keinen Graph. Beim Laden gehen dort alle Tracks an den Output, ohne Migration. - **Laufzeitausgleich pro Verbindung:** Hängt auf einem Weg ein Pitch-Shifter (2048 Samples Verzögerung) und auf einem anderen nicht, wird der kürzere Weg verzögert. Ein Send vor dem FX läuft am Shifter vorbei und wird ebenfalls angeglichen. So kommt alles gleichzeitig am Output an, ohne Kammfilter. - Pattern-Items mit eigenem FX gehen wie heute in ihren Track. - **Im Spiel** gilt dasselbe Routing wie im Editor. ## Technischer Plan 1. **Modell:** Der Song bekommt einen `graph` (wie das Instrument) mit den Node-Typen *Track* und *Output*. Eine Verbindung trägt Volume und Mode. Beim Laden und bei jeder Änderung der Tracks gleicht eine reine Funktion den Graph an: ein Node je Track, genau ein Output, neue Tracks am Output, Kanten zu fehlenden Tracks fallen weg. 2. **Rechnung (rein, `core/music`):** - welche Sends es gibt, mit Gain und Abgriff - Mute/Solo als Tor am Eingang und als Tor für die eigenen Items - Ankunftszeit je Bus und Verzögerung je Send für den Laufzeitausgleich 3. **SoundLibrary:** Ein Bus kann statt eines Ziels (`into`) mehrere Sends haben, jeder mit Gain, Abgriff und Delay. `busLatency` rechnet über die Sends. Die Projekt-Busse aus #325 bleiben bei einem Ziel. 4. **Song-Tab:** Umschalter *Timeline | Routing*, Routing über den Graph-Editor. Im Inspector Volume und Mode der gewählten Verbindung. Warnung am Track ohne Ausgang. 5. **Tests:** Unit-Tests für Angleichen, Sends, Solo/Mute und Ausgleich, je mit Gegenprobe. Dazu ein e2e-Check im Song-Modul.
Author
Owner

Erledigt mit daeffe0, Wiki: Songs (Abschnitt Routing), Wiki-Commit b065d62.

Was gebaut ist

  • Song-Tab: Umschalter Timeline | Routing im Kopf. Routing ist der Graph-Editor wie bei Sound FX: ein Node pro Track (Name vom Track) und ein fester Node Output (der Song-Master, von dort weiter an den Bus des Songs aus #325).
  • Verbindungen: Ein Track nimmt beliebig viele Eingänge an und geht an beliebig viele Ziele. Ein neuer Track hängt am Output, alte Songs bekommen beim Laden dieselbe Grundverdrahtung.
  • Pegel je Verbindung (2b): Eine gewählte Verbindung zeigt im Inspector Volume (-60 bis +12 dB, Standard 0) und Mode: Post volume (Post pan) (Standard), Pre volume (Post FX), Pre volume (Pre FX).
  • Schleifen lehnt der Editor schon beim Ziehen ab, beim Laden fallen sie weg.
  • Track-Nodes kommen und gehen mit den Tracks. Delete im Graph nimmt nur Verbindungen.
  • Track ohne Ausgang (3a): stumm, der Node zeigt Goes nowhere.
  • Mute und Solo (4a) wirken auf die Verbindungen:
    • Mute macht alles stumm, was durch den Track läuft, auf jedem Abgriff.
    • Solo auf A, A geht in B: B reicht A durch, die eigenen Items von B bleiben stumm. Tracks, die in A gehen, klingen mit.
    • Geht ein Track in den gesoloten Track und in den Output, hört man ihn nur über den gesoloten Track (der Fall aus dem Screenshot mit Pitch FX).
  • Laufzeitausgleich: Jeder Weg eines Tracks wird auf den spätesten verzögert. Ein Pre FX-Send am Pitch-Shifter vorbei kommt gleichzeitig mit dem Weg durch den Shifter an.
  • Im Spiel gilt dasselbe Routing, der Output ist dort der Master der Wiedergabe.

Selbst entschieden

  • Mute schließt die Sends, das Volume des Tracks bleibt stehen.
  • Die eigenen Items eines Tracks laufen über einen eigenen Bus …:#items. Ohne den ließe sich Solo nach 4a nicht umsetzen.

Funde unterwegs

  • Wer erst Volume auf -6 und dann Mode setzte, bekam wieder 0 dB: die Mode-Zeile schrieb den alten Stand mit. Behoben, vom ersten e2e-Lauf gefunden.
  • Solo wurde zuerst pro Track entschieden, dadurch blieben die direkten Wege in den Output offen (dein Screenshot). Jetzt wird jede Verbindung einzeln geprüft (trackGates in src/core/music/routing.ts).

Tests

Unit song-routing (neu)   → 13 grün
Unit sound-library        → 94 grün (4 neu)
Gegenproben               → 11, jede einzeln rot
e2e 65 (melektaus-atx)    → ALL PASSED, 43 Checks (5 neu)
Gate (melektaus-atx)      → Typcheck/Lint/Format sauber, 2 Tests rot
                            (Registry-Regel, Form von describeEdge),
                            angepasst und lokal 56 grün

Nicht geprüft:

  • e2e 65 und das Gate nach dem Solo-Fix (nur Unit-Tests, den vollen Lauf macht CI)
  • wie es klingt (die Tests laufen stumm)
  • Laufzeitausgleich und Routing einer Spiel-Wiedergabe im Browser (nur per Unit-Test)
Erledigt mit daeffe0, Wiki: *Songs* (Abschnitt *Routing*), Wiki-Commit b065d62. ## Was gebaut ist - **Song-Tab:** Umschalter **Timeline | Routing** im Kopf. Routing ist der Graph-Editor wie bei Sound FX: ein Node pro Track (Name vom Track) und ein fester Node **Output** (der Song-Master, von dort weiter an den Bus des Songs aus #325). - **Verbindungen:** Ein Track nimmt beliebig viele Eingänge an und geht an beliebig viele Ziele. Ein neuer Track hängt am Output, alte Songs bekommen beim Laden dieselbe Grundverdrahtung. - **Pegel je Verbindung (2b):** Eine gewählte Verbindung zeigt im Inspector *Volume* (-60 bis +12 dB, Standard 0) und *Mode*: **Post volume (Post pan)** (Standard), **Pre volume (Post FX)**, **Pre volume (Pre FX)**. - **Schleifen** lehnt der Editor schon beim Ziehen ab, beim Laden fallen sie weg. - **Track-Nodes** kommen und gehen mit den Tracks. `Delete` im Graph nimmt nur Verbindungen. - **Track ohne Ausgang (3a):** stumm, der Node zeigt *Goes nowhere*. - **Mute und Solo (4a)** wirken auf die Verbindungen: - Mute macht alles stumm, was durch den Track läuft, auf jedem Abgriff. - Solo auf A, A geht in B: B reicht A durch, die eigenen Items von B bleiben stumm. Tracks, die in A gehen, klingen mit. - Geht ein Track in den gesoloten Track **und** in den Output, hört man ihn nur über den gesoloten Track (der Fall aus dem Screenshot mit *Pitch FX*). - **Laufzeitausgleich:** Jeder Weg eines Tracks wird auf den spätesten verzögert. Ein *Pre FX*-Send am Pitch-Shifter vorbei kommt gleichzeitig mit dem Weg durch den Shifter an. - **Im Spiel** gilt dasselbe Routing, der Output ist dort der Master der Wiedergabe. ## Selbst entschieden - Mute schließt die Sends, das Volume des Tracks bleibt stehen. - Die eigenen Items eines Tracks laufen über einen eigenen Bus `…:#items`. Ohne den ließe sich Solo nach 4a nicht umsetzen. ## Funde unterwegs - Wer erst *Volume* auf -6 und dann *Mode* setzte, bekam wieder 0 dB: die Mode-Zeile schrieb den alten Stand mit. Behoben, vom ersten e2e-Lauf gefunden. - Solo wurde zuerst pro Track entschieden, dadurch blieben die direkten Wege in den Output offen (dein Screenshot). Jetzt wird jede Verbindung einzeln geprüft (`trackGates` in `src/core/music/routing.ts`). ## Tests ``` Unit song-routing (neu) → 13 grün Unit sound-library → 94 grün (4 neu) Gegenproben → 11, jede einzeln rot e2e 65 (melektaus-atx) → ALL PASSED, 43 Checks (5 neu) Gate (melektaus-atx) → Typcheck/Lint/Format sauber, 2 Tests rot (Registry-Regel, Form von describeEdge), angepasst und lokal 56 grün ``` **Nicht geprüft:** - e2e 65 und das Gate nach dem Solo-Fix (nur Unit-Tests, den vollen Lauf macht CI) - wie es klingt (die Tests laufen stumm) - Laufzeitausgleich und Routing einer Spiel-Wiedergabe im Browser (nur per Unit-Test)
Author
Owner

Nachtrag: Snap im Routing (8c0d1cf)

Im Issue stand „mit Zoom, Snap und Undo“, gebaut war Snap aber nie. Das ist jetzt nachgezogen.

  • Der Magnet sitzt im Kopf des Song-Tabs direkt neben Routing. Er sieht aus wie in den anderen Graph-Tabs, ist am Anfang aus und wirkt auf den Routing-Graph.
  • Auf der Timeline ist er ausgegraut. Umgekehrt ist Grid im Routing ausgegraut.
  • Nebenbei behoben: Beim Umschalten der Ansicht wurde Grid bisher erst bei der nächsten Änderung am Projekt aktiviert oder ausgegraut. Jetzt schaltet der Wechsel beide Knöpfe gleich mit um. Der laufende Song bekommt dabei seine Sequenz nicht neu übergeben.
Commit
Repo 8c0d1cf Snap the routing graph of a song with the header's magnet (#350)
Wiki ccc9542 Describe the magnet of the song routing (#350)

Im Wiki stand derselbe Satz mit „Snap“. Songs nennt jetzt den Magnet, Development 1890 Checks.

Tests

e2e 65 (melektaus-atx)                          → ALL PASSED – 52 Checks (1 neu)
Gegenprobe (Magnet auch auf der Timeline aktiv) → genau dieser Check rot
Gate (melektaus-atx)                            → CHECK EXIT 0, 270 Dateien, 4178 Tests
  • Der neue Check: Auf der Timeline ist der Magnet ausgegraut, im Routing aktiv. Ein Klick schaltet Snap im Routing-Graph ein und lässt den Knopf leuchten, ein zweiter schaltet es wieder aus.
  • Nicht geprüft: dass ein gezogener Node im Song-Routing auf dem Raster landet. Das Einrasten macht derselbe GraphCanvas wie in den anderen Graph-Tabs, dort prüfen e2e 06 und 26 es.

Das Issue bleibt geschlossen.

## Nachtrag: Snap im Routing (`8c0d1cf`) Im Issue stand „mit Zoom, Snap und Undo“, gebaut war Snap aber nie. Das ist jetzt nachgezogen. - **Der Magnet sitzt im Kopf des Song-Tabs direkt neben *Routing*.** Er sieht aus wie in den anderen Graph-Tabs, ist am Anfang aus und wirkt auf den Routing-Graph. - **Auf der Timeline ist er ausgegraut.** Umgekehrt ist *Grid* im Routing ausgegraut. - **Nebenbei behoben:** Beim Umschalten der Ansicht wurde *Grid* bisher erst bei der nächsten Änderung am Projekt aktiviert oder ausgegraut. Jetzt schaltet der Wechsel beide Knöpfe gleich mit um. Der laufende Song bekommt dabei seine Sequenz nicht neu übergeben. | | Commit | |---|---| | Repo | `8c0d1cf` Snap the routing graph of a song with the header's magnet (#350) | | Wiki | `ccc9542` Describe the magnet of the song routing (#350) | Im Wiki stand derselbe Satz mit „Snap“. *Songs* nennt jetzt den Magnet, *Development* 1890 Checks. ### Tests ``` e2e 65 (melektaus-atx) → ALL PASSED – 52 Checks (1 neu) Gegenprobe (Magnet auch auf der Timeline aktiv) → genau dieser Check rot Gate (melektaus-atx) → CHECK EXIT 0, 270 Dateien, 4178 Tests ``` - **Der neue Check:** Auf der Timeline ist der Magnet ausgegraut, im Routing aktiv. Ein Klick schaltet Snap im Routing-Graph ein und lässt den Knopf leuchten, ein zweiter schaltet es wieder aus. - **Nicht geprüft:** dass ein gezogener Node im Song-Routing auf dem Raster landet. Das Einrasten macht derselbe `GraphCanvas` wie in den anderen Graph-Tabs, dort prüfen e2e 06 und 26 es. Das Issue bleibt geschlossen.
admin added this to the Development project 2026-10-08 21:43:22 +02:00
admin moved this to Next in Development on 2026-10-08 21:43:30 +02:00
admin moved this to Done in Development on 2026-10-08 21:43:40 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#350