#include "Ngs2Test.hpp" #include "prx/libc/include/General.hpp" #include #include #include #include #include static void Put16(std::vector& out, std::uint32_t value) { out.push_back(static_cast(value)); out.push_back(static_cast(value >> 8)); } static void Put32(std::vector& out, std::uint32_t value) { Put16(out, value & 0xffff); Put16(out, value >> 16); } static void PutTag(std::vector& out, const char* tag) { out.insert(out.end(), tag, tag + 4); } static std::vector PcmFile(std::uint32_t channels, std::uint32_t sampleRate, std::uint32_t bits, std::uint32_t frames) { const std::uint32_t frameBytes = channels * bits / 8; std::vector file; PutTag(file, "RIFF"); Put32(file, 36 + frames * frameBytes); PutTag(file, "WAVE"); PutTag(file, "fmt "); Put32(file, 16); Put16(file, 1); Put16(file, channels); Put32(file, sampleRate); Put32(file, sampleRate * frameBytes); Put16(file, frameBytes); Put16(file, bits); PutTag(file, "data"); Put32(file, frames * frameBytes); file.resize(file.size() + frames * frameBytes, 0x11); return file; } static void TestParsePcm() { const auto file = PcmFile(2, 44100, 16, 100); Ngs2WaveformInfo info{}; Require(sceNgs2ParseWaveformData(file.data(), file.size(), &info) == SCE_NGS2_OK); Require(info.format.waveform_type == SCE_NGS2_WAVEFORM_TYPE_PCM_I16L && info.format.num_channels == 2 && info.format.sample_rate == 44100); Require(info.data_offset == 44 && info.data_size == 400 && info.num_samples == 100); Require(info.num_blocks == 1 && info.block[0].data_offset == 44 && info.block[0].data_size == 400 && info.block[0].num_samples == 100); auto truncated = file; truncated.resize(44 + 202); Require(sceNgs2ParseWaveformData(truncated.data(), truncated.size(), &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA); auto partialFrame = PcmFile(2, 44100, 16, 100); partialFrame.resize(44 + 402, 0x11); const std::uint32_t partialSize = 402; std::memcpy(partialFrame.data() + 40, &partialSize, sizeof(partialSize)); Require(sceNgs2ParseWaveformData(partialFrame.data(), partialFrame.size(), &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA); const auto eightBit = PcmFile(1, 44100, 8, 10); Require(sceNgs2ParseWaveformData(eightBit.data(), eightBit.size(), &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_FORMAT); const auto noChannels = PcmFile(0, 44100, 16, 10); Require(sceNgs2ParseWaveformData(noChannels.data(), noChannels.size(), &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_FORMAT); } static void TestParseFile() { const auto wave = PcmFile(1, 22050, 16, 64); const char* const guestPath = "/aps5_ngs2_parse_file.wav"; const auto path = ResolvePath_nid_no_patch(guestPath); { std::ofstream out(path, std::ios::binary); const char pad[3]{}; out.write(pad, sizeof(pad)); out.write(reinterpret_cast(wave.data()), static_cast(wave.size())); } Ngs2WaveformInfo info{}; Require(sceNgs2ParseWaveformFile(guestPath, 3, nullptr) == SCE_NGS2_ERROR_INVALID_OUT_ADDRESS); Require(sceNgs2ParseWaveformFile(nullptr, 0, &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA); Require(sceNgs2ParseWaveformFile(guestPath, 3, &info) == SCE_NGS2_OK); Require(info.format.num_channels == 1 && info.format.sample_rate == 22050 && info.num_samples == 64); Require(info.data_offset == 3 + 44 && info.block[0].data_offset == 3 + 44 && info.data_size == 128); Require(sceNgs2ParseWaveformFile(guestPath, static_cast(wave.size()) + 4, &info) == SCE_NGS2_ERROR_INVALID_WAVEFORM_DATA); Require(sceNgs2ParseWaveformFile(guestPath, 0, &info) == SCE_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT); std::filesystem::remove(path); } static void TestParseFileBank() { const auto first = PcmFile(2, 48000, 16, 300); auto second = PcmFile(1, 32000, 16, 50); PutTag(second, "LIST"); Put32(second, 4); PutTag(second, "INFO"); const std::uint32_t riffSize = static_cast(second.size() - 8); std::memcpy(second.data() + 4, &riffSize, sizeof(riffSize)); const char* const guestPath = "/aps5_ngs2_parse_bank.bin"; const auto path = ResolvePath_nid_no_patch(guestPath); { std::ofstream out(path, std::ios::binary); out.write(reinterpret_cast(first.data()), static_cast(first.size())); out.write(reinterpret_cast(second.data()), static_cast(second.size())); } Ngs2WaveformInfo info{}; Require(sceNgs2ParseWaveformFile(guestPath, 0, &info) == SCE_NGS2_OK); Require(info.format.num_channels == 2 && info.format.sample_rate == 48000 && info.num_samples == 300); Require(info.data_offset == 44 && info.data_size == 1200 && info.block[0].data_offset == 44); const auto secondOffset = static_cast(first.size()); Require(sceNgs2ParseWaveformFile(guestPath, secondOffset, &info) == SCE_NGS2_OK); Require(info.format.num_channels == 1 && info.format.sample_rate == 32000 && info.num_samples == 50); Require(info.data_offset == secondOffset + 44 && info.data_size == 100 && info.block[0].data_offset == secondOffset + 44); std::filesystem::remove(path); } int main() { TestParsePcm(); TestParseFile(); TestParseFileBank(); return 0; }