mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-09-04 09:13:24 +00:00
FIX - use packaged 2048 sound effects
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,77 +1,42 @@
|
|||||||
|
import gameOverUrl from '@/assets/audio/number-merge/game-over.wav?url'
|
||||||
|
import mergeUrl from '@/assets/audio/number-merge/merge.wav?url'
|
||||||
|
import moveUrl from '@/assets/audio/number-merge/move.wav?url'
|
||||||
|
import winUrl from '@/assets/audio/number-merge/win.wav?url'
|
||||||
|
|
||||||
export type NumberMergeSound = 'game-over' | 'merge' | 'move' | 'win'
|
export type NumberMergeSound = 'game-over' | 'merge' | 'move' | 'win'
|
||||||
|
|
||||||
type Tone = {
|
const soundUrls: Record<NumberMergeSound, string> = {
|
||||||
duration: number
|
'game-over': gameOverUrl,
|
||||||
frequency: number
|
merge: mergeUrl,
|
||||||
offset: number
|
move: moveUrl,
|
||||||
type: OscillatorType
|
win: winUrl,
|
||||||
volume: number
|
|
||||||
}
|
}
|
||||||
|
const playerPools = new Map<NumberMergeSound, HTMLAudioElement[]>()
|
||||||
|
|
||||||
const sounds: Record<NumberMergeSound, Tone[]> = {
|
function getPlayers(sound: NumberMergeSound): HTMLAudioElement[] {
|
||||||
move: [{ duration: 0.065, frequency: 290, offset: 0, type: 'sine', volume: 0.085 }],
|
const existing = playerPools.get(sound)
|
||||||
merge: [
|
if (existing) return existing
|
||||||
{ duration: 0.1, frequency: 390, offset: 0, type: 'sine', volume: 0.1 },
|
|
||||||
{ duration: 0.14, frequency: 540, offset: 0.055, type: 'sine', volume: 0.12 },
|
const players = Array.from({ length: 3 }, () => {
|
||||||
],
|
const player = new Audio(soundUrls[sound])
|
||||||
win: [
|
player.preload = 'auto'
|
||||||
{ duration: 0.16, frequency: 523.25, offset: 0, type: 'sine', volume: 0.08 },
|
player.volume = 0.82
|
||||||
{ duration: 0.16, frequency: 659.25, offset: 0.1, type: 'sine', volume: 0.085 },
|
return player
|
||||||
{ duration: 0.16, frequency: 783.99, offset: 0.2, type: 'sine', volume: 0.09 },
|
})
|
||||||
{ duration: 0.3, frequency: 1046.5, offset: 0.3, type: 'sine', volume: 0.1 },
|
playerPools.set(sound, players)
|
||||||
],
|
return players
|
||||||
'game-over': [
|
|
||||||
{ duration: 0.14, frequency: 260, offset: 0, type: 'triangle', volume: 0.065 },
|
|
||||||
{ duration: 0.18, frequency: 195, offset: 0.12, type: 'triangle', volume: 0.06 },
|
|
||||||
{ duration: 0.22, frequency: 146, offset: 0.26, type: 'triangle', volume: 0.055 },
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let audioContext: AudioContext | undefined
|
|
||||||
|
|
||||||
export function playNumberMergeSound(
|
export function playNumberMergeSound(
|
||||||
sound: NumberMergeSound,
|
sound: NumberMergeSound,
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
): void {
|
): void {
|
||||||
if (!enabled) return
|
if (!enabled) return
|
||||||
|
|
||||||
const AudioContextConstructor =
|
const players = getPlayers(sound)
|
||||||
window.AudioContext ??
|
const player = players.find((candidate) => candidate.paused) ?? players[0]
|
||||||
(window as typeof window & { webkitAudioContext?: typeof AudioContext })
|
player.currentTime = 0
|
||||||
.webkitAudioContext
|
void player.play().catch((error: unknown) => {
|
||||||
if (!AudioContextConstructor) {
|
console.error(`[2048 audio] Failed to play ${sound}`, error)
|
||||||
console.error('[2048 audio] Web Audio is unavailable')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
audioContext ??= new AudioContextConstructor()
|
|
||||||
const context = audioContext
|
|
||||||
|
|
||||||
const scheduleSound = (): void => {
|
|
||||||
const now = context.currentTime + 0.02
|
|
||||||
for (const tone of sounds[sound]) {
|
|
||||||
const oscillator = context.createOscillator()
|
|
||||||
const gain = context.createGain()
|
|
||||||
const start = now + tone.offset
|
|
||||||
const end = start + tone.duration
|
|
||||||
|
|
||||||
oscillator.type = tone.type
|
|
||||||
oscillator.frequency.setValueAtTime(tone.frequency, start)
|
|
||||||
gain.gain.setValueAtTime(0.0001, start)
|
|
||||||
gain.gain.linearRampToValueAtTime(tone.volume, start + 0.012)
|
|
||||||
gain.gain.exponentialRampToValueAtTime(0.0001, end)
|
|
||||||
oscillator.connect(gain).connect(context.destination)
|
|
||||||
oscillator.start(start)
|
|
||||||
oscillator.stop(end + 0.01)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.state === 'running') {
|
|
||||||
scheduleSound()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
void context.resume().then(scheduleSound).catch((error: unknown) => {
|
|
||||||
console.error('[2048 audio] Failed to start sound', error)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user