CNA-BUG-147: SoundBank::PlayCue destroys a fire-and-forget cue that is still playing five minutes after it started

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

SweepFireAndForget, run by every AudioEngine::Update and every PlayCue, removes still-playing or paused fire-and-forget cues older than kFireAndForgetSafetyNet (5 minutes), which stops long or looping cues such as music started with PlayCue.

Identifier
CNA-BUG-147
Category
Bug
Subsystem
Audio & media
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Medium (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
SoundBank::PlayCue(const std::string&) and PlayCue(name, listener, emitter)

Expected behaviour

In XNA, a cue started with SoundBank.PlayCue plays until it ends or its category is stopped; there is no age limit, and looping music or ambience is commonly started this way.

Actual behaviour at TARGET

AudioEngine::Update in AudioEngine.cpp sweeps every registered bank, and SoundBank::PlayCueInternal in SoundBank.cpp calls SweepFireAndForget first. The sweep keeps a playing or paused cue only while now - faf.created < kFireAndForgetSafetyNet (5 minutes); older entries are erased, destroying the Cue and its instances. Any AudioEngine::Update (which XNA games call every frame) or PlayCue more than five minutes after a looping cue started therefore cuts that cue off. The comment calls the constant a safety net against unbounded growth that “never affects ordinary playback”; the test comment explains that a looping cue never reports itself finished (plan_audio.md Fáze 7 D6).

Source locations

Evidence

Checked by reading at 009d40f5; not executed.

Focused reproduction

// Illustrative; not compiled or run.
soundBank.PlayCue("MusicLoop");     // a looping cue
// ... more than five minutes later, the next per-frame call:
audioEngine.Update();                // the sweep destroys MusicLoop

Current tests

SoundBankTests.cpp keeps long-playing and paused cues across sweeps and pins the cut itself: FireAndForgetCueIsForceSweptPastSafetyNetEvenIfStillPlaying backdates a playing cue by ten minutes and expects it swept. A fix must change that test.

Regression test

A test with an injectable clock (or a shortened safety net) asserting a looping fire-and-forget cue survives later PlayCue calls; bound growth by sweeping stopped cues only, or by a count limit that does not stop audible cues.

Blast radius

Games that start music or ambience with PlayCue and keep playing cues from the same bank; the long cue stops abruptly after five minutes.

Workaround

Start long or looping cues with GetCue + Play and keep the Cue.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

User guide
Audio: XACT
Known issues
Bug index