#include "AudioLoader.h" #include "utils/binarytools/BinaryReader.h" #include "assets/ast_audio.h" #include "BitConverter.h" #include "port/Engine.h" #include #include #include namespace fs = std::filesystem; Ship::BinaryReader Audio_MakeReader(const char* resource, u32 offset = 0){ auto data = (char*)ResourceGetDataByName(resource); auto size = ResourceGetSizeByName(resource); Ship::BinaryReader reader(data, size); reader.SetEndianness(Ship::Endianness::Big); reader.Seek(offset, Ship::SeekOffsetType::Start); return reader; } char* Audio_LoadBlob(const char* resource, u32 offset){ auto data = (char*)ResourceGetDataByName(resource); return data + offset; } EnvelopePoint* Audio_LoadEnvelope(uint32_t addr) { auto reader = Audio_MakeReader(gAudioBank, addr); std::vector temp; while(true) { int16_t delay = BSWAP16(reader.ReadInt16()); int16_t arg = BSWAP16(reader.ReadInt16()); temp.push_back({delay, arg}); if (1 <= (-delay) % (1 << 16) && (-delay) % (1 << 16) <= 3){ break; } } EnvelopePoint* envelopes = memallocn(EnvelopePoint, temp.size()); memcpy(envelopes, temp.data(), sizeof(EnvelopePoint) * temp.size()); return envelopes; } extern "C" SoundFont* Audio_LoadFont(AudioTableEntry entry) { auto reader = Audio_MakeReader(gAudioBank, entry.romAddr); SoundFont* font = memalloc(SoundFont); font->numInstruments = (entry.shortData2 >> 8) & 0xFFu; font->numDrums = entry.shortData2 & 0xFFu; font->sampleBankId1 = (entry.shortData1 >> 8) & 0xFFu; font->sampleBankId2 = entry.shortData1 & 0xFFu; font->instruments = memallocn(Instrument*, font->numInstruments); font->drums = memallocn(Drum*, font->numDrums); uint32_t drumBaseAddr = entry.romAddr + reader.ReadUInt32(); uint32_t instBaseAddr = 4; if(font->drums != nullptr && drumBaseAddr != 0){ reader.Seek(drumBaseAddr, Ship::SeekOffsetType::Start); for(size_t i = 0; i < font->numDrums; i++){ font->drums[i] = Audio_LoadDrum(entry.romAddr + reader.ReadUInt32(), entry.romAddr, font->sampleBankId1); } } if(font->instruments != nullptr){ reader.Seek(instBaseAddr, Ship::SeekOffsetType::Start); for(size_t i = 1; i < font->numInstruments; i++){ font->instruments[i] = Audio_LoadInstrument(reader.ReadUInt32(), font->sampleBankId1); } } gSampleFontLoadStatus[font->sampleBankId1] = 2; return font; } extern "C" AdpcmLoop* Audio_LoadLoop(uint32_t addr) { auto reader = Audio_MakeReader(gAudioBank, addr); AdpcmLoop* loop = memalloc(AdpcmLoop); loop->start = reader.ReadInt32(); loop->end = reader.ReadUInt32(); loop->count = reader.ReadUInt32(); if(loop->count != 0){ for(size_t i = 0; i < 16; i++){ loop->predictorState[i] = reader.ReadInt16(); } } return loop; } extern "C" AdpcmBook* Audio_LoadBook(uint32_t addr) { auto reader = Audio_MakeReader(gAudioBank, addr); AdpcmBook* book = memalloc(AdpcmBook); book->order = reader.ReadInt32(); book->numPredictors = reader.ReadInt32(); size_t length = 8 * book->order * book->numPredictors; book->book = memallocn(int16_t, length); if(length > 0x40){ return nullptr; } for(size_t i = 0; i < length; i++){ book->book[i] = reader.ReadInt16(); } return book; } Sample* Audio_LoadSample(uint32_t sampleAddr, uint32_t baseAddr = 0, uint32_t sampleBankID = 0) { auto reader = Audio_MakeReader(gAudioBank, sampleAddr); Sample* sample = memalloc(Sample); sample->size = reader.ReadUInt32(); uint32_t addr = reader.ReadUInt32(); sample->loop = Audio_LoadLoop(baseAddr + reader.ReadUInt32()); sample->book = Audio_LoadBook(baseAddr + reader.ReadUInt32()); sample->isRelocated = 1; sample->sampleAddr = (uint8_t*) Audio_LoadBlob(gAudioTable, gSampleBankTable->entries[sampleBankID].romAddr + addr); std::filesystem::path path{ "dumps/" + std::to_string(sampleAddr) + ".raw" }; std::ofstream ofs(path); ofs.write(reinterpret_cast(sample->sampleAddr), sample->size); ofs.close(); gUsedSamples[gNumUsedSamples++] = sample; return sample; } TunedSample Audio_LoadTunedSample(uint32_t addr, uint32_t baseAddr = 0, uint32_t sampleBankID = 0) { auto reader = Audio_MakeReader(gAudioBank, addr); auto sampleAddr = reader.ReadUInt32(); auto tuning = reader.ReadFloat(); if(sampleAddr == 0){ assert(tuning == 0.0f); return { nullptr, 0.0f }; } return { .sample = Audio_LoadSample(baseAddr + sampleAddr, baseAddr, sampleBankID), .tuning = tuning }; } extern "C" Instrument* Audio_LoadInstrument(uint32_t addr, uint32_t sampleBankID) { if (addr == 0) { return nullptr; } auto reader = Audio_MakeReader(gAudioBank, addr); Instrument* instrument = memalloc(Instrument); instrument->isRelocated = reader.ReadUByte(); instrument->normalRangeLo = reader.ReadUByte(); instrument->normalRangeHi = reader.ReadUByte(); instrument->adsrDecayIndex = reader.ReadUByte(); instrument->envelope = Audio_LoadEnvelope(reader.ReadUInt32()); instrument->lowPitchTunedSample = Audio_LoadTunedSample(addr + 8, 0, sampleBankID); instrument->normalPitchTunedSample = Audio_LoadTunedSample(addr + 16, 0, sampleBankID); instrument->highPitchTunedSample = Audio_LoadTunedSample(addr + 24, 0, sampleBankID); instrument->isRelocated = 1; return instrument; } extern "C" Drum* Audio_LoadDrum(uint32_t addr, uint32_t baseAddr, uint32_t sampleBankID) { if(baseAddr != 0 && addr >= baseAddr){ return nullptr; } auto reader = Audio_MakeReader(gAudioBank, addr); Drum* drum = memalloc(Drum); drum->adsrDecayIndex = reader.ReadInt8(); drum->pan = reader.ReadInt8(); drum->isRelocated = reader.ReadUByte(); reader.ReadUByte(); drum->isRelocated = 1; drum->tunedSample = Audio_LoadTunedSample(addr + 4, baseAddr, sampleBankID); reader.Seek(0x8, Ship::SeekOffsetType::Current); drum->envelope = Audio_LoadEnvelope(reader.ReadUInt32()); return drum; }