feat: coordinate adaptive audio intent
This commit is contained in:
@@ -1,25 +1,56 @@
|
||||
import type { AudioJourneyState } from '@/audio/types';
|
||||
import type { SectionId } from '@/content/types';
|
||||
import type {
|
||||
AudioJourneyState,
|
||||
ChapterIntent,
|
||||
DriveEnergySample,
|
||||
MusicMood,
|
||||
} from '@/audio/types';
|
||||
|
||||
const JOURNEY_MUSIC = Object.freeze({
|
||||
start: { bias: 'open', entryPhrase: 0 },
|
||||
profile: { bias: 'open', entryPhrase: 1 },
|
||||
experience: { bias: 'shadow', entryPhrase: 2 },
|
||||
infrastructure: { bias: 'shadow', entryPhrase: 3 },
|
||||
'selected-builds': { bias: 'lift', entryPhrase: 4 },
|
||||
'additional-work': { bias: 'lift', entryPhrase: 5 },
|
||||
toolkit: { bias: 'resolve', entryPhrase: 6 },
|
||||
contact: { bias: 'resolve', entryPhrase: 7 },
|
||||
} as const);
|
||||
start: { mood: 'open', entryPhrase: 0 },
|
||||
profile: { mood: 'open', entryPhrase: 1 },
|
||||
experience: { mood: 'shadow', entryPhrase: 2 },
|
||||
infrastructure: { mood: 'shadow', entryPhrase: 3 },
|
||||
'selected-builds': { mood: 'lift', entryPhrase: 4 },
|
||||
'additional-work': { mood: 'lift', entryPhrase: 5 },
|
||||
toolkit: { mood: 'resolve', entryPhrase: 6 },
|
||||
contact: { mood: 'resolve', entryPhrase: 7 },
|
||||
} as const satisfies Readonly<Record<
|
||||
SectionId,
|
||||
{ readonly mood: MusicMood; readonly entryPhrase: number }
|
||||
>>);
|
||||
|
||||
export function resolveChapterIntent(
|
||||
sectionId: SectionId,
|
||||
generation = 0,
|
||||
): ChapterIntent {
|
||||
const chapter = JOURNEY_MUSIC[sectionId];
|
||||
return Object.freeze({
|
||||
sectionId,
|
||||
mood: chapter.mood,
|
||||
atStart: sectionId === 'start',
|
||||
entryPhrase: chapter.entryPhrase,
|
||||
generation: Math.max(0, Math.trunc(generation)),
|
||||
});
|
||||
}
|
||||
|
||||
export const DEFAULT_CHAPTER_INTENT = resolveChapterIntent('start');
|
||||
export const DEFAULT_DRIVE_ENERGY = Object.freeze({
|
||||
energy: 0,
|
||||
source: 'idle',
|
||||
} as const satisfies DriveEnergySample);
|
||||
|
||||
export function resolveJourneyMusicState(sectionId: string, intensity = 0): AudioJourneyState {
|
||||
const chapter = Object.hasOwn(JOURNEY_MUSIC, sectionId)
|
||||
? JOURNEY_MUSIC[sectionId as keyof typeof JOURNEY_MUSIC]
|
||||
: JOURNEY_MUSIC.start;
|
||||
const canonicalId = Object.hasOwn(JOURNEY_MUSIC, sectionId)
|
||||
? sectionId as SectionId
|
||||
: 'start';
|
||||
const chapter = resolveChapterIntent(canonicalId);
|
||||
const finiteIntensity = Number.isFinite(intensity) ? intensity : 0;
|
||||
return Object.freeze({
|
||||
...chapter,
|
||||
atStart: sectionId === 'start',
|
||||
intensity: Math.min(1, Math.max(0, finiteIntensity)),
|
||||
bias: chapter.mood,
|
||||
entryPhrase: chapter.entryPhrase,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user