# 4. Music Mood Mixer Pitfalls Part of [[Music Mood Mixer]]. Previous: [[3. Snapshot Blends Stem Remixing and Scheduling]]. > [!note] Verification status > SetFloat-vs-snapshots behaviour is from the 6000.5 `AudioMixer.SetFloat` reference ("Once you call this function, mixer snapshots will no longer control the exposed parameter"). PlayScheduled-in-the-past behaviour and the 100-200 ms prep recommendation are from the 6000.5 `AudioSource.PlayScheduled` page. Pause behaviour draws on `AudioListener.pause`, `AudioSource.ignoreListenerPause` and `AudioMixerUpdateMode` as already cited in [[2. Audio Mixer Snapshots and Exposed Parameters]]. **No new code; nothing compiled.** ## Snapshots and `SetFloat` still do not mix This is the same trap as Audio 1, and it will silently ruin a mood mixer. If you expose `TensionVol` and write `mixer.SetFloat("TensionVol", x)` every frame from combat intensity, `TransitionTo("Combat")` will no longer move that fader. Either: - Let snapshots (or `TransitionToSnapshots` weights) own stem levels, or - Call `ClearFloat` before returning ownership to snapshots. Player-facing `MusicVol` is the parameter that *should* be owned by `SetFloat`. Keep it on the parent group. ## Pops come from stopping audio, not from fading it Typical pop sources: - Assigning `audioSource.clip` while the source is playing. - Calling `Stop()` on a bed to "save a voice," then `Play()` a beat later. The waveform jumps and the downbeat is gone. - Scheduling with `PlayScheduled(AudioSettings.dspTime)` *right now*. The docs say a time in the past (or "now") starts as soon as possible and does not reconstruct missed audio. Give the system ~100-200 ms. - Hard-cutting a compressed clip at a non-zero crossing. `SetScheduledEndTime` plus a short overlapping tail is the documented mitigation; a snapshot fade on top hides what remains. If you only need a simple delay and not a stitch, `PlayDelayed` is fine. It is not a substitute for `PlayScheduled` when two clips must meet. ## Flicker is a design bug, not an audio bug If the mix chatters between Tension and Combat, do not shorten snapshot fades to hide it. Lengthen `exitHoldSeconds` on Combat, or debounce `SetCombat` at the publisher (for example only report combat while any enemy's state machine is actually in `Attack`, see [[Enemy AI State Machine]]). Hysteresis belongs in the director so every publisher does not invent its own timer. The health band (enter 30%, exit 45%) exists for the same reason. A 1 HP potion should not restore the entire explore mix. ## `time` vs `timeSamples` `AudioSource.time` is seconds; `timeSamples` is PCM samples and is the more precise cursor if you are going to seek (the 6000.5 reference says to use it when you want more precise timing than `time` allows). For adaptive *score* you rarely seek a looping bed; you fade it. Seeking shows up more in [[In-Game Radio Stations]], where returning to a station mid-song is the feature. ## Pause and `timeScale` `Time.timeScale = 0` does not stop audio. Decide explicitly: - Freeze the score with `AudioListener.pause = true`, and set `ignoreListenerPause = true` on UI / pause-menu sources; or - Keep the score running and transition to a `Paused` snapshot, with `mixer.updateMode = AudioMixerUpdateMode.UnscaledTime` so the fade itself still happens. The director in Part 3 uses `Time.unscaledDeltaTime` for hold timers so a paused game does not "owe" two seconds of combat hold when you unpause. If you would rather have hold timers freeze with gameplay, switch those to `Time.deltaTime`. ## Voice and CPU cost of "all stems always on" Three looping stereo beds plus percussion are four real voices before any SFX. That is cheap on desktop and worth watching on Quest; see [[4. Interactable Audio Pitfalls and Quest]] (start thinking about a global voice cap) and the Quest-specific spatial notes in [[Spatial Audio and Reverb Zones]]. Mitigations that do *not* pop: - Author the silent stems as mono. - Use a tighter DSP buffer only if you have measured a reason to (Quest latency vs CPU is a tradeoff; Meta's own XR Audio setup page recommends "Best latency" when you are using their spatializer - that is about input-to-output latency, not about running more music voices). - Do not Play/Stop stems to save voices on every mood change. ## Weighted blends fight discrete `TransitionTo` If `Update` calls `TransitionToSnapshots` every frame for the health blend, a simultaneous `combat.TransitionTo(0.6f)` will keep getting overwritten. The Part 3 director avoids this by *not* calling the discrete combat snapshot every frame - it only `TransitionTo`s on a state change, then lets `BlendLowHealthIfNeeded` take over while you remain in that state. If you add more continuous axes (wanted level 0..5, indoor/outdoor), put them all into one `TransitionToSnapshots` call with matching weights rather than stacking competing transitions. ## Do not couple the director to one health script A `GetComponent<PlayerHealth>()` inside `MusicMoodDirector` means the class project that uses [[Stat-Driven RPG Systems]] and the one that uses a 3-hit Pong life counter cannot share the director. `PlayerMusicSignals` exists so either publisher can talk to the same observer. ## Victory is easy to leave "stuck" If you fire `RequestVictory()` and never clear it, you will never leave the Victory snapshot. The director clears the flag when the sting's `clip.length` elapses. If you play victory as a looping section by mistake, you will sit on that snapshot forever - so Victory's `sectionClip` should be a one-shot sting routed to `Music/Stingers`, not a looping bed. ## Diegetic vs non-diegetic The score you built here is non-diegetic: the player character does not hear a hidden orchestra. A car radio is diegetic and should not use these stems. When both can play, duck or mute `Music/Bed` (snapshot `RadioOn`) rather than pausing `AudioListener`. That hand-off is covered in [[In-Game Radio Stations]]. ## Related follow-ons - [[In-Game Radio Stations]] - playlists, DJ chatter, simulated continuity - [[Spatial Audio and Reverb Zones]] - 3D settings, reverb zones, Meta XR Audio on Quest 2 - [[FMOD vs Built-in Mixer and Procedural Synth]] - when snapshot-and-stem mixing is no longer enough, and a procedural synth for when you want to generate tones rather than play clips