Implement Phase 1 audio gaps: 20 quick-win procedural sounds and ambient loops

- 18 low + 2 low-medium discrete elements (comm badge, door swishes, bosun
  whistle, sickbay ECG, TARDIS lever/door, Sevastopol sparks, commlock tone,
  station ECG, solar roar, cryo sigh, Orion thump, tea dispenser, kettle
  whistle, plaid alarm, cassette transport, grappler servo, radio static,
  mag-boot latch) with soundboard buttons, preset tuning, and automated
  background loops
- bio-wraith misty life-support tuning; sound_reference.md and audio_gaps.md
  implementation tracking
- gitignore audition scratch and local artifacts
This commit is contained in:
Claude
2026-09-04 08:32:36 -07:00
parent 19ff051d58
commit f2776885c9
8 changed files with 5760 additions and 264 deletions
+176 -35
View File
@@ -14,6 +14,10 @@ document.addEventListener('DOMContentLoaded', () => {
const alerts = new AlertSynth(audioManager);
const whoniverseAudio = new WhoniverseAudioSynth(audioManager);
const expandedAudio = new ExpandedSciFiAudioSynth(audioManager);
const engineTransitions = new EngineTransitionSynth(audioManager);
window.expandedAudio = expandedAudio;
window.whoniverseAudio = whoniverseAudio;
window.engineTransitions = engineTransitions;
const visualizer = new StarshipVisualizer(audioManager, warpCore);
const observationEngine = new ObservationEngine(audioManager, warpCore, alerts, hullDrone, lifeSupport);
window.observationEngine = observationEngine;
@@ -306,7 +310,14 @@ document.addEventListener('DOMContentLoaded', () => {
syncSlidersToSynthParams();
expandedAudio.stopAllLoops();
if (isPlaying) {
if (presetId === 'sta-sevastopol') {
expandedAudio.startStationSparks(4000, 11000);
} else if (presetId === 'sta-gateway' || presetId.includes('sickbay') || presetId.includes('med')) {
expandedAudio.startMedicalMonitor(1.15);
}
if (activeUniverseId === 'whoniverse') whoniverseAudio.synthesizeDematSwitch();
else if (activeUniverseId === 'industrial') expandedAudio.synthesizeDockingClamp();
else telemetry.synthesizeLCARSSingleChirp();
@@ -344,39 +355,93 @@ document.addEventListener('DOMContentLoaded', () => {
}
// 5. Play / Pause Master Toggle
let isTransitioning = false;
const ENGINE_TRANSITION_SECS = 2.5;
async function togglePlay() {
if (isTransitioning) return;
const engineProfile = typeof getEngineProfileForPreset === 'function'
? getEngineProfileForPreset(activePresetId, activeUniverseId)
: 'galaxy';
if (!isPlaying) {
isTransitioning = true;
await audioManager.resume();
hullDrone.start();
warpCore.start();
lifeSupport.start();
telemetry.start();
isPlaying = true;
btnPlay.classList.add('playing');
playIcon.textContent = '■';
playText.textContent = 'DISENGAGE';
statAudioStatus.textContent = 'ONLINE';
statAudioStatus.style.color = '#00ff88';
// Flashing state while engaging
btnPlay.classList.add('engaging');
btnPlay.classList.remove('playing', 'stopping');
statAudioStatus.textContent = 'ENGAGING...';
statAudioStatus.style.color = '#ffcc00';
// Layered & Staged Procedural Startup Script for this Profile
engineTransitions.playStartup(engineProfile, ENGINE_TRANSITION_SECS);
// Acoustic chime / chirp feedback
if (activeUniverseId === 'whoniverse') whoniverseAudio.synthesizeTelepathicChime();
else if (activeUniverseId === 'bioships') expandedAudio.synthesizeStarburst();
else telemetry.synthesizeLCARSDoubleChirp();
// Start engine sounds with smooth spool-up ramp
hullDrone.start(ENGINE_TRANSITION_SECS);
warpCore.start(ENGINE_TRANSITION_SECS);
lifeSupport.start(ENGINE_TRANSITION_SECS);
telemetry.start();
setTimeout(() => {
isPlaying = true;
isTransitioning = false;
btnPlay.classList.remove('engaging');
btnPlay.classList.add('playing');
playIcon.textContent = '■';
playText.textContent = 'FULL STOP';
statAudioStatus.textContent = 'ONLINE';
statAudioStatus.style.color = '#00ff88';
if (activePresetId === 'sta-sevastopol') {
expandedAudio.startStationSparks(4000, 11000);
} else if (activePresetId === 'sta-gateway' || activePresetId.includes('sickbay') || activePresetId.includes('med')) {
expandedAudio.startMedicalMonitor(1.15);
}
}, ENGINE_TRANSITION_SECS * 1000);
} else {
hullDrone.stop();
warpCore.stop();
lifeSupport.stop();
isTransitioning = true;
// Flashing state while stopping
btnPlay.classList.remove('playing', 'engaging');
btnPlay.classList.add('stopping');
statAudioStatus.textContent = 'STOPPING...';
statAudioStatus.style.color = '#ff9900';
// Layered & Staged Procedural Shutdown Script for this Profile
engineTransitions.playShutdown(engineProfile, ENGINE_TRANSITION_SECS);
if (activeUniverseId === 'whoniverse') whoniverseAudio.synthesizeLeverClunk();
else telemetry.synthesizeLCARSDoubleChirp();
// Stop engine sounds with smooth spool-down fade
hullDrone.stop(ENGINE_TRANSITION_SECS);
warpCore.stop(ENGINE_TRANSITION_SECS);
lifeSupport.stop(ENGINE_TRANSITION_SECS);
telemetry.stop();
expandedAudio.stopAllLoops();
alerts.stopAlert();
whoniverseAudio.stopCloisterBell();
resetAlertButtons();
isPlaying = false;
btnPlay.classList.remove('playing');
playIcon.textContent = '▶';
playText.textContent = 'ENGAGE AMBIENCE';
statAudioStatus.textContent = 'STANDBY';
statAudioStatus.style.color = '#ffcc00';
setTimeout(() => {
isPlaying = false;
isTransitioning = false;
btnPlay.classList.remove('stopping');
playIcon.textContent = '';
playText.textContent = 'ENGAGE';
statAudioStatus.textContent = 'STANDBY';
statAudioStatus.style.color = '#ffcc00';
}, ENGINE_TRANSITION_SECS * 1000);
}
}
@@ -588,7 +653,8 @@ document.addEventListener('DOMContentLoaded', () => {
visualizer.spawnWarpPulses();
break;
case 'solar':
alerts.synthesizeWarpJump();
expandedAudio.synthesizeSolarRoar();
visualizer.spawnWarpPulses();
break;
case 'afterburner':
expandedAudio.synthesizeAfterburner();
@@ -609,7 +675,24 @@ document.addEventListener('DOMContentLoaded', () => {
}
function handleSoundboardTrigger(id) {
const universe = UniverseRegistry[activeUniverseId];
const preset = universe && universe.presets ? universe.presets[activePresetId] : null;
const era = preset ? preset.era : 'tng';
switch (id) {
// Star Trek
case 'btn-comm-badge':
expandedAudio.synthesizeCommBadge();
break;
case 'btn-door-swish':
expandedAudio.synthesizeDoorSwish(era);
break;
case 'btn-bosun-whistle':
expandedAudio.synthesizeBosunWhistle();
break;
case 'btn-medical-monitor':
expandedAudio.synthesizeMedicalMonitor();
break;
case 'btn-chirp-single':
case 'btn-switch-pop':
telemetry.synthesizeLCARSSingleChirp();
@@ -626,9 +709,17 @@ document.addEventListener('DOMContentLoaded', () => {
case 'btn-chirp-door':
telemetry.synthesizeDoorChime();
break;
// Whoniverse
case 'btn-sonic':
whoniverseAudio.synthesizeSonicScrewdriver();
break;
case 'btn-lever-clunk':
whoniverseAudio.synthesizeLeverClunk();
break;
case 'btn-tardis-door':
whoniverseAudio.synthesizeTardisDoor();
break;
case 'btn-fast-return':
whoniverseAudio.synthesizeFastReturn();
break;
@@ -644,33 +735,84 @@ document.addEventListener('DOMContentLoaded', () => {
whoniverseAudio.synthesizeDematSwitch();
telemetry.synthesizeSensorSweep();
break;
// Space Stations
case 'btn-air-handler':
expandedAudio.synthesizeAirHandlerThud();
break;
case 'btn-mag-boot':
expandedAudio.synthesizeMagBootLatch();
break;
case 'btn-commlock':
expandedAudio.synthesizeCommlockTone();
break;
case 'btn-sevas-spark':
expandedAudio.synthesizeSevastopolSpark();
break;
case 'btn-station-ecg':
expandedAudio.synthesizeStationMedicalPing();
break;
case 'btn-tram-gong':
whoniverseAudio.synthesizeCloisterStrike();
break;
// Deep Space
case 'btn-solar-roar':
expandedAudio.synthesizeSolarRoar();
break;
case 'btn-cryo-sigh':
expandedAudio.synthesizeCryoDepressurize();
break;
case 'btn-orion-thump':
expandedAudio.synthesizeOrionPulseThump();
break;
// Outlaw & Frontier
case 'btn-tape-clunk':
expandedAudio.synthesizeCassetteTransport();
break;
case 'btn-grappler-servo':
expandedAudio.synthesizeGrapplerServo();
break;
case 'btn-radio-static':
expandedAudio.synthesizeRadioStatic();
break;
case 'btn-afterburner-snd':
expandedAudio.synthesizeAfterburner();
break;
// Comedy & Adventure
case 'btn-cheerful-door':
expandedAudio.synthesizeCheerfulDoor();
break;
case 'btn-tea-machine':
expandedAudio.synthesizeTeaDispenser();
break;
case 'btn-kettle-whistle':
expandedAudio.synthesizeKettleWhistle();
break;
case 'btn-plaid-alarm':
expandedAudio.synthesizePlaidAlarm();
break;
case 'btn-beryllium-pulse':
expandedAudio.synthesizeImprobabilityFlip();
break;
// General / Industrial / Military
case 'btn-geiger':
expandedAudio.synthesizeGeigerBurst();
break;
case 'btn-dock-clamp':
case 'btn-pneumatic-door':
case 'btn-tape-clunk':
expandedAudio.synthesizeDockingClamp();
break;
case 'btn-air-handler':
expandedAudio.synthesizeAirHandlerThud();
break;
case 'btn-dradis-ping':
expandedAudio.synthesizeDradisPing();
break;
case 'btn-hal-chime':
expandedAudio.synthesizeHalChime();
break;
case 'btn-cheerful-door':
expandedAudio.synthesizeCheerfulDoor();
break;
case 'btn-beryllium-pulse':
case 'btn-tea-machine':
expandedAudio.synthesizeImprobabilityFlip();
break;
case 'btn-tram-gong':
whoniverseAudio.synthesizeCloisterStrike();
break;
default:
telemetry.synthesizeLCARSSingleChirp();
break;
@@ -3960,4 +4102,3 @@ document.addEventListener('DOMContentLoaded', () => {
updateMasterVolumeUI(0.75, false);
visualizer.init('spectrum-canvas', 'warp-core-canvas');
});