Effetti sonori sci-fi: sweep, modulazione, beacon e arpeggi via aevalsrc
This commit is contained in:
+31
-18
@@ -422,39 +422,52 @@ function cancelRecording(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Feedback sonori (bip) per le interazioni con la registrazione
|
// Feedback sonori sci-fi (sintesi procedurale ffmpeg)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
type SoundType = "start" | "stop" | "cancel" | "timeout" | "done";
|
type SoundType = "start" | "stop" | "cancel" | "timeout" | "done";
|
||||||
|
|
||||||
const SOUNDS: Record<SoundType, { freq: number; dur: number; repeat?: number }> = {
|
// Espressioni aevalsrc per effetti fantascientifici
|
||||||
start: { freq: 880, dur: 0.15 }, // bip acuto breve (inizio)
|
const SOUNDS: Record<SoundType, { expr: string; dur: string }> = {
|
||||||
stop: { freq: 660, dur: 0.25 }, // conferma
|
// Power up: sweep ascendente 440→1760Hz
|
||||||
cancel: { freq: 220, dur: 0.3 }, // tono basso (annullamento)
|
start: { expr: "sin(2*PI*(440+1320*t/0.15)*t)*(1-t/0.15)", dur: "0.15" },
|
||||||
timeout: { freq: 440, dur: 0.4, repeat: 2 }, // doppio bip di avviso
|
// Deactivate: sweep discendente 1200→300Hz
|
||||||
done: { freq: 990, dur: 0.2 }, // completamento (successo)
|
stop: { expr: "sin(2*PI*(1200-900*t/0.18)*t)*(1-t/0.18)", dur: "0.18" },
|
||||||
|
// Error/Abort: modulato discendente a bassa freq
|
||||||
|
cancel: { expr: "sin(2*PI*(350-200*t/0.35)*t)*exp(-2*t)*(1+0.3*sin(2*PI*8*t))", dur: "0.35" },
|
||||||
|
// Warning beacon: pulsazione bi-tono (radar)
|
||||||
|
timeout: { expr: "if(lt(mod(t,0.5),0.15),sin(2*PI*700*t),if(lt(mod(t,0.5),0.35),0,sin(2*PI*500*t)))*0.8", dur: "1.2" },
|
||||||
|
// Success chime: arpeggio Do-Mi-Sol acuto
|
||||||
|
done: { expr: "if(lt(t,0.08),sin(2*PI*523*t),if(lt(t,0.16),sin(2*PI*659*t),sin(2*PI*784*t)))*(1-0.3*t)", dur: "0.28" },
|
||||||
};
|
};
|
||||||
|
|
||||||
function playSound(type: SoundType) {
|
function playSound(type: SoundType) {
|
||||||
const cfg = SOUNDS[type];
|
const cfg = SOUNDS[type];
|
||||||
if (!cfg) return;
|
if (!cfg) return;
|
||||||
const wav = path.join(os.tmpdir(), `agy-sound-${type}-${Date.now()}.wav`);
|
const wav = path.join(os.tmpdir(), `agy-sound-${type}-${Date.now()}.wav`);
|
||||||
const { freq, dur, repeat = 1 } = cfg;
|
// genera il tono sci-fi con ffmpeg (silenzioso) e riproduce con paplay/aplay/ffplay
|
||||||
// genera il tono con ffmpeg (silenzioso) e riproduce con paplay/aplay/ffplay
|
|
||||||
try {
|
try {
|
||||||
execFileAsync(
|
execFileAsync(
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
["-hide_banner", "-loglevel", "error", "-y", "-f", "lavfi", "-i", `sine=frequency=${freq}:duration=${dur}`, wav],
|
[
|
||||||
|
"-hide_banner",
|
||||||
|
"-loglevel",
|
||||||
|
"error",
|
||||||
|
"-y",
|
||||||
|
"-f",
|
||||||
|
"lavfi",
|
||||||
|
"-i",
|
||||||
|
`aevalsrc='${cfg.expr}':d=${cfg.dur}:s=44100`,
|
||||||
|
wav,
|
||||||
|
],
|
||||||
{ timeout: 10_000 },
|
{ timeout: 10_000 },
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
for (let i = 0; i < repeat; i++) {
|
execFileAsync("paplay", [wav], { timeout: 5000 }).catch(() => {
|
||||||
execFileAsync("paplay", [wav], { timeout: 5000 }).catch(() => {
|
// fallback su aplay/ffplay se paplay non disponibile
|
||||||
// fallback su aplay/ffplay se paplay non disponibile
|
execFileAsync("aplay", ["-q", wav], { timeout: 5000 }).catch(() => {
|
||||||
execFileAsync("aplay", ["-q", wav], { timeout: 5000 }).catch(() => {
|
execFileAsync("ffplay", ["-nodisp", "-autoexit", wav], { timeout: 5000 }).catch(() => {});
|
||||||
execFileAsync("ffplay", ["-nodisp", "-autoexit", wav], { timeout: 5000 }).catch(() => {});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
// pulizia
|
// pulizia
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
@@ -462,7 +475,7 @@ function playSound(type: SoundType) {
|
|||||||
} catch {
|
} catch {
|
||||||
/* ignora */
|
/* ignora */
|
||||||
}
|
}
|
||||||
}, repeat * 1500);
|
}, 3000);
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user