sceNgs2ParseWaveformFile read everything from the offset to the end of
the file into a zero-filled buffer and parsed that, although parsing
uses only the RIFF chunk headers and the fmt, fact and smpl payloads.
A waveform at an offset in a sound bank cost a read of the rest of the
bank on each call.
ReadChunks now takes the bytes through an accessor. Waveform data passes
its buffer; a waveform file seeks to and reads the headers and those
payloads alone, with the same checks against the length from the offset
to the end of the file. The format dispatch both use moves to
ParseWaveform.
ngs2_parse adds a bank of two waveforms in one file, the second with a
chunk after its samples, and parses each at its offset.
PPSA21402 (Balatro) parses its five 33 MB music tracks at start: one
call took 8.3 to 26.7 ms and allocated 33 MB, and now takes 0.01 to
0.04 ms with the same result.
On Linux ngs2_atrac9 aborted without any output once TestParseFile was part of
its main(). The exception that TestCorruptSuperframeAtPageEnd throws in the
Ngs2 module and catches in main() has to resume through a cleanup landing pad
inside main(). That resume goes through the unwinder statically linked into the
test executable, which then fails with _URC_FATAL_PHASE2_ERROR and aborts
silently. Whether main() gets such a pad depends on what the compiler inlines
into it, so adding any function with non-trivial cleanups to that main() is
enough to trigger it.
Move the PCM and file parse tests into a new ngs2_parse executable and restore
Ngs2Atrac9.cpp to its upstream content, so the test that catches exceptions is
unchanged. The new executable has no catch and never relies on that path.