feat(sounds): accept lossless FLAC samples first
- commit
- 665a02e6189303ea50ba589c260b5c8d079153d4
- author
- Kit · · 2026-09-29 08:00 UTC
- parent
- f4b3b19
- signature
- SSH Unverified
SHA256:H91DFuEG4jpk5edzLA4aUKkpv4zv9Q339ipRmkph6TkThe key is unknown
2 files · +6 -3
M src/lib/aim/sounds.svelte.ts +3 -2
| @@ -234,7 +234,7 @@ export const SOUND_DURATIONS_MS: Record<AimSound, number> = { | |||
| 234 | 234 | // Not UI state, so a plain Map is intended. | |
| 235 | 235 | // eslint-disable-next-line svelte/prefer-svelte-reactivity | |
| 236 | 236 | const samples = new Map<AimSound, Promise<AudioBuffer | null>>(); | |
| 237 | - | const SAMPLE_EXTENSIONS = ['mp3', 'wav', 'ogg']; | |
| 237 | + | const SAMPLE_EXTENSIONS = ['flac', 'mp3', 'wav', 'ogg']; | |
| 238 | 238 | ||
| 239 | 239 | function loadSample(ac: AudioContext, name: AimSound): Promise<AudioBuffer | null> { | |
| 240 | 240 | let pending = samples.get(name); | |
| @@ -243,7 +243,8 @@ function loadSample(ac: AudioContext, name: AimSound): Promise<AudioBuffer | nul | |||
| 243 | 243 | for (const ext of SAMPLE_EXTENSIONS) { | |
| 244 | 244 | try { | |
| 245 | 245 | const res = await fetch(`/sounds/${name}.${ext}`, { cache: 'force-cache' }); | |
| 246 | - | if (!res.ok || !(res.headers.get('content-type') ?? '').startsWith('audio/')) continue; | |
| 246 | + | // Skip HTML fallbacks; some servers send .flac without an audio/* type | |
| 247 | + | if (!res.ok || (res.headers.get('content-type') ?? '').startsWith('text/')) continue; | |
| 247 | 248 | return await ac.decodeAudioData(await res.arrayBuffer()); | |
| 248 | 249 | } catch { | |
| 249 | 250 | // try next extension | |
| @@ -234,7 +234,7 @@ export const SOUND_DURATIONS_MS: Record<AimSound, number> = { | |||||
| 234 | // Not UI state, so a plain Map is intended. | 234 | // Not UI state, so a plain Map is intended. | ||
| 235 | // eslint-disable-next-line svelte/prefer-svelte-reactivity | 235 | // eslint-disable-next-line svelte/prefer-svelte-reactivity | ||
| 236 | const samples = new Map<AimSound, Promise<AudioBuffer | null>>(); | 236 | const samples = new Map<AimSound, Promise<AudioBuffer | null>>(); | ||
| 237 | - | const SAMPLE_EXTENSIONS = ['mp3', 'wav', 'ogg']; | 237 | + | const SAMPLE_EXTENSIONS = ['flac', 'mp3', 'wav', 'ogg']; |
| 238 | 238 | ||||
| 239 | function loadSample(ac: AudioContext, name: AimSound): Promise<AudioBuffer | null> { | 239 | function loadSample(ac: AudioContext, name: AimSound): Promise<AudioBuffer | null> { | ||
| 240 | let pending = samples.get(name); | 240 | let pending = samples.get(name); | ||
| @@ -243,7 +243,8 @@ function loadSample(ac: AudioContext, name: AimSound): Promise<AudioBuffer | nul | |||||
| 243 | for (const ext of SAMPLE_EXTENSIONS) { | 243 | for (const ext of SAMPLE_EXTENSIONS) { | ||
| 244 | try { | 244 | try { | ||
| 245 | const res = await fetch(`/sounds/${name}.${ext}`, { cache: 'force-cache' }); | 245 | const res = await fetch(`/sounds/${name}.${ext}`, { cache: 'force-cache' }); | ||
| 246 | - | if (!res.ok || !(res.headers.get('content-type') ?? '').startsWith('audio/')) continue; | 246 | + | // Skip HTML fallbacks; some servers send .flac without an audio/* type |
| 247 | + | if (!res.ok || (res.headers.get('content-type') ?? '').startsWith('text/')) continue; | |||
| 247 | return await ac.decodeAudioData(await res.arrayBuffer()); | 248 | return await ac.decodeAudioData(await res.arrayBuffer()); | ||
| 248 | } catch { | 249 | } catch { | ||
| 249 | // try next extension | 250 | // try next extension | ||
M static/sounds/README.md +3 -1
| @@ -16,5 +16,7 @@ Pour retrouver les vrais sons, déposer ici : | |||
| 16 | 16 | | `welcome.wav` | Welcome.wav | | |
| 17 | 17 | | `modem.wav` | (optionnel) | | |
| 18 | 18 | ||
| 19 | - | Formats acceptés : `.wav`, `.mp3`, `.ogg`. Source archivée connue : | |
| 19 | + | Formats acceptés (dans cet ordre) : `.flac`, `.mp3`, `.wav`, `.ogg`. Pour les gros | |
| 20 | + | fichiers, `.flac` est sans perte et bien plus léger : | |
| 21 | + | `ffmpeg -i modem.wav -c:a flac -compression_level 12 modem.flac`. Source archivée connue : | |
| 20 | 22 | <https://archive.org/details/im_20191103>. | |
| @@ -16,5 +16,7 @@ Pour retrouver les vrais sons, déposer ici : | |||||
| 16 | | `welcome.wav` | Welcome.wav | | 16 | | `welcome.wav` | Welcome.wav | | ||
| 17 | | `modem.wav` | (optionnel) | | 17 | | `modem.wav` | (optionnel) | | ||
| 18 | 18 | ||||
| 19 | - | Formats acceptés : `.wav`, `.mp3`, `.ogg`. Source archivée connue : | 19 | + | Formats acceptés (dans cet ordre) : `.flac`, `.mp3`, `.wav`, `.ogg`. Pour les gros |
| 20 | + | fichiers, `.flac` est sans perte et bien plus léger : | |||
| 21 | + | `ffmpeg -i modem.wav -c:a flac -compression_level 12 modem.flac`. Source archivée connue : | |||
| 20 | <https://archive.org/details/im_20191103>. | 22 | <https://archive.org/details/im_20191103>. | ||