"use strict"; const AsteroidThreatAlarmSound = (function(){ return function(audio_ctx, output_node, volume_multiplier = 1.0, threat_level = 0.5){ const now = audio_ctx.currentTime; const threat = Math.max(0.0, Math.min(1.0, threat_level)); // Bus maestro de cabina const master_bus = audio_ctx.createGain(); master_bus.gain.setValueAtTime(volume_multiplier * 0.5, now); // Filtro de megafonía/altavoz de instrumentación (elimina graves y agudos molestos) const horn_filter = audio_ctx.createBiquadFilter(); horn_filter.type = "bandpass"; horn_filter.frequency.setValueAtTime(1150, now); horn_filter.Q.setValueAtTime(1.8, now); master_bus.connect(horn_filter); horn_filter.connect(output_node); // Función que sintetiza un 'BEEP' limpio de aviónica const trigger_avionics_beep = (start_time, freq) => { const beep_duration = 0.065; // 65ms: corto, clínico y penetrante // Envolvente de amplitud trapezoidal (ataque 4ms, salida 8ms) const env = audio_ctx.createGain(); env.gain.setValueAtTime(0.0001, start_time); env.gain.linearRampToValueAtTime(0.85, start_time + 0.004); env.gain.setValueAtTime(0.85, start_time + beep_duration - 0.008); env.gain.exponentialRampToValueAtTime(0.0001, start_time + beep_duration); // 1. Tono fundamental limpio const osc_main = audio_ctx.createOscillator(); osc_main.type = "sine"; osc_main.frequency.setValueAtTime(freq, start_time); // 2. Segundo armónico discreto (le da presencia de instrumento de cabina) const osc_harm = audio_ctx.createOscillator(); const harm_gain = audio_ctx.createGain(); osc_harm.type = "sine"; osc_harm.frequency.setValueAtTime(freq * 2, start_time); harm_gain.gain.setValueAtTime(0.18, start_time); // 3. Toque de onda triangular sutil para cuerpo mecánico const osc_tri = audio_ctx.createOscillator(); const tri_gain = audio_ctx.createGain(); osc_tri.type = "triangle"; osc_tri.frequency.setValueAtTime(freq, start_time); tri_gain.gain.setValueAtTime(0.12, start_time); osc_main.connect(env); osc_harm.connect(harm_gain); harm_gain.connect(env); osc_tri.connect(tri_gain); tri_gain.connect(env); env.connect(master_bus); osc_main.start(start_time); osc_harm.start(start_time); osc_tri.start(start_time); osc_main.stop(start_time + beep_duration); osc_harm.stop(start_time + beep_duration); osc_tri.stop(start_time + beep_duration); }; // Frecuencia estándar de advertencia: 1020 Hz (tono aeronáutico estándar) // Si la piedra viene de camino a la cabina (> 0.6), sube ligeramente a 1280 Hz const base_freq = threat > 0.6 ? 1280 : 1020; // Primer beep trigger_avionics_beep(now, base_freq); // Si el peligro es inminente (la roca ya fue lanzada a cabina), emite un doble beep militar ("PIP-PIP") if(threat > 0.6){ trigger_avionics_beep(now + 0.09, base_freq); } }; })();