XGravity/Public/ecma/Sounds/AsteroidThreatAlarmSound.ecma.js

82 lines
3.3 KiB
JavaScript

"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);
}
};
})();