Load the sounds of a project ahead of their first play

A sound was fetched and decoded on its first Play sound. That play
started late, its beginning was not heard, and a graph that tuned the
voice in the meantime had moved on by the time it started. Images and
fonts were already loaded when a project opens. Sounds now are too.

- projectFiles lists the sounds of a project, and preloadProjectFiles
  hands them to the new soundLibrary.preload. That covers the editor
  and the published game.
- Preloading opens no audio device. It decodes with an
  OfflineAudioContext at 48 kHz. The real AudioContext is still made
  on the first play, and a source resamples where the device runs at
  another rate.
- A run started right after opening a project can still find a sound
  loading. It then starts late as before.

Tests:
- sound-library: a preload makes only the offline context, and a
  play after it starts at once, opening the device only then.
- sound-library + project-files: 18 tests, green.
- e2e 34 on melektaus-atx: ALL PASSED, 30 checks.
- Counter-check: decoding with the real AudioContext again fails the
  new test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-05 21:47:00 +02:00
1 parent ded0022903
commit ed2b58b3c0
5 files changed
+72 -8

No files matched your search

+5 -2
View File
@@ -1,13 +1,15 @@
import { isFontFile } from './font';
import { celFilesOf } from './pixelart';
import type { Project } from './Project';
import { isSoundFile } from './sound';
import { isTextureFile } from './texture';
/** The stored files a project draws with, per library – what is loaded before anything asks. */
/** The stored files a project draws and plays, per library – what is loaded before anything asks. */
export interface ProjectFiles {
textures: string[];
fonts: string[];
cels: string[];
sounds: string[];
}
/**
@@ -16,11 +18,12 @@ export interface ProjectFiles {
* an upload that failed – is left out, as the libraries would never get it anyway.
*/
export function projectFiles(project: Project): ProjectFiles {
const files: ProjectFiles = { textures: [], fonts: [], cels: [] };
const files: ProjectFiles = { textures: [], fonts: [], cels: [], sounds: [] };
for (const asset of project.assets) {
if (asset.type === 'texture' && isTextureFile(asset.file)) files.textures.push(asset.file);
else if (asset.type === 'font' && isFontFile(asset.file)) files.fonts.push(asset.file);
else if (asset.type === 'pixelart') files.cels.push(...celFilesOf(asset));
else if (asset.type === 'sound' && isSoundFile(asset.file)) files.sounds.push(asset.file);
}
return files;
}