vue.js used

This commit is contained in:
cpu
2025-05-07 22:17:29 +02:00
parent 049866ecd7
commit 04dd879c24
33 changed files with 4471 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
let audioContext;
let tickSoundBuffer; // For short tick
let passTurnSoundBuffer; // For 3s pass turn alert
let isMutedGlobally = false;
let continuousTickInterval = null; // For setInterval based continuous ticking
let passTurnSoundTimeout = null;
function getAudioContext() {
if (!audioContext && (window.AudioContext || window.webkitAudioContext)) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
return audioContext;
}
function createBeepBuffer(frequency = 440, duration = 0.1, type = 'sine') {
const ctx = getAudioContext();
if (!ctx) return null;
const sampleRate = ctx.sampleRate;
const numFrames = duration * sampleRate;
const buffer = ctx.createBuffer(1, numFrames, sampleRate);
const data = buffer.getChannelData(0);
const gain = 0.1; // Reduce gain to make beeps softer
for (let i = 0; i < numFrames; i++) {
// Simple fade out
const currentGain = gain * (1 - (i / numFrames));
if (type === 'square') {
data[i] = (Math.sin(2 * Math.PI * frequency * (i / sampleRate)) >= 0 ? 1 : -1) * currentGain;
} else { // sine
data[i] = Math.sin(2 * Math.PI * frequency * (i / sampleRate)) * currentGain;
}
}
return buffer;
}
async function initSounds() {
const ctx = getAudioContext();
if (!ctx) return;
// Tick sound (shorter, slightly different pitch)
if (!tickSoundBuffer) {
// Using a square wave for a more 'digital' tick, short duration
tickSoundBuffer = createBeepBuffer(1000, 0.03, 'square');
}
// Pass turn alert sound (3 beeps)
if (!passTurnSoundBuffer) {
passTurnSoundBuffer = createBeepBuffer(660, 0.08, 'sine');
}
}
initSounds();
function playSoundBuffer(buffer) {
if (isMutedGlobally || !buffer || !audioContext || audioContext.state === 'suspended') return;
const source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start();
}
export const AudioService = {
setMuted(muted) {
isMutedGlobally = muted;
if (muted) {
this.stopContinuousTick();
this.cancelPassTurnSound();
}
},
// This is the single, short tick sound for "All Timers Running" mode.
_playSingleTick() {
playSoundBuffer(tickSoundBuffer);
},
playPassTurnAlert() {
if (isMutedGlobally || !audioContext || audioContext.state === 'suspended') return;
this.cancelPassTurnSound();
let count = 0;
const playAndSchedule = () => {
if (count < 3 && !isMutedGlobally && audioContext.state !== 'suspended') {
playSoundBuffer(passTurnSoundBuffer);
count++;
passTurnSoundTimeout = setTimeout(playAndSchedule, 1000); // Beep every second for 3s
} else {
passTurnSoundTimeout = null;
}
};
playAndSchedule();
},
cancelPassTurnSound() {
if (passTurnSoundTimeout) {
clearTimeout(passTurnSoundTimeout);
passTurnSoundTimeout = null;
}
},
startContinuousTick() {
this.stopContinuousTick(); // Clear any existing interval
if (isMutedGlobally || !audioContext || audioContext.state === 'suspended') return;
// Play immediately once, then set interval
this._playSingleTick();
continuousTickInterval = setInterval(() => {
if (!isMutedGlobally && audioContext.state !== 'suspended') {
this._playSingleTick();
} else {
this.stopContinuousTick(); // Stop if muted or context suspended during interval
}
}, 1000); // Tick every second
},
stopContinuousTick() {
if (continuousTickInterval) {
clearInterval(continuousTickInterval);
continuousTickInterval = null;
}
// Ensure no rogue oscillators are playing.
// If an oscillator was ever used directly and not disconnected, it could persist.
// The current implementation relies on BufferSource which stops automatically.
},
resumeContext() {
const ctx = getAudioContext();
if (ctx && ctx.state === 'suspended') {
ctx.resume().then(() => {
console.log("AudioContext resumed successfully.");
initSounds(); // Re-initialize sounds if context was suspended for long
}).catch(e => console.error("Error resuming AudioContext:", e));
} else if (ctx && !tickSoundBuffer) { // If context was fine but sounds not loaded
initSounds();
}
}
};