- 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>
14 KiB
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)
// 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:
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 15–20 sehr kurzen Filler-Audios (1–3 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 30–60 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 wartetr_wp_geo_*(pro Wegpunkt): MEDIUM — wird vom nächsten Tower-Funk abgebrochenr_tower_*(Wegpunkt-Anweisungen): HIGHr_caution_*(Notfall-Warnung): CRITICALr_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)
-
„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_c1bisr_tower_handover_c16(14 Tower-Audios: „Heute übernimmt die Chefpilotin")
-
„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_wasserist 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.
-
Marlene als zentrale Chefpilotin überall (Vereinheitlichung 2026-05-31, vorher 4 rotierende Profile)
- Wirkt sich aus auf alle
pilot_*undcaution_*-Audios, die perpilot_by_helikeyausgewä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
- Wirkt sich aus auf alle
-
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 ~30–40 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 15–20 kurzen Audios) — gemeinsame Auswahl mit Thomas
- Environmental-Loops beschaffen oder aufnehmen
- Audio-Re-Generierung mit korrigiertem Text (siehe oben)