From 57e744784e28618ec9a00c3500dd2d509f14f3a1 Mon Sep 17 00:00:00 2001 From: Rikki Date: Sat, 19 Apr 2025 16:53:56 +0800 Subject: change pitch when playing --- scripts/main.js | 152 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 112 insertions(+), 40 deletions(-) (limited to 'scripts/main.js') diff --git a/scripts/main.js b/scripts/main.js index e3e2546..8f62173 100644 --- a/scripts/main.js +++ b/scripts/main.js @@ -16,7 +16,7 @@ const COMMANDS = [ ]; // Built-in handlers not in COMMANDS -const BUILTIN_COMMANDS = ['su','sudo','shutdown','reboot','echo','df','pwd','cat','top','rm','ls','oiia']; +const BUILTIN_COMMANDS = ['su', 'sudo', 'shutdown', 'reboot', 'echo', 'df', 'pwd', 'cat', 'top', 'rm', 'ls', 'oiia']; // Consolidated for autocomplete const ALL_COMMANDS = [ @@ -64,42 +64,113 @@ const delay = ms => { const randomElement = arr => arr[Math.floor(Math.random() * arr.length)]; // --------- Audio Playback --------- -async function playSound(file, playSpeed = 1, minTime = null) { - const ctx = new AudioContext(); +function unlockAudio() { + const ctx = getAudioCtx(); + if (ctx.state === 'suspended') { + ctx.resume() + } +} + +const AudioCtx = window.AudioContext ?? window.webkitAudioContext; +let audioCtx; +function getAudioCtx() { + if (!audioCtx) audioCtx = new AudioCtx(); + return audioCtx; +} + +async function playSound(file, speed = 1, loops = 1) { + if (loops <= 0) return; + + const ctx = getAudioCtx(); + if (ctx.state === 'suspended') { + await ctx.resume(); + } + try { - const response = await fetch(file); - const arrayBuffer = await response.arrayBuffer(); - const buffer = await ctx.decodeAudioData(arrayBuffer); - - const singleDur = buffer.duration / playSpeed; - const targetTime = minTime != null ? minTime : singleDur; - const loops = Math.ceil(targetTime / singleDur); - const totalDur = loops * singleDur; - const startTime = ctx.currentTime; - const stopTime = startTime + totalDur; - const fadeTime = Math.min(0.1, totalDur / 2); + const resp = await fetch(file, { mode: 'cors' }); + if (!resp.ok) throw new Error(`HTTP ${resp.status}`); + const data = await resp.arrayBuffer(); + + const buffer = await ctx.decodeAudioData(data); const src = ctx.createBufferSource(); - src.buffer = buffer; - src.playbackRate.value = playSpeed; - src.loop = true; + src.buffer = buffer; + src.playbackRate.value = speed; + src.loop = loops > 1; src.connect(ctx.destination); - src.start(startTime); - src.stop(stopTime); - - return new Promise(resolve => { - setTimeout(() => { - ctx.close(); - resolve(totalDur); - }, totalDur * 1000 + 20); + src.start(); + + if (loops > 1) { + const totalTime = (buffer.duration / speed) * loops; + src.stop(ctx.currentTime + totalTime); + } + + return new Promise((resolve, reject) => { + src.onended = () => { + resolve(); + }; }); } catch (err) { - console.error('Error loading audio file:', err); - throw err; + // console.warn('⚠️ WebAudio path failed, falling back to HTMLAudioElement:', err); + // return _playWithAudioElement(file, speed, loops); + + console.error('❌ Failed to play sound:', err); } } +// function _playWithAudioElement(file, speed, loops) { +// if (loops <= 0) return Promise.resolve(); + +// const audio = new Audio(file); +// audio.preload = 'auto'; +// audio.crossOrigin = 'anonymous'; +// audio.playbackRate = speed; + +// let remaining = loops; + +// audio.addEventListener('ended', onEnded); +// audio.addEventListener('error', onError); + +// function onEnded() { +// remaining--; +// if (remaining > 0) { +// audio.currentTime = 0; +// audio.play().catch(onError); +// } else { +// cleanup(); +// resolvePromise(); +// } +// } + +// function onError(e) { +// cleanup(); +// rejectPromise(e); +// } + +// function cleanup() { +// audio.pause(); +// audio.currentTime = 0; +// audio.removeEventListener('ended', onEnded); +// audio.removeEventListener('error', onError); +// } + +// let resolvePromise, rejectPromise; +// const p = new Promise((res, rej) => { +// resolvePromise = res; +// rejectPromise = rej; +// }); + +// // kick it off +// audio.play() +// .catch(err => { +// console.error('❌