From 7dae835ac566cde57cb6adb1a889c93faa92b0fe Mon Sep 17 00:00:00 2001 From: LucaP Date: Wed, 2 Sep 2026 18:44:24 +0300 Subject: [PATCH] fix: rebalance procedural audio mix --- src/audio/synth-engine.ts | 12 ++++++------ tests/unit/audio-lifecycle.test.ts | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/audio/synth-engine.ts b/src/audio/synth-engine.ts index 5ecec9b..261ae6b 100644 --- a/src/audio/synth-engine.ts +++ b/src/audio/synth-engine.ts @@ -54,7 +54,7 @@ export function createSynthEngine(createContext: AudioContextFactory): AudioGrap musicFilter.frequency.setValueAtTime(900, context.currentTime); musicFilter.Q.setValueAtTime(0.72, context.currentTime); const musicGain = context.createGain(); - musicGain.gain.setValueAtTime(0.38, context.currentTime); + musicGain.gain.setValueAtTime(0.78, context.currentTime); musicFilter.connect(musicGain); musicGain.connect(dynamics); @@ -64,7 +64,7 @@ export function createSynthEngine(createContext: AudioContextFactory): AudioGrap engineFilter.Q.setValueAtTime(1.25, context.currentTime); const engineGain = context.createGain(); - engineGain.gain.setValueAtTime(0.24, context.currentTime); + engineGain.gain.setValueAtTime(0.09, context.currentTime); engineFilter.connect(engineGain); engineGain.connect(dynamics); @@ -76,7 +76,7 @@ export function createSynthEngine(createContext: AudioContextFactory): AudioGrap roadFilter.frequency.setValueAtTime(410, context.currentTime); roadFilter.Q.setValueAtTime(0.55, context.currentTime); const roadGain = context.createGain(); - roadGain.gain.setValueAtTime(0.045, context.currentTime); + roadGain.gain.setValueAtTime(0.018, context.currentTime); roadFilter.connect(roadGain); roadGain.connect(dynamics); @@ -90,7 +90,7 @@ export function createSynthEngine(createContext: AudioContextFactory): AudioGrap ignition.frequency.setValueAtTime(68, context.currentTime); const ignitionGain = context.createGain(); ignitionGain.gain.setValueAtTime(0.0001, context.currentTime); - ignitionGain.gain.exponentialRampToValueAtTime(0.07, context.currentTime + 0.12); + ignitionGain.gain.exponentialRampToValueAtTime(0.025, context.currentTime + 0.12); ignitionGain.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 1.15); ignition.connect(ignitionGain); ignitionGain.connect(engineFilter); @@ -154,8 +154,8 @@ export function createSynthEngine(createContext: AudioContextFactory): AudioGrap engineFilter.frequency.setTargetAtTime(260 + next * 670, time, 0.38); roadFilter.frequency.setTargetAtTime(410 + next * 520, time, 0.42); musicFilter.frequency.setTargetAtTime(900 + next * 2_400, time, 0.42); - engineGain.gain.setTargetAtTime(0.24 + next * 0.12, time, 0.4); - roadGain.gain.setTargetAtTime(0.045 + next * 0.06, time, 0.45); + engineGain.gain.setTargetAtTime(0.09 + next * 0.04, time, 0.4); + roadGain.gain.setTargetAtTime(0.018 + next * 0.02, time, 0.45); music.setIntensity(next, time); }, onContextStateChange(listener) { diff --git a/tests/unit/audio-lifecycle.test.ts b/tests/unit/audio-lifecycle.test.ts index df10089..ef5b4a7 100644 --- a/tests/unit/audio-lifecycle.test.ts +++ b/tests/unit/audio-lifecycle.test.ts @@ -212,6 +212,29 @@ describe('audio controller lifecycle', () => { }); describe('procedural audio graph', () => { + it('keeps the soundtrack clearly ahead of the ambient drive effects across intensity changes', async () => { + vi.useFakeTimers(); + const context = new FakeAudioContext(); + + try { + const graph = createSynthEngine(() => context as unknown as AudioContext); + const [, musicGain, engineGain, , , roadGain, ignitionGain] = context.gains; + + expect(musicGain?.gain.value).toBe(0.78); + expect(engineGain?.gain.value).toBe(0.09); + expect(roadGain?.gain.value).toBe(0.018); + expect(ignitionGain?.gain.scheduledValues).toEqual([0.0001, 0.025, 0.0001]); + + graph.setIntensity(1); + expect(engineGain?.gain.targetValues).toContain(0.13); + expect(roadGain?.gain.targetValues).toContain(0.038); + + await graph.close(); + } finally { + vi.useRealTimers(); + } + }); + it('routes independent music, engine, and road buses through compression before the master output', async () => { vi.useFakeTimers(); const context = new FakeAudioContext();