Files
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

277 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Heli-Audio — Konzept V2
Stand: 2026-05-31 · Autor: Atlas · Status: Diskussion mit Thomas
## Thomas-Direktiven (2026-05-31)
> Wir brauchen ein geschicktes Konzept, dass nicht irgendwo ewige Stille ist. Gleichzeitig gibt es zentral wichtige Ansagen/Geräusche (Unfall, Warnung, Missionsinfo) und weniger wichtige (geografische Info) — die aber natürlich auch gespielt werden sollen, wenn möglich.
>
> Ducking: ja. Crossfade weglassen. Geo-Audios werden von Notfall-Zwischenrufen überlagert bzw. gestoppt. Alles andere (Environmental, Reverb, Spatial): machen.
## Audio-Schichten (Architektur-Bild)
```
┌───────────────────────────────────────────┐
SCHICHT 1 │ AMBIENT (loop, Volume 0.1) │ immer da
(Hintergrund) │ • Wind/Wasser/Verkehr je Szenario │ nie still
│ • Heli-Rotor (nur Flight-Phase) │
│ • Musik (nur Mission/Results-Phase) │
└───────────────────────────────────────────┘
▲ Ducking: 0.10 → 0.04 wenn Stimme spielt
┌───────────────────────────────────────────┐
SCHICHT 2 │ SPRACH-PIPE (seriell, prioritätssortiert)│
(Stimmen) │ │
│ CRITICAL (1) — unterbricht alles │
│ • Crash-Warnung, Boden-Alarm │
│ • Tower-Notfunk, Pilot-Übernahme │
│ • Stop!-Ansagen │
│ │
│ HIGH (2) — Standard-Funk-Pipe │
│ • Tower-Wegpunkt-Anweisungen │
│ • Mission-Briefing │
│ • Pilot-Antworten │
│ │
│ MEDIUM (3) — wenn Pipe leer ist │
│ • Geografische Hintergrund-Infos │
│ • Stimmung („Sicht klar", „Wind ruhig")│
│ • Stadt-/Berg-Fakten beim Überflug │
│ │
│ FILLER (4) — Anti-Stille │
│ • Wenn Pipe >12 s leer: Filler-Item │
│ • Cockpit-Geräusche, Pilot-Murmeln │
└───────────────────────────────────────────┘
┌───────────────────────────────────────────┐
SCHICHT 3 │ FEEDBACK-SOUNDS (kurz, ohne Pipe) │ sofort
(UI/Feedback) │ • Klick-OK, Klick-Fehler │ parallel
│ • Wegpunkt-Treffer-Glocke │ zur Pipe
└───────────────────────────────────────────┘
```
## Prioritäten-Logik
Aktuell hat die Pipe nur: **seriell + 10s-Gap + `priority:'now'`-Bypass**. Wir brauchen ein **vollwertiges Prioritäten-System** mit 4 Levels.
### Pipe-Verhalten pro Priorität
| Level | Verhalten beim Einreihen | Beispiel-Audios |
|---|---|---|
| **1 CRITICAL** | Laufendes Audio per 120ms-Fade abbrechen, gesamte Queue leeren, sofort spielen | „Achtung! Boden zu nah!", „Pilot übernimmt — wir landen jetzt!", „Stop! Falsche Richtung!" |
| **2 HIGH** | Hinten in Queue einreihen, nach Gap (3 s) spielen. Wird von CRITICAL unterbrochen. | Tower-Wegpunkt-Anweisungen, Briefing-Hinweise, Pilot-Antworten |
| **3 MEDIUM** | Nur einreihen wenn keine HIGH-Items in Queue. Wird beim Eintreffen eines HIGH-Items aus der Queue entfernt (verlieren ihre Chance), beim Eintreffen eines CRITICAL auch sofort gestoppt wenn laufend. | Geo-Fakten („Wir überfliegen Schwaz, drittgrößte Stadt Tirols"), Stadt-Kommentare |
| **4 FILLER** | Wird automatisch eingereiht wenn Pipe >12 s leer war. Wird von HIGH/CRITICAL überschrieben. | Cockpit-Klick, Pilot-Räuspern, „Sicht ist klar", „Höhe stabil" |
### Code-Konzept (Pseudo-JS)
```js
// Ersetzt die aktuelle flightAudioQueue durch priority-Queue
var pipe = {
current: null, // {src, priority, _fadeGain}
queue: [], // sorted by priority
lastSpokenMs: 0, // für FILLER-Trigger
gapMs: { 1: 0, 2: 3000, 3: 5000, 4: 8000 }
};
function enqueueSpeech(path, priority) {
// 1) CRITICAL: alles wegfegen, sofort spielen
if (priority === 1) {
abortCurrentWithFade(120);
pipe.queue.length = 0;
pipe.queue.push({path, priority});
pump();
return;
}
// 2) HIGH: einreihen, MEDIUM-Items davor aus Queue entfernen
if (priority === 2) {
pipe.queue = pipe.queue.filter(it => it.priority <= 2);
pipe.queue.push({path, priority});
pump();
return;
}
// 3) MEDIUM: nur einreihen wenn keine HIGH in Queue ist
if (priority === 3) {
if (pipe.queue.some(it => it.priority <= 2)) return;
pipe.queue.push({path, priority});
pump();
return;
}
// 4) FILLER: separate Strategie (siehe unten)
}
function pump() {
if (pipe.current) return;
if (!pipe.queue.length) return;
var now = performance.now();
// Gap nur ANWENDEN, wenn dasselbe oder höhere Level wartet
var next = pipe.queue[0];
var requiredGap = pipe.gapMs[next.priority];
if (now - pipe.lastSpokenMs < requiredGap) {
setTimeout(pump, requiredGap - (now - pipe.lastSpokenMs));
return;
}
var item = pipe.queue.shift();
playWithDucking(item).then(() => {
pipe.current = null;
pipe.lastSpokenMs = performance.now();
pump();
});
}
// Anti-Stille: alle 2s prüfen, ob FILLER nötig
setInterval(() => {
if (pipe.current || pipe.queue.length) return;
if (performance.now() - pipe.lastSpokenMs < 12000) return;
enqueueFiller(); // wählt Filler je nach Phase + Szenario
}, 2000);
```
## Ducking
Wenn Stimme spielt → **Rotor-Lautstärke von 0.30 auf 0.08 fadrenken** (300 ms attack), nach Stimmenende **3 s linear zurück auf 0.30** (release). Gleiches für Hintergrund-Musik (von 0.20 auf 0.05). Environmental-Loops bleiben unverändert (sie sind schon leise genug).
Code-Skizze:
```js
function duckAmbient(on) {
var t = audioCtx.currentTime;
var targetRotor = on ? 0.08 : 0.30;
var targetMusic = on ? 0.05 : 0.20;
var rampSec = on ? 0.3 : 3.0;
rotorGain.gain.cancelScheduledValues(t);
rotorGain.gain.linearRampToValueAtTime(targetRotor, t + rampSec);
musicGain.gain.cancelScheduledValues(t);
musicGain.gain.linearRampToValueAtTime(targetMusic, t + rampSec);
}
```
## „Keine ewige Stille" — FILLER-Strategie
Pool von **1520 sehr kurzen Filler-Audios** (13 s), die je nach Phase + Szenario gewählt werden:
| Phase | Filler-Pool |
|---|---|
| **plan** (Routenplanung) | „Hmm…", „Schauen wir mal", „Lass mich nachdenken", Cockpit-Schalter-Klick |
| **flight** Berg | Pilot: „Wind ruhig", „Sicht klar", Höhenmesser-Beep, „Höhe stabil" |
| **flight** Wasser | Pilot: „Wellen ruhig", „Patient in Sicht", Wasser-Plätschern |
| **flight** Autobahn | Pilot: „Funk-Check", „Verkehr läuft" |
| **landing** | Pilot: „Sinkrate gut", „Ein Meter", „Last steady" |
Plus: **Cockpit-Ambient-Loops** auf Schicht 1 (siehe oben) — die laufen IMMER, also ist nie wirklich Stille.
## Environmental-Loops (Schicht 1, neu)
Pro Szenario ein 3060 s-Loop, Volume 0.10 (wird bei Stimme auf 0.04 geduckt):
| Szenario | Loop | Beschreibung |
|---|---|---|
| `basis` (Standard) | `amb_general.mp3` | leises Cockpit-Brummen + Wind |
| `wasser` | `amb_water.mp3` | Wellen, Möwen, Wind |
| `berg-fels` | `amb_mountain.mp3` | Wind, leichter Hall |
| `berg-schnee` | `amb_snow.mp3` | Sturm-Säuseln, Schnee |
| `autobahn` | `amb_highway.mp3` | Verkehr, Sirenen entfernt |
| `stadt` | `amb_urban.mp3` | Stadt-Rauschen, Hupen |
| `schlucht` | `amb_canyon.mp3` | Echo-Wind, Wasser |
| `tal-dorf` | `amb_village.mp3` | Vogelzwitschern, Kirchglocke selten |
**8 Loops**. Beschaffung: entweder selbst aufnehmen (Wind im Garten, Wasser im Bad…), oder Lizenz-frei (Freesound.org, BBC Sound Effects Library — frei für Bildung).
## Reverb für ausgewählte Missionen
Mit einem `ConvolverNode` und einem kurzen Impulse-Response können wir den Funk-Klang räumlich variieren:
| Mission-Typ | Reverb-IR | Effekt |
|---|---|---|
| Schlucht (M6 Canyoning Mellau) | `ir_canyon_short.wav` (0.8 s) | Funk klingt hallend, eng |
| Berg-Hochalpin (M19, M20, M24 Glockner/Dachstein) | `ir_mountain.wav` (1.2 s) | weit, kalt |
| Tunnel/Autobahn-Tunnel | `ir_tunnel.wav` (1.5 s) | dröhnend |
| Standard (Stadt, Wasser, Wald) | kein Reverb | trocken, klar |
**3 Reverb-IRs**. Beschaffung: kostenlose IR-Libraries (z.B. https://www.openair.hosted.york.ac.uk/).
## Spatial Stereo (kleines Feature)
Sprecher-Position als Stereo-Pan:
- **Tower-Lotsin**: pan -0.4 (links — sitzt im Tower, „neben" dem Heli)
- **Pilot:in**: pan +0.3 (rechts — sitzt rechts vom Schüler im Cockpit)
- **Sani / Flugretter**: pan 0 (zentriert, hinten im Cockpit)
- **Briefing-Offizierin**: pan 0 (vor dem Bildschirm, direkt)
Subtil (Pan ±0.4 max), nicht aufdringlich.
## Geo-Audios — wann triggern?
Aktueller Code: Geo-Audios (`r_mission_geo_*`, `r_wp_geo_*`) sind in der Standard-Pipe → konkurrieren mit Tower-Anweisungen → 10s-Gap verzögert alles.
**Neu** (Prioritäten):
- `r_mission_geo_*` (am Kartenflug-Beginn): **MEDIUM** — spielt nur wenn keine Tower-Anweisung wartet
- `r_wp_geo_*` (pro Wegpunkt): **MEDIUM** — wird vom nächsten Tower-Funk abgebrochen
- `r_tower_*` (Wegpunkt-Anweisungen): **HIGH**
- `r_caution_*` (Notfall-Warnung): **CRITICAL**
- `r_pilot_takeover`: **CRITICAL**
Wenn der Schüler in der Plan-Phase Wegpunkte klickt und der Tower antworten muss („Korrekt, weiter über X"), bricht das die laufende Geo-Info ab. Bei richtigem Tempo bekommt er aber so viel Geo wie möglich.
## Übersicht — was wir bauen
| # | Komponente | Aufwand | Wirkung |
|---|---|---|---|
| 1 | **Prioritäten-Pipe** (4 Levels statt eines) | mittel | Kern der ganzen Logik |
| 2 | **Ducking** (Rotor + Musik bei Stimme leiser) | klein | Verständlichkeit massiv besser |
| 3 | **FILLER-Strategie** (Anti-Stille mit Pool) | mittel | Keine toten Phasen mehr |
| 4 | **Environmental-Loops** (8 Loops, 1 pro Szenario) | mittel (Beschaffung + Wiring) | Stimmung, kontinuierlicher Klangteppich |
| 5 | **Audio-Texte umstellen** auf Prioritäten-API | mittel | Skripte sortieren |
| 6 | **Reverb für 3 Mission-Typen** | klein (IR-Files + ConvolverNode) | Räumlichkeit |
| 7 | **Spatial Stereo** | klein | Goldener Schliff |
Reihenfolge bauen: **1 → 2 → 3 → 5 → 4 → 6 → 7**.
## Beziehung zu Heli-Kennzeichen-Konzept
Audio-Texte (8 JSON-Dateien, 366 Stellen mit „Christophorus") werden im Zuge von Schritt 5 auf Platzhalter `{code}` umgestellt. Audio-Regenerierung dann **pro Mission gemeinsam mit Thomas** (siehe Heli-Kennzeichen-Konzept Schritt 7).
## Audio-Re-Generierung — offene Text-Korrekturen (zu erledigen wenn Audios neu gebaut werden)
Die Audio-Skript-JSON-Dateien (`scripts/*-lines.json` + `scripts/audio-texts.json`) wurden bereits textlich korrigiert. Die zugehörigen MP3-Dateien sind aber noch alt und sagen die ursprünglichen Texte. **Beim nächsten Re-Generieren** müssen folgende Audios neu erstellt werden:
### Inhaltliche Korrekturen (2026-05-31)
1. **„Chefpilot" → „Chefpilotin"** (Marlene als weibliche Mentorin im Onboarding etabliert)
- `r_mission_abort` + `r_mission_abort_m` (Drei Berührungen → die Chefpilotin übernimmt)
- `r_nav_departure_takeover` (Chefpilotin hat übernommen)
- `r_tower_handover_c1` bis `r_tower_handover_c16` (14 Tower-Audios: „Heute übernimmt die Chefpilotin")
2. **„Rotorabwind wäre Steinschlag" → „Rotorabwind kann Steinschlag verursachen"** (kausal richtiger Satz)
- `r_caution_berg_fels` + `r_caution_berg_fels_m` (in M3/M6/M7/M12/M13/M21 etc. — alle berg-fels-Missionen)
- `r_caution_wasser` ist unverändert sinnvoll, weil dort der Effekt deterministisch ist
- **Status:** Text in JSON gefixt am 2026-05-31. Alte MP3 spielt noch den alten Wortlaut bis Re-Generierung.
3.5 **ASCII-Umlaut-Fixes in audio-texts.json** (2026-05-31, zweite Runde)
- `r_nav_plan_correct`, `r_nav_plan_done`, `r_nav_seg_arrive`, `r_nav_altitude_mountain`, `r_nav_altitude_valley`, `r_nav_fuel_half`, `r_nav_route_check`, `r_nav_weather_enter`, `r_land_approach`, `r_land_rescuer_down`, `r_land_winch_down`, `r_land_rescuer_ready`, `r_tower_sea_approach_c9`
- Vorher: "naechsten", "vollstaendig", "Ueberflughoehe", "moeglich", "Stroemung" etc. — alle MP3s sprechen noch das ASCII-Wort, JSON-Text aber UTF-8-korrekt
- **Status:** Text in JSON gefixt am 2026-05-31. Alte MP3s warten auf Re-Generierung.
4. **Marlene als zentrale Chefpilotin überall** (Vereinheitlichung 2026-05-31, vorher 4 rotierende Profile)
- Wirkt sich aus auf alle `pilot_*` und `caution_*`-Audios, die per `pilot_by_helikey` ausgewählt werden
- **Alle pilot_*_m-Audios (Hannes/Stefan) werden in V1 nicht mehr abgespielt** — bleiben im System für später
- Bilder + Funk-Pille zeigen ab sofort immer pilot_b_f (Marlene) statt der jeweiligen Stationspilot:in
- Bei Re-Generierung: nur die weiblichen Varianten (ohne `_m`) brauchen Updates
3. **Marken-Bezeichnungen** (siehe `docs/konzept-heli-kennzeichen.md`):
- „Christophorus N" → Pool-Kennzeichen oder generisches „R/N-N" (16 + viele weitere Stellen)
- ggf. nochmal Audio-Workflow gemeinsam mit Thomas pro Mission
### Total beim nächsten Audio-Bau
Ca. 18 Pilot- + Tower-Audios kombiniert mit Marken-Refactor ergeben ~3040 zu re-generierende MP3s.
---
## Status & nächste Schritte
- [ ] Schritt 1 (Prioritäten-Pipe) — warte auf Thomas-OK
- [ ] Schritt 2 (Ducking) — warte
- [ ] Schritt 3 (FILLER-Strategie) — warte
- [ ] Filler-Texte definieren (Pool von 1520 kurzen Audios) — gemeinsame Auswahl mit Thomas
- [ ] Environmental-Loops beschaffen oder aufnehmen
- [ ] Audio-Re-Generierung mit korrigiertem Text (siehe oben)