fix: align audiovisual and narrative feedback
This commit is contained in:
@@ -48,7 +48,7 @@ try {
|
||||
const { campaignBattleRouteEntries } = await server.ssrLoadModule(
|
||||
'/src/game/state/campaignRouting.ts'
|
||||
);
|
||||
const { musicTracks, ambienceTracks } = await server.ssrLoadModule(
|
||||
const { ambienceTrackGainCompensation, musicTracks, ambienceTracks } = await server.ssrLoadModule(
|
||||
'/src/game/audio/audioAssets.ts'
|
||||
);
|
||||
const { campSkinDefinitions, campSkinBattleArcs } = await server.ssrLoadModule(
|
||||
@@ -197,7 +197,12 @@ try {
|
||||
const environment = battleEnvironmentProfiles[battleId];
|
||||
const expectedAmbienceKey = environment?.soundscape.ambienceKey ?? profile?.arc.audio.defaultAmbienceKey;
|
||||
const expectedAmbienceVolume = environment?.soundscape.ambienceVolume ??
|
||||
campaignBattleAmbienceFallbackVolume(profile?.arc.audio.defaultAmbienceVolume);
|
||||
campaignBattleAmbienceFallbackVolume(
|
||||
profile?.arc.audio.defaultAmbienceVolume,
|
||||
profile?.arc.audio.defaultAmbienceKey,
|
||||
profile?.arc.audio.battleMusicKey,
|
||||
profile?.arc.audio.anchorMusicVolume
|
||||
);
|
||||
assertEqual(battlePlan?.musicKey, profile?.arc.audio.battleMusicKey, `${battleId}: battle music plan`);
|
||||
assertEqual(battlePlan?.ambienceKey, expectedAmbienceKey, `${battleId}: battle ambience plan`);
|
||||
assertEqual(battlePlan?.ambienceVolume, expectedAmbienceVolume, `${battleId}: battle ambience volume`);
|
||||
@@ -218,6 +223,47 @@ try {
|
||||
'battle ambience fallback count'
|
||||
);
|
||||
|
||||
[
|
||||
[battleIds[0], 'campfire-ambience', 0.166],
|
||||
[battleIds[16], 'mountain-wind-ambience', 0.153],
|
||||
[battleIds[32], 'river-night-ambience', 0.093],
|
||||
[battleIds[53], 'nanzhong-night-ambience', 0.084]
|
||||
].forEach(([battleId, ambienceKey, expectedVolume]) => {
|
||||
const plan = resolveCampaignPresentationSoundscape({ battleId, stage: 'battle' });
|
||||
assertEqual(plan?.ambienceKey, ambienceKey, `${battleId}: calibrated fallback track`);
|
||||
assertEqual(plan?.ambienceVolume, expectedVolume, `${battleId}: calibrated fallback target volume`);
|
||||
});
|
||||
const quietStoryCampfirePlan = resolveCampaignPresentationSoundscape({ battleId: battleIds[9], stage: 'battle' });
|
||||
const quietFrontierMountainPlan = resolveCampaignPresentationSoundscape({ battleId: battleIds[54], stage: 'battle' });
|
||||
assert(
|
||||
quietStoryCampfirePlan?.musicKey === 'story-dark' &&
|
||||
quietStoryCampfirePlan.ambienceKey === 'campfire-ambience' &&
|
||||
quietStoryCampfirePlan.ambienceVolume <= 0.085,
|
||||
`${quietStoryCampfirePlan?.battleId}: quiet story-dark pairing must attenuate campfire fallback`
|
||||
);
|
||||
assert(
|
||||
quietFrontierMountainPlan?.musicKey === 'camp-frontier' &&
|
||||
quietFrontierMountainPlan.ambienceKey === 'mountain-wind-ambience' &&
|
||||
quietFrontierMountainPlan.ambienceVolume <= 0.105,
|
||||
`${quietFrontierMountainPlan?.battleId}: quiet frontier pairing must attenuate mountain fallback`
|
||||
);
|
||||
|
||||
const redCliffsFirePlan = resolveCampaignPresentationSoundscape({ battleId: battleIds[21], stage: 'battle' });
|
||||
const yilingFirePlan = resolveCampaignPresentationSoundscape({ battleId: battleIds[45], stage: 'battle' });
|
||||
const wuzhangSnowPlan = resolveCampaignPresentationSoundscape({ battleId: battleIds[65], stage: 'battle' });
|
||||
[redCliffsFirePlan, yilingFirePlan].forEach((plan) => {
|
||||
assert(
|
||||
plan?.ambienceKey === 'battle-fire' &&
|
||||
plan.ambienceVolume * ambienceTrackGainCompensation['battle-fire'] <= 0.095,
|
||||
`${plan?.battleId}: fire crackle effective volume must retain its peak ceiling`
|
||||
);
|
||||
});
|
||||
assert(
|
||||
wuzhangSnowPlan?.ambienceKey === 'mountain-wind-ambience' &&
|
||||
wuzhangSnowPlan.ambienceVolume * ambienceTrackGainCompensation['mountain-wind-ambience'] <= 0.08,
|
||||
`${wuzhangSnowPlan?.battleId}: snow-wind effective volume must retain its gust ceiling`
|
||||
);
|
||||
|
||||
const preservedStoryPlan = resolveCampaignPresentationSoundscape({
|
||||
battleId: battleIds[0],
|
||||
stage: 'story',
|
||||
@@ -274,9 +320,12 @@ try {
|
||||
'specific-profile-then-arc-fallback',
|
||||
'battle ambience behavior'
|
||||
);
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackScale, 0.58, 'battle ambience fallback scale');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackMinimum, 0.05, 'battle ambience fallback minimum');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackMaximum, 0.065, 'battle ambience fallback maximum');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackScale, 1, 'battle ambience fallback scale');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackMinimum, 0.08, 'battle ambience fallback minimum');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceFallbackMaximum, 0.2, 'battle ambience fallback maximum');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceTargetRelativeLoudnessLu, -16, 'battle ambience target offset');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceRelativeLoudnessMinimumLu, -18, 'battle ambience lower bound');
|
||||
assertEqual(campaignPresentationTransitionPolicy.battleAmbienceRelativeLoudnessMaximumLu, -14, 'battle ambience upper bound');
|
||||
assert(Object.isFrozen(campaignPresentationTransitionPolicy), 'transition policy must be frozen');
|
||||
|
||||
const soundDirectorSource = readFileSync('src/game/audio/SoundDirector.ts', 'utf8');
|
||||
@@ -334,7 +383,7 @@ try {
|
||||
|
||||
console.log(
|
||||
`Verified ${arcEntries.length} campaign presentation arcs across ${battleIds.length} battles, ` +
|
||||
`${battleMusicKeys.size} battle music groups, ${battleAmbienceFallbackCount} quiet ambience fallbacks, ` +
|
||||
`${battleMusicKeys.size} battle music groups, ${battleAmbienceFallbackCount} loudness-calibrated ambience fallbacks, ` +
|
||||
'all state policies, palettes, motifs, and crossfade constraints.'
|
||||
);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user