fix: make soundtrack loading terminal
This commit is contained in:
@@ -387,7 +387,9 @@ export function createSoundtrackEngine(
|
|||||||
mainSource = main;
|
mainSource = main;
|
||||||
mainSchedule = schedule;
|
mainSchedule = schedule;
|
||||||
attachMainEnded(main);
|
attachMainEnded(main);
|
||||||
for (const source of introSourceNodes) {
|
const committedIntroSources = introSourceNodes;
|
||||||
|
introSourceNodes = [];
|
||||||
|
for (const source of committedIntroSources) {
|
||||||
source.stopAt(transitionTime + EXIT_CROSSFADE_SECONDS);
|
source.stopAt(transitionTime + EXIT_CROSSFADE_SECONDS);
|
||||||
}
|
}
|
||||||
loadedIntroBuffer = null;
|
loadedIntroBuffer = null;
|
||||||
@@ -456,22 +458,24 @@ export function createSoundtrackEngine(
|
|||||||
void mainPromise.catch(() => undefined);
|
void mainPromise.catch(() => undefined);
|
||||||
|
|
||||||
if (activatedFromStart) {
|
if (activatedFromStart) {
|
||||||
loadedIntroBuffer = await dependencies.loadBuffer(context, sources.intro, signal);
|
const [introBuffer, mainBuffer] = await Promise.all([
|
||||||
|
dependencies.loadBuffer(context, sources.intro, signal),
|
||||||
|
mainPromise,
|
||||||
|
]);
|
||||||
if (closed || signal.aborted) throw abortError();
|
if (closed || signal.aborted) throw abortError();
|
||||||
|
loadedIntroBuffer = introBuffer;
|
||||||
if (latestChapter.atStart) {
|
if (latestChapter.atStart) {
|
||||||
transportStarted = true;
|
transportStarted = true;
|
||||||
startIntro(loadedIntroBuffer, context.currentTime + SOURCE_LEAD_SECONDS);
|
startIntro(loadedIntroBuffer, context.currentTime + SOURCE_LEAD_SECONDS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
transportStarted = true;
|
||||||
|
startDirectMain(mainBuffer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainBuffer = await mainPromise;
|
const mainBuffer = await mainPromise;
|
||||||
if (closed || signal.aborted) throw abortError();
|
if (closed || signal.aborted) throw abortError();
|
||||||
if (activatedFromStart && latestChapter.atStart && loadedIntroBuffer !== null) {
|
|
||||||
transportStarted = true;
|
|
||||||
startIntro(loadedIntroBuffer, context.currentTime + SOURCE_LEAD_SECONDS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
transportStarted = true;
|
transportStarted = true;
|
||||||
startDirectMain(mainBuffer);
|
startDirectMain(mainBuffer);
|
||||||
};
|
};
|
||||||
@@ -514,6 +518,16 @@ export function createSoundtrackEngine(
|
|||||||
mixer.dispose();
|
mixer.dispose();
|
||||||
for (const source of [...ownedSources]) source.cancel();
|
for (const source of [...ownedSources]) source.cancel();
|
||||||
ownedSources.clear();
|
ownedSources.clear();
|
||||||
|
pendingIntroExit = null;
|
||||||
|
introSourceNodes = [];
|
||||||
|
introProgramGain = null;
|
||||||
|
mainSource = null;
|
||||||
|
driveLiftSource = null;
|
||||||
|
afterglowSource = null;
|
||||||
|
mainSchedule = null;
|
||||||
|
mainBufferPromise = null;
|
||||||
|
loadPromise = null;
|
||||||
|
exitLoadRequest = null;
|
||||||
context.removeEventListener('statechange', onStateChange);
|
context.removeEventListener('statechange', onStateChange);
|
||||||
stateListeners.clear();
|
stateListeners.clear();
|
||||||
outputGain.disconnect();
|
outputGain.disconnect();
|
||||||
|
|||||||
@@ -306,14 +306,18 @@ describe('soundtrack engine', () => {
|
|||||||
expect(test.mixer.setDriveEnergy).toHaveBeenLastCalledWith(sample);
|
expect(test.mixer.setDriveEnergy).toHaveBeenLastCalledWith(sample);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keeps dominant intro and direct-main load failures terminal', async () => {
|
it('keeps dominant intro and main load failures terminal on every activation path', async () => {
|
||||||
const intro = createEngineHarness(initialState, { rejectIntro: true });
|
const intro = createEngineHarness(initialState, { rejectIntro: true });
|
||||||
await expect(intro.graph.resume()).rejects.toThrow('/intro.opus unavailable');
|
await expect(intro.graph.resume()).rejects.toThrow('/intro.opus unavailable');
|
||||||
const main = createEngineHarness({
|
const startMain = createEngineHarness(initialState, { rejectMain: true });
|
||||||
|
await expect(startMain.graph.resume()).rejects.toThrow('/main.opus unavailable');
|
||||||
|
expect(startMain.sourcesFor('/intro.opus')).toHaveLength(0);
|
||||||
|
|
||||||
|
const directMain = createEngineHarness({
|
||||||
chapter: resolveChapterIntent('profile'),
|
chapter: resolveChapterIntent('profile'),
|
||||||
drive: { energy: 0, source: 'idle' },
|
drive: { energy: 0, source: 'idle' },
|
||||||
}, { rejectMain: true });
|
}, { rejectMain: true });
|
||||||
await expect(main.graph.resume()).rejects.toThrow('/main.opus unavailable');
|
await expect(directMain.graph.resume()).rejects.toThrow('/main.opus unavailable');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('stops and disconnects each owned source exactly once when closed twice', async () => {
|
it('stops and disconnects each owned source exactly once when closed twice', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user