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:
@@ -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');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user