CNA-BUG-222: Audio comments describe behaviour the code does not have: SoundEffect::Play's instance limit, FireAndForgetPanState freeing, the is3D_ latch and SoundEffectReader's WAV route

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.

SoundEffect.hpp promises that Play returns false at an instance limit CNA does not implement, and three internal comments in the audio and content modules contradict the code next to them.

Identifier
CNA-BUG-222
Category
Bug
Subsystem
Documentation & release tooling
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (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
SoundEffect::Play() and SoundEffect::Play(float, float, float) documentation; maintainer comments in SoundEffect.cpp, SoundEffectInstance.hpp and SoundEffectContentTypeReader.hpp

Expected behaviour

Comments and Doxygen describe what the code does. For SoundEffect::Play the XNA meaning of a false return is specific: XNA 4.0's SoundEffect.Play(float, float, float) returns false when it catches InstancePlayLimitException (decompiled reference, Microsoft.Xna.Framework.Audio/SoundEffect.cs).

Actual behaviour at TARGET

  1. SoundEffect.hpp documents both Play overloads as returning false “if the instance limit was reached”. SoundEffect::Play(float, float, float) in SoundEffect.cpp checks no limit and CNA has none: it returns false for a disposed effect, a missing native audio handle, a track that cannot be created, bound or started, and always in a build without SOUND_ENABLED.
  2. In SoundEffect.cpp the comment above FireAndForgetPanState says it is “freed in OnFireAndForgetStopped”, and the comment at SetMixerTrackStoppedCallback says the stopped callback frees it. OnFireAndForgetStopped only pushes it onto g_pendingPanStateCleanup; the next Play or process exit frees it. The deferral is deliberate (an AddressSanitizer heap-use-after-free, P11-PAN-002), so the stale comment invites reintroducing the bug.
  3. The is3D_ member comment in SoundEffectInstance.hpp says setPanProperty() keeps updating Pan_ but stops writing the track, and that the flag is “never reset back to false once set”. setPanProperty in SoundEffectInstance.cpp clears is3D_ before the first Play and throws InvalidOperationException for a 3D instance after it (CABI-25).
  4. SoundEffectContentTypeReader.hpp says 8-bit PCM, float and ADPCM are wrapped in a synthetic WAV and decoded through SoundEffect::FromStream. SoundEffectReader::Read in SoundEffectContentTypeReader.cpp converts every format with ConvertXnbSoundToImportedSound and ProcessImportedSoundEffect and constructs through the raw 16-bit PCM buffer constructor.

Source locations

Evidence

Checked by reading at 009d40f5; nothing executed. The XNA meaning of the return value was read from the decompiled XNA 4.0 SoundEffect. The behaviours the comments misdescribe are pinned elsewhere: SoundEffectInstanceTest.SetPanBeforePlaybackTakesTheInstanceOutOf3D (whose own comment records that it replaces the older latch-for-life reading). The fire-and-forget pan path is exercised by SoundEffectTest.PlayWithHardPanDoesNotCrash, which does not observe when the pan state is freed.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

Comments are not tested. The code paths are covered by SoundEffectTests.cpp and SoundEffectInstanceTests.cpp (SDL3 audio only).

Regression test

No behavioural test applies: correct the four comments, and document the false-return cases SoundEffect::Play really has (or implement an instance limit and keep the XNA wording).

Blast radius

Readers of the public SoundEffect header, who may code against a limit that never triggers, and maintainers of the fire-and-forget, 3D-pan and XNB sound paths.

Workaround

No workaround is known.

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

Known issues
Bug index