| 26 | } |
| 27 | |
| 28 | WaveOAL::WaveOAL(SoundSystemOAL* sys, RString name, bool is3D) : IWave(name), _sys(sys), _is3D(is3D), _createdAs3D(is3D) |
| 29 | { |
| 30 | // Match DX8 WaveBuffers8::Reset() — initialize _volumeAdjust from current mixer state |
| 31 | _volumeAdjust = _sys->_volumeAdjustEffect; |
| 32 | |
| 33 | // Phase A measurement: file-open + decoder-init cost (the |
| 34 | // `SoundLoadFile` → `ov_open_callbacks` path for OGG; the |
| 35 | // equivalent header parse for WAV/WSS). Split out from the |
| 36 | // bigger `WaveOAL::Load` decode so we can see open vs full-decode |
| 37 | // separately. Threshold filters voice-line noise. |
| 38 | const auto _perfOpenStart = ::Poseidon::Dev::Perf::Now(); |
| 39 | |
| 40 | const char* nameStr = static_cast<const char*>(name); |
| 41 | if (!nameStr || !nameStr[0]) |
| 42 | { |
| 43 | // Empty sound name — a config slot with no sound assigned (common for |
| 44 | // some weapons/vehicles). Nothing to load; not an error. Logging it trips |
| 45 | // --strict during mass combat where many such slots are touched. |
| 46 | _loadError = true; |
| 47 | return; |
| 48 | } |
| 49 | _stream = SoundLoadFile(nameStr); |
| 50 | if (!_stream) |
| 51 | { |
| 52 | _loadError = true; |
| 53 | LOG_ERROR(Audio, "Load failed: '{}' (file not found or unsupported format)", nameStr); |
| 54 | return; |
| 55 | } |
| 56 | LoadHeader(); |
| 57 | |
| 58 | // Phase 3g: route OGG sources through the chunked streaming |
| 59 | // path. Case-insensitive .ogg suffix is the cheap test that |
| 60 | // catches every music + voice OGG asset in the demo and the |
| 61 | // full game. WSS / WAV stay on the Phase 3c/3d full-decode |
| 62 | // path because they're small and decode fast — streaming |
| 63 | // would add a frame of playback latency without a perceptual |
| 64 | // win. |
| 65 | const char* n = static_cast<const char*>(name); |
| 66 | if (const size_t nlen = n ? std::strlen(n) : 0; nlen >= 4) |
| 67 | { |
| 68 | const char* ext = n + nlen - 4; |
| 69 | if ((ext[0] == '.' || ext[0] == 0) && |
| 70 | (ext[1] == 'o' || ext[1] == 'O') && |
| 71 | (ext[2] == 'g' || ext[2] == 'G') && |
| 72 | (ext[3] == 'g' || ext[3] == 'G')) |
| 73 | { |
| 74 | _isStreamed = true; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | _sys->RegisterWave(this); |
| 79 | |
| 80 | const double _perfOpenMs = ::Poseidon::Dev::Perf::ElapsedMs(_perfOpenStart); |
| 81 | if (_perfOpenMs >= 1.0) |
| 82 | { |
| 83 | LOG_DEBUG(Audio, "PERF: WaveOAL::Open {} took {:.2f}ms", static_cast<const char*>(name), _perfOpenMs); |
| 84 | } |
| 85 | ::Poseidon::Dev::Perf::EmitTraceEventAsset(Poseidon::Foundation::LogCategory::Audio, "WaveOAL::Open", _perfOpenStart, |
nothing calls this directly
no test coverage detected