Fix silent telemetry soundboard buttons before first engage
TelemetrySynth.gainNode was only ever created inside start(), which is only called from the main ENGAGE/FULL STOP flow. Every telemetry-driven soundboard one-shot (LCARS Single/Double Chirp, Ack Sequence, Sensor Sweep, the TOS/NX/Cardassian era sounds, Door Chime, and the Phase 3 who/bioship/belter era generators) guarded on `!this.gainNode` with no fallback, so clicking any of them before the ambient bed had been engaged once did nothing at all: no sound, no console error, and nothing for the spectrum analyzer to react to. ExpandedSciFiAudioSynth and WhoniverseAudioSynth already self-heal this way via their own init() (called at the top of every public synth method) - that's why buttons like Comm Badge work standalone. Add the same init() to TelemetrySynth and call it from every method reachable from the soundboard, so the whole class follows the same convention. start() is left untouched: it still unconditionally rebuilds the node on every engage so a newly-selected preset's volume takes effect immediately. Verified with a small headless harness driving TelemetrySynth directly (no prior start()): all 13 affected methods now create gainNode and fire real oscillators on first call, where they previously did nothing. Confirmed against the pre-fix code that the same harness reproduces the original silent failure. Regenerated dist/SciFiAmbientDisplay_v4.html to match (tools/package.ps1 requires PowerShell, unavailable in this shell, so the inlining was replicated in Python matching its exact output convention; diff against the previous build is exactly the 31 added lines, nothing else). Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01582UUCEBExzp3oK3Spz1Xx
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b3407812a1
commit
9dc48e94d9
Vendored
+31
@@ -3560,6 +3560,23 @@ class TelemetrySynth {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily creates the telemetry gain node so soundboard one-shots (LCARS
|
||||
* chirps, era-specific one-shots) work standalone even before the ambient
|
||||
* bed has been engaged via start(). Mirrors the init() self-heal pattern
|
||||
* used by ExpandedSciFiAudioSynth and WhoniverseAudioSynth. start() below
|
||||
* still unconditionally rebuilds the node on every engage so a fresh
|
||||
* preset's volume takes effect immediately; this only fills the gap
|
||||
* before that has ever happened.
|
||||
*/
|
||||
init() {
|
||||
if (this.gainNode || !this.am.ctx) return;
|
||||
const ctx = this.am.ctx;
|
||||
this.gainNode = ctx.createGain();
|
||||
this.gainNode.gain.setValueAtTime(this.isMuted ? 0 : this.params.volume, ctx.currentTime);
|
||||
this.gainNode.connect(this.am.compressor);
|
||||
}
|
||||
|
||||
start() {
|
||||
this.stop();
|
||||
const ctx = this.am.ctx;
|
||||
@@ -3663,6 +3680,7 @@ class TelemetrySynth {
|
||||
* Star Trek Comm Badge Confirmation Chirp
|
||||
*/
|
||||
synthesizeCommBadge() {
|
||||
this.init();
|
||||
if (window.expandedAudio) {
|
||||
window.expandedAudio.synthesizeCommBadge();
|
||||
return;
|
||||
@@ -3690,6 +3708,7 @@ class TelemetrySynth {
|
||||
* TNG/Voyager Single LCARS Touch Tone (Soft sine with gentle attack and rapid exponential decay)
|
||||
*/
|
||||
synthesizeLCARSSingleChirp(pitch = null) {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3725,6 +3744,7 @@ class TelemetrySynth {
|
||||
* TNG LCARS Double Chirp (Iconic standard confirmation tone)
|
||||
*/
|
||||
synthesizeLCARSDoubleChirp() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx) return;
|
||||
const idx = Math.floor(Math.random() * (this.lcarsPitches.length - 2));
|
||||
@@ -3741,6 +3761,7 @@ class TelemetrySynth {
|
||||
* TNG LCARS Multi-Tone Data Acknowledgment Sequence
|
||||
*/
|
||||
synthesizeLCARSSequence() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx) return;
|
||||
const notes = [
|
||||
@@ -3760,6 +3781,7 @@ class TelemetrySynth {
|
||||
* High-tech Sensor Sweep Tone (Voyager/TNG Long-Range Sensor telemetry)
|
||||
*/
|
||||
synthesizeSensorSweep() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3790,6 +3812,7 @@ class TelemetrySynth {
|
||||
* Two detuned square/triangle oscillators modulated by high-speed vibrato LFO
|
||||
*/
|
||||
synthesizeTOSWarble() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3846,6 +3869,7 @@ class TelemetrySynth {
|
||||
* TOS Mechanical Relay Solenoid Click
|
||||
*/
|
||||
synthesizeTOSRelayClick() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3872,6 +3896,7 @@ class TelemetrySynth {
|
||||
* DS9 / Cardassian Cavernous Sensor Tone (Resonant metallic ring)
|
||||
*/
|
||||
synthesizeCardassianSensor() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3906,6 +3931,7 @@ class TelemetrySynth {
|
||||
* NX-01 Industrial Hydraulic Relay Click
|
||||
*/
|
||||
synthesizeNXRelay() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3932,6 +3958,7 @@ class TelemetrySynth {
|
||||
* NX-01 Indicator Beep (Early 22nd century industrial tone)
|
||||
*/
|
||||
synthesizeNXIndicatorBeep() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -3959,6 +3986,7 @@ class TelemetrySynth {
|
||||
* Iconic TNG 2-Tone Door Chime ("Come in")
|
||||
*/
|
||||
synthesizeDoorChime() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -4005,6 +4033,7 @@ class TelemetrySynth {
|
||||
* the single scheduler timeout can never orphan nodes.
|
||||
*/
|
||||
synthesizeWhoMechanicalTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -4088,6 +4117,7 @@ class TelemetrySynth {
|
||||
* One 0.5-1.1 s phrase of 2-4 events on absolute ctx time.
|
||||
*/
|
||||
synthesizeBioshipOrganicTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -4198,6 +4228,7 @@ class TelemetrySynth {
|
||||
* occasional late sub-cluster to mimic an unsteady clock.
|
||||
*/
|
||||
synthesizeBelterJuryRiggedTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
|
||||
+31
@@ -826,6 +826,23 @@ class TelemetrySynth {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily creates the telemetry gain node so soundboard one-shots (LCARS
|
||||
* chirps, era-specific one-shots) work standalone even before the ambient
|
||||
* bed has been engaged via start(). Mirrors the init() self-heal pattern
|
||||
* used by ExpandedSciFiAudioSynth and WhoniverseAudioSynth. start() below
|
||||
* still unconditionally rebuilds the node on every engage so a fresh
|
||||
* preset's volume takes effect immediately; this only fills the gap
|
||||
* before that has ever happened.
|
||||
*/
|
||||
init() {
|
||||
if (this.gainNode || !this.am.ctx) return;
|
||||
const ctx = this.am.ctx;
|
||||
this.gainNode = ctx.createGain();
|
||||
this.gainNode.gain.setValueAtTime(this.isMuted ? 0 : this.params.volume, ctx.currentTime);
|
||||
this.gainNode.connect(this.am.compressor);
|
||||
}
|
||||
|
||||
start() {
|
||||
this.stop();
|
||||
const ctx = this.am.ctx;
|
||||
@@ -929,6 +946,7 @@ class TelemetrySynth {
|
||||
* Star Trek Comm Badge Confirmation Chirp
|
||||
*/
|
||||
synthesizeCommBadge() {
|
||||
this.init();
|
||||
if (window.expandedAudio) {
|
||||
window.expandedAudio.synthesizeCommBadge();
|
||||
return;
|
||||
@@ -956,6 +974,7 @@ class TelemetrySynth {
|
||||
* TNG/Voyager Single LCARS Touch Tone (Soft sine with gentle attack and rapid exponential decay)
|
||||
*/
|
||||
synthesizeLCARSSingleChirp(pitch = null) {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -991,6 +1010,7 @@ class TelemetrySynth {
|
||||
* TNG LCARS Double Chirp (Iconic standard confirmation tone)
|
||||
*/
|
||||
synthesizeLCARSDoubleChirp() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx) return;
|
||||
const idx = Math.floor(Math.random() * (this.lcarsPitches.length - 2));
|
||||
@@ -1007,6 +1027,7 @@ class TelemetrySynth {
|
||||
* TNG LCARS Multi-Tone Data Acknowledgment Sequence
|
||||
*/
|
||||
synthesizeLCARSSequence() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx) return;
|
||||
const notes = [
|
||||
@@ -1026,6 +1047,7 @@ class TelemetrySynth {
|
||||
* High-tech Sensor Sweep Tone (Voyager/TNG Long-Range Sensor telemetry)
|
||||
*/
|
||||
synthesizeSensorSweep() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1056,6 +1078,7 @@ class TelemetrySynth {
|
||||
* Two detuned square/triangle oscillators modulated by high-speed vibrato LFO
|
||||
*/
|
||||
synthesizeTOSWarble() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1112,6 +1135,7 @@ class TelemetrySynth {
|
||||
* TOS Mechanical Relay Solenoid Click
|
||||
*/
|
||||
synthesizeTOSRelayClick() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1138,6 +1162,7 @@ class TelemetrySynth {
|
||||
* DS9 / Cardassian Cavernous Sensor Tone (Resonant metallic ring)
|
||||
*/
|
||||
synthesizeCardassianSensor() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1172,6 +1197,7 @@ class TelemetrySynth {
|
||||
* NX-01 Industrial Hydraulic Relay Click
|
||||
*/
|
||||
synthesizeNXRelay() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1198,6 +1224,7 @@ class TelemetrySynth {
|
||||
* NX-01 Indicator Beep (Early 22nd century industrial tone)
|
||||
*/
|
||||
synthesizeNXIndicatorBeep() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1225,6 +1252,7 @@ class TelemetrySynth {
|
||||
* Iconic TNG 2-Tone Door Chime ("Come in")
|
||||
*/
|
||||
synthesizeDoorChime() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1271,6 +1299,7 @@ class TelemetrySynth {
|
||||
* the single scheduler timeout can never orphan nodes.
|
||||
*/
|
||||
synthesizeWhoMechanicalTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1354,6 +1383,7 @@ class TelemetrySynth {
|
||||
* One 0.5-1.1 s phrase of 2-4 events on absolute ctx time.
|
||||
*/
|
||||
synthesizeBioshipOrganicTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
@@ -1464,6 +1494,7 @@ class TelemetrySynth {
|
||||
* occasional late sub-cluster to mimic an unsteady clock.
|
||||
*/
|
||||
synthesizeBelterJuryRiggedTelemetry_() {
|
||||
this.init();
|
||||
const ctx = this.am.ctx;
|
||||
if (!ctx || !this.gainNode) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user