From bc4333e313a3d26546fe8b719d3bce511ff2ea90 Mon Sep 17 00:00:00 2001 From: Axcxiii Date: Thu, 29 Oct 2026 23:39:49 -0500 Subject: [PATCH] ngs2: size 16-bit PCM blocks in Ngs2CalcWaveformBlock (The Binding of Isaac: Repentance) (#1968) Ngs2CalcWaveformBlock returned NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT with a zeroed block for 16-bit PCM (0x12). The Binding of Isaac: Repentance (PPSA03311) ignores the error and queues the zeroed blocks, which the sampler skips, so the game had no audio at all. PCM frames have a fixed size, so the block now starts at sample_pos frames and spans num_samples frames. Fixes #667 Co-authored-by: gl-ungus Co-authored-by: Claude Opus 5.5 --- src/libs/ngs2.cpp | 5 +++++ tests/Ngs2SamplerTests.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/libs/ngs2.cpp b/src/libs/ngs2.cpp index efa26fe1e..b7b783daf 100644 --- a/src/libs/ngs2.cpp +++ b/src/libs/ngs2.cpp @@ -2210,6 +2210,11 @@ int KYTY_SYSV_ABI Ngs2CalcWaveformBlock(const Ngs2WaveformFormat* format, uint32 : ((skip + num_samples + frame_samples - 1) / frame_samples) * codec.superframeSize; block->num_skip_samples = num_samples == 0 ? 0 : static_cast(skip); + } else if (format->waveform_type == 0x12) { + // 16-bit PCM has fixed-size frames, so the block starts exactly at the sample. + const uint64_t frame_size = uint64_t(format->num_channels) * sizeof(int16_t); + block->data_offset = uint64_t(sample_pos) * frame_size; + block->data_size = uint64_t(num_samples) * frame_size; } else { return NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT; } diff --git a/tests/Ngs2SamplerTests.cpp b/tests/Ngs2SamplerTests.cpp index 8c86034f2..a62a0c8d5 100644 --- a/tests/Ngs2SamplerTests.cpp +++ b/tests/Ngs2SamplerTests.cpp @@ -651,6 +651,11 @@ void TestWaveformBlockGeometry() { Check(Ngs2CalcWaveformBlock(&format, 0, 0, &block) == OK && block.data_size == 0 && block.num_samples == 0, "empty ATRAC9 block acquired encoded data"); + const Ngs2WaveformFormat pcm {0x12, 2, 48000}; + Check(Ngs2CalcWaveformBlock(&pcm, 4096, 4096, &block) == OK && + block.data_offset == 16384 && block.data_size == 16384 && + block.num_skip_samples == 0 && block.num_samples == 4096, + "PCM block calculation omitted the sample frames"); Fixture f(24000); const int16_t silence = 0; f.Queue(&silence, 0, 0, UINT32_MAX);