diff --git a/OTRExporter/OTRExporter/AudioExporter.cpp b/OTRExporter/OTRExporter/AudioExporter.cpp index 7fb065831..f1a9bb2fd 100644 --- a/OTRExporter/OTRExporter/AudioExporter.cpp +++ b/OTRExporter/OTRExporter/AudioExporter.cpp @@ -6,7 +6,7 @@ #include #include "DisplayListExporter.h" -void OTRExporter_Audio::WriteSampleEntryReference(SampleEntry* entry, std::map samples, BinaryWriter* writer) +void OTRExporter_Audio::WriteSampleEntryReference(ZAudio* audio, SampleEntry* entry, std::map samples, BinaryWriter* writer) { writer->Write((uint8_t)(entry != nullptr ? 1 : 0)); @@ -21,7 +21,17 @@ void OTRExporter_Audio::WriteSampleEntryReference(SampleEntry* entry, std::mapWrite(addr); + if (entry != nullptr) + { + if (audio->sampleOffsets[entry->bankId].find(entry->sampleDataOffset) != audio->sampleOffsets[entry->bankId].end()) + { + writer->Write(StringHelper::Sprintf("audio/samples/%s", audio->sampleOffsets[entry->bankId][entry->sampleDataOffset].c_str())); + } + else + writer->Write(entry->fileName); + } + else + writer->Write(""); } void OTRExporter_Audio::WriteSampleEntry(SampleEntry* entry, BinaryWriter* writer) @@ -52,13 +62,13 @@ void OTRExporter_Audio::WriteSampleEntry(SampleEntry* entry, BinaryWriter* write writer->Write((entry->book.books[i])); } -void OTRExporter_Audio::WriteSoundFontEntry(SoundFontEntry* entry, std::map samples, BinaryWriter* writer) +void OTRExporter_Audio::WriteSoundFontEntry(ZAudio* audio, SoundFontEntry* entry, std::map samples, BinaryWriter* writer) { writer->Write((uint8_t)(entry != nullptr ? 1 : 0)); if (entry != nullptr) { - WriteSampleEntryReference(entry->sampleEntry, samples, writer); + WriteSampleEntryReference(audio, entry->sampleEntry, samples, writer); writer->Write(entry->tuning); } } @@ -86,21 +96,21 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit MemoryStream* sampleStream = new MemoryStream(); BinaryWriter sampleWriter = BinaryWriter(sampleStream); + writer->Write((uint32_t)pair.first); WriteSampleEntry(pair.second, &sampleWriter); - std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("samples/sample_%08X", pair.first)); + std::string basePath = ""; + + if (audio->sampleOffsets[pair.second->bankId].find(pair.second->sampleDataOffset) != audio->sampleOffsets[pair.second->bankId].end()) + basePath = StringHelper::Sprintf("samples/%s", audio->sampleOffsets[pair.second->bankId][pair.second->sampleDataOffset].c_str()); + else + basePath = StringHelper::Sprintf("samples/sample_%08X", pair.first); + + std::string fName = OTRExporter_DisplayList::GetPathToRes(res, basePath); AddFile(fName, sampleStream->ToVector()); } - // Write the samplebank table - //writer->Write((uint32_t)audio->sampleBankTable.size()); - //for (size_t i = 0; i < audio->sampleBankTable.size(); i++) - //{ - //} - // Write the soundfont table - //writer->Write((uint32_t)audio->soundFontTable.size()); - for (size_t i = 0; i < audio->soundFontTable.size(); i++) { MemoryStream* fntStream = new MemoryStream(); @@ -108,6 +118,7 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit WriteHeader(nullptr, "", &fntWriter, Ship::ResourceType::AudioSoundFont); + fntWriter.Write((uint32_t)i); fntWriter.Write(audio->soundFontTable[i].medium); fntWriter.Write(audio->soundFontTable[i].cachePolicy); fntWriter.Write(audio->soundFontTable[i].data1); @@ -126,7 +137,7 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit WriteEnvData(audio->soundFontTable[i].drums[k].env, &fntWriter); - WriteSampleEntryReference(audio->soundFontTable[i].drums[k].sample, audio->samples, &fntWriter); + WriteSampleEntryReference(audio, audio->soundFontTable[i].drums[k].sample, audio->samples, &fntWriter); fntWriter.Write(audio->soundFontTable[i].drums[k].tuning); } @@ -141,14 +152,14 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit WriteEnvData(audio->soundFontTable[i].instruments[k].env, &fntWriter); - WriteSoundFontEntry(audio->soundFontTable[i].instruments[k].lowNotesSound, audio->samples, &fntWriter); - WriteSoundFontEntry(audio->soundFontTable[i].instruments[k].normalNotesSound, audio->samples, &fntWriter); - WriteSoundFontEntry(audio->soundFontTable[i].instruments[k].highNotesSound, audio->samples, &fntWriter); + WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].lowNotesSound, audio->samples, &fntWriter); + WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].normalNotesSound, audio->samples, &fntWriter); + WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].highNotesSound, audio->samples, &fntWriter); } for (int k = 0; k < audio->soundFontTable[i].soundEffects.size(); k++) { - WriteSoundFontEntry(audio->soundFontTable[i].soundEffects[k], audio->samples, &fntWriter); + WriteSoundFontEntry(audio, audio->soundFontTable[i].soundEffects[k], audio->samples, &fntWriter); } std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("fonts/font_%02X", i)); @@ -163,12 +174,18 @@ void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWrit MemoryStream* seqStream = new MemoryStream(); BinaryWriter seqWriter = BinaryWriter(seqStream); + seqWriter.Write((uint8_t)0); // Version 0 of format... + seqWriter.Write((uint8_t)i); seqWriter.Write((uint8_t)audio->sequenceTable[i].medium); seqWriter.Write((uint8_t)audio->sequenceTable[i].cachePolicy); + seqWriter.Write((uint8_t)audio->fontIndices[i].size()); + + for (int k = 0; k < audio->fontIndices[i].size(); k++) + seqWriter.Write((uint8_t)audio->fontIndices[i][k]); seqWriter.Write(seq.data(), seq.size()); - std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("sequences/seq_%02X", i)); + std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("sequences/%s", audio->seqNames[i].c_str())); AddFile(fName, seqStream->ToVector()); } } diff --git a/OTRExporter/OTRExporter/AudioExporter.h b/OTRExporter/OTRExporter/AudioExporter.h index bd91da67f..13a8cc0a0 100644 --- a/OTRExporter/OTRExporter/AudioExporter.h +++ b/OTRExporter/OTRExporter/AudioExporter.h @@ -9,8 +9,8 @@ class OTRExporter_Audio : public OTRExporter { public: void WriteSampleEntry(SampleEntry* entry, BinaryWriter* writer); - void WriteSampleEntryReference(SampleEntry* entry, std::map samples, BinaryWriter* writer); - void WriteSoundFontEntry(SoundFontEntry* entry, std::map samples, BinaryWriter* writer); + void WriteSampleEntryReference(ZAudio* audio, SampleEntry* entry, std::map samples, BinaryWriter* writer); + void WriteSoundFontEntry(ZAudio* audio, SoundFontEntry* entry, std::map samples, BinaryWriter* writer); void WriteEnvData(std::vector envelopes, BinaryWriter* writer); virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override; }; \ No newline at end of file diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index 1c24c824a..63443de34 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -13,6 +13,54 @@ ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent) { //RegisterRequiredAttribute("CodeOffset"); //RegisterOptionalAttribute("LangOffset", "0"); + +} + +void ZAudio::ParseXML(tinyxml2::XMLElement* reader) +{ + ZResource::ParseXML(reader); + + auto t = reader->Name(); + + auto child = reader->FirstChildElement(); + + while (child != nullptr) + { + int bp = 0; + if (std::string(child->Value()) == "Sequences") + { + auto seqChild = child->FirstChildElement(); + + while (seqChild != nullptr) + { + if (std::string(seqChild->Value()) == "Sequence") + { + seqNames.push_back(seqChild->Attribute("Name")); + } + + seqChild = seqChild->NextSiblingElement(); + } + } + + if (std::string(child->Value()) == "Samples") + { + int bankId = child->IntAttribute("Bank", 0); + auto sampChild = child->FirstChildElement(); + + while (sampChild != nullptr) + { + if (std::string(sampChild->Value()) == "Sample") + { + auto atStr = sampChild->FirstChildElement()->Attribute("At"); + sampleOffsets[bankId][StringHelper::StrToL(atStr, 16)] = sampChild->Attribute("Name"); + } + + sampChild = sampChild->NextSiblingElement(); + } + } + + child = child->NextSiblingElement(); + } } void ZAudio::DecodeADPCMSample(SampleEntry* sample) @@ -26,9 +74,6 @@ std::vector ZAudio::ParseEnvelopeData(std::vector audioB { std::vector result; - //bool process = true; - - //for (int i = 0; i < 4; i++) while (true) { AdsrEnvelope* env = new AdsrEnvelope(); @@ -49,13 +94,13 @@ std::vector ZAudio::ParseEnvelopeData(std::vector audioB SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int soundFontOffset, int baseOffset) { SoundFontEntry* soundFont = new SoundFontEntry(); soundFont->sampleEntry = ParseSampleEntry( - audioBank, audioTable, audioSampleBankEntry, + audioBank, audioTable, audioSampleBankEntry, bankIndex, BitConverter::ToInt32BE(audioBank, soundFontOffset + 0) + baseOffset, baseOffset); soundFont->tuning = BitConverter::ToFloatBE(audioBank, soundFontOffset + 4); @@ -64,7 +109,7 @@ SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector audioBank, SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset) { @@ -74,6 +119,8 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, { SampleEntry* sample = new SampleEntry(); + sample->bankId = bankIndex; + int sampleSize = BitConverter::ToInt32BE(audioBank, sampleOffset + 0) & 0x00FFFFFF; int loopOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 8) + baseOffset; int bookOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 12) + baseOffset; @@ -111,6 +158,9 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, BitConverter::ToInt16BE(audioBank, bookOffset + 8 + (i * 2))); } + sample->sampleDataOffset = sampleDataOffset; + sample->fileName = StringHelper::Sprintf("audio/samples/sample_%08X", sampleOffset); + samples[sampleOffset] = sample; return sample; @@ -173,15 +223,13 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector { samplePtr += ptr; - drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, BitConverter::ToInt32BE(codeData, samplePtr + 4) + ptr, ptr); drum.releaseRate = codeData[samplePtr + 0]; drum.pan = codeData[samplePtr + 1]; drum.loaded = codeData[samplePtr + 2]; drum.tuning = BitConverter::ToFloatBE(codeData, samplePtr + 8); - - //int sampleDefOffset = BitConverter::ToInt32BE(codeData, samplePtr + 4); drum.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, samplePtr + 12) + ptr, ptr); } @@ -194,7 +242,7 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector for (int i = 0; i < numSfx; i++) { SoundFontEntry* sfx; - sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset, ptr); entry.soundEffects.push_back(sfx); @@ -221,16 +269,16 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector if (BitConverter::ToInt32BE(codeData, currentOffset + 8) != 0) instrument.lowNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 8, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 8, ptr); if (BitConverter::ToInt32BE(codeData, currentOffset + 16) != 0) instrument.normalNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 16, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 16, ptr); if (BitConverter::ToInt32BE(codeData, currentOffset + 24) != 0 && instrument.normalRangeHi != 0x7F) instrument.highNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 24, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 24, ptr); } entry.instruments.push_back(instrument); @@ -251,33 +299,69 @@ void ZAudio::ParseRawData() else codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code"); + codeData = File::ReadAllBytes("baserom/code_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioTableData = Globals::Instance->GetBaseromFile("Audiotable"); else audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable"); + audioTableData = File::ReadAllBytes("baserom/Audiotable_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioBankData = Globals::Instance->GetBaseromFile("Audiobank"); else audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank"); + audioBankData = File::ReadAllBytes("baserom/Audiobank_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioSeqData = Globals::Instance->GetBaseromFile("Audioseq"); else audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audioseq"); + audioSeqData = File::ReadAllBytes("baserom/Audioseq_ntsc"); + // TABLE PARSING + + // GC PAL //int gSoundFontTableOffset = 0x138270; // OTRTODO: Make this an XML Param //int gSequenceTableOffset = 0x1386A0; // OTRTODO: Make this an XML Param //int gSampleBankTableOffset = 0x138D90; // OTRTODO: Make this an XML Param - int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param - int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param - int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + // NMQ DBG ROM + //int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param + //int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param + //int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + //int gSequenceFontTableOffset = 0x138500; // OTRTODO: Make this an XML Param + + // NTSC 1.0 + int gSoundFontTableOffset = 0x1026A0; // OTRTODO: Make this an XML Param + int gSequenceTableOffset = 0x102AD0; // OTRTODO: Make this an XML Param + int gSampleBankTableOffset = 0x1031C0; // OTRTODO: Make this an XML Param + int gSequenceFontTableOffset = 0x102910; // OTRTODO: Make this an XML Param + soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); sampleBankTable = ParseAudioTable(codeData, gSampleBankTableOffset); - // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + // SEQEUNCE FONT TABLE PARSING + for (int i = 0; i < sequenceTable.size(); i++) + { + uint16_t idx = BitConverter::ToUInt16BE(codeData, gSequenceFontTableOffset + (i * 2)); + uint8_t numFonts = codeData[gSequenceFontTableOffset + (idx++)]; + std::vector fontIds; + + for (int j = 0; j < numFonts; j++) + { + uint8_t fontId = codeData[gSequenceFontTableOffset + (idx++)]; + fontIds.push_back(fontId); + } + + fontIndices.push_back(fontIds); + } // SAMPLE/FONT PARSING @@ -286,13 +370,6 @@ void ZAudio::ParseRawData() ParseSoundFont(audioBankData, audioTableData, sampleBankTable, soundFontTable[i]); } - - // SOUNDBANK PARSING - /*for (int i = 0; i < sampleBankTable.size(); i++) - { - - }*/ - // SEQUENCE PARSING for (int i = 0; i < sequenceTable.size(); i++) { diff --git a/ZAPDTR/ZAPD/ZAudio.h b/ZAPDTR/ZAPD/ZAudio.h index a7c88410f..5d18c2e71 100644 --- a/ZAPDTR/ZAPD/ZAudio.h +++ b/ZAPDTR/ZAPD/ZAudio.h @@ -21,12 +21,14 @@ struct AdpcmLoop /* 0x00 */ uint32_t start; /* 0x04 */ uint32_t end; /* 0x08 */ uint32_t count; - ///* 0x10 */ int16_t state[16]; // only exists if count != 0. 8-byte aligned /* 0x10 */ std::vector states; }; struct SampleEntry { + std::string fileName; + uint8_t bankId; + uint32_t sampleDataOffset; uint8_t codec; uint8_t medium; uint8_t unk_bit26; @@ -51,7 +53,6 @@ struct DrumEntry uint32_t offset; float tuning; std::vector env; - //AdsrEnvelope* env = nullptr; SampleEntry* sample = nullptr; }; @@ -63,7 +64,6 @@ struct InstrumentEntry uint8_t normalRangeHi; uint8_t releaseRate; std::vector env; - //AdsrEnvelope* env = nullptr; SoundFontEntry* lowNotesSound = nullptr; SoundFontEntry* normalNotesSound = nullptr; SoundFontEntry* highNotesSound = nullptr; @@ -92,21 +92,26 @@ public: std::vector sampleBankTable; std::vector> sequences; std::map samples; + std::vector> fontIndices; + std::vector seqNames; + std::map> sampleOffsets; ZAudio(ZFile* nParent); + void ParseXML(tinyxml2::XMLElement* reader) override; + void DecodeADPCMSample(SampleEntry* sample); std::vector ParseEnvelopeData(std::vector audioBank, std::vector audioTable, int envelopeOffset, int baseOffset); SoundFontEntry* ParseSoundFontEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int soundFontOffset, int baseOffset); SampleEntry* ParseSampleEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset); std::vector ParseAudioTable(std::vector codeData, int baseOffset); diff --git a/ZAPDTR/ZAPD/ZResource.cpp b/ZAPDTR/ZAPD/ZResource.cpp index c6efef073..550031ab4 100644 --- a/ZAPDTR/ZAPD/ZResource.cpp +++ b/ZAPDTR/ZAPD/ZResource.cpp @@ -100,11 +100,14 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) attrs = attrs->Next(); } - if (!canHaveInner && !reader->NoChildren()) + if (!Globals::Instance->otrMode) { - std::string errorHeader = StringHelper::Sprintf( - "resource '%s' with inner element/child detected", reader->Name()); - HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); + if (!canHaveInner && !reader->NoChildren()) + { + std::string errorHeader = StringHelper::Sprintf( + "resource '%s' with inner element/child detected", reader->Name()); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); + } } for (const auto& attr : registeredAttributes) @@ -121,7 +124,6 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) name = registeredAttributes.at("Name").value; - // Disable this check for OTR file generation for now since it takes up a considerable amount of CPU time if (!Globals::Instance->otrMode) { diff --git a/libultraship/libultraship/Audio.cpp b/libultraship/libultraship/Audio.cpp index 801fac554..16168a01c 100644 --- a/libultraship/libultraship/Audio.cpp +++ b/libultraship/libultraship/Audio.cpp @@ -15,7 +15,7 @@ namespace Ship int dataSize = reader->ReadInt32(); - for (size_t i = 0; i < dataSize; i++) + for (uint32_t i = 0; i < dataSize; i++) entry->data.push_back(reader->ReadUByte()); entry->loop.start = reader->ReadUInt32(); @@ -24,7 +24,7 @@ namespace Ship int loopStateCnt = reader->ReadUInt32(); - for (size_t i = 0; i < loopStateCnt; i++) + for (uint32_t i = 0; i < loopStateCnt; i++) entry->loop.states.push_back(reader->ReadInt16()); entry->book.order = reader->ReadInt32(); @@ -32,7 +32,7 @@ namespace Ship int bookSize = reader->ReadInt32(); - for (size_t i = 0; i < bookSize; i++) + for (uint32_t i = 0; i < bookSize; i++) entry->book.books.push_back(reader->ReadInt16()); } @@ -42,6 +42,7 @@ namespace Ship ResourceFile::ParseFileBinary(reader, res); + soundFont->id = reader->ReadInt32(); soundFont->medium = reader->ReadByte(); soundFont->cachePolicy = reader->ReadByte(); soundFont->data1 = reader->ReadInt16(); @@ -62,7 +63,7 @@ namespace Ship drum.env = ReadEnvelopeData(reader); bool hasSample = reader->ReadByte(); - drum.offset = reader->ReadInt32(); + drum.sampleFileName = reader->ReadString(); drum.tuning = reader->ReadSingle(); soundFont->drums.push_back(drum); @@ -87,7 +88,7 @@ namespace Ship { entry.lowNotesSound = new SoundFontEntry(); bool hasSampleRef = reader->ReadByte(); - entry.lowNotesSound->sampleOffset = reader->ReadInt32(); + entry.lowNotesSound->sampleFileName = reader->ReadString(); entry.lowNotesSound->tuning = reader->ReadSingle(); } } @@ -99,7 +100,7 @@ namespace Ship { entry.normalNotesSound = new SoundFontEntry(); bool hasSampleRef = reader->ReadByte(); - entry.normalNotesSound->sampleOffset = reader->ReadInt32(); + entry.normalNotesSound->sampleFileName = reader->ReadString(); entry.normalNotesSound->tuning = reader->ReadSingle(); } } @@ -111,7 +112,7 @@ namespace Ship { entry.highNotesSound = new SoundFontEntry(); bool hasSampleRef = reader->ReadByte(); - entry.highNotesSound->sampleOffset = reader->ReadInt32(); + entry.highNotesSound->sampleFileName = reader->ReadString(); entry.highNotesSound->tuning = reader->ReadSingle(); } } @@ -128,7 +129,7 @@ namespace Ship if (hasSFEntry) { bool hasSampleRef = reader->ReadByte(); - entry->sampleOffset = reader->ReadInt32(); + entry->sampleFileName = reader->ReadString(); entry->tuning = reader->ReadSingle(); } @@ -159,10 +160,5 @@ namespace Ship Audio* audio = (Audio*)res; ResourceFile::ParseFileBinary(reader, res); - - //int sampleCnt = reader->ReadInt32(); - - //for (size_t i = 0; i < sampleCnt; i++) - //audio->samples.push_back(ReadSampleEntry(reader)); } } \ No newline at end of file diff --git a/libultraship/libultraship/Audio.h b/libultraship/libultraship/Audio.h index e66846bc0..aa063d638 100644 --- a/libultraship/libultraship/Audio.h +++ b/libultraship/libultraship/Audio.h @@ -3,6 +3,7 @@ #include "Resource.h" #include #include +#include namespace Ship { @@ -24,14 +25,12 @@ namespace Ship /* 0x00 */ uint32_t start; /* 0x04 */ uint32_t end; /* 0x08 */ uint32_t count; - ///* 0x10 */ int16_t state[16]; // only exists if count != 0. 8-byte aligned /* 0x10 */ std::vector states; }; struct SoundFontEntry { - //SampleEntry* sampleEntry = nullptr; - uint32_t sampleOffset; + std::string sampleFileName; float tuning; }; @@ -40,10 +39,9 @@ namespace Ship uint8_t releaseRate; uint8_t pan; uint8_t loaded; - uint32_t offset; + std::string sampleFileName; float tuning; std::vector env; - //SampleEntry* sample = nullptr; }; struct InstrumentEntry @@ -83,6 +81,7 @@ namespace Ship public: uint32_t ptr; uint32_t size; + uint32_t id; uint8_t medium; uint8_t cachePolicy; uint16_t data1; @@ -97,6 +96,7 @@ namespace Ship class AudioSample : public Resource { public: + uint32_t originalOffset; uint8_t codec; uint8_t medium; uint8_t unk_bit26; @@ -115,6 +115,5 @@ namespace Ship //std::vector sampleBankTable; //std::vector sequences; //std::vector samples; - }; } \ No newline at end of file diff --git a/libultraship/libultraship/Resource.h b/libultraship/libultraship/Resource.h index 01949675e..7a1e09517 100644 --- a/libultraship/libultraship/Resource.h +++ b/libultraship/libultraship/Resource.h @@ -12,10 +12,10 @@ namespace Ship { enum class ResourceType { - Archive = 0x4F415243, // OARC - Model = 0x4F4D444C, // OMDL + Archive = 0x4F415243, // OARC (UNUSED) + Model = 0x4F4D444C, // OMDL (WIP) Texture = 0x4F544558, // OTEX - Material = 0x4F4D4154, // OMAT + Material = 0x4F4D4154, // OMAT (WIP) Animation = 0x4F414E4D, // OANM PlayerAnimation = 0x4F50414D, // OPAM DisplayList = 0x4F444C54, // ODLT diff --git a/libultraship/libultraship/ResourceMgr.cpp b/libultraship/libultraship/ResourceMgr.cpp index a028bc39c..b92ce8103 100644 --- a/libultraship/libultraship/ResourceMgr.cpp +++ b/libultraship/libultraship/ResourceMgr.cpp @@ -340,6 +340,18 @@ namespace Ship { return LoadedList; } + std::shared_ptr> ResourceMgr::ListFiles(std::string SearchMask) + { + auto result = std::make_shared>(); + auto fileList = OTR->ListFiles(SearchMask); + + for (DWORD i = 0; i < fileList.size(); i++) { + result->push_back(fileList[i].cFileName); + } + + return result; + } + void ResourceMgr::InvalidateResourceCache() { ResourceCache.clear(); } diff --git a/libultraship/libultraship/ResourceMgr.h b/libultraship/libultraship/ResourceMgr.h index e76d5b521..97d276ad6 100644 --- a/libultraship/libultraship/ResourceMgr.h +++ b/libultraship/libultraship/ResourceMgr.h @@ -41,6 +41,7 @@ namespace Ship std::shared_ptr>> CacheDirectory(std::string SearchMask); std::shared_ptr>> CacheDirectoryAsync(std::string SearchMask); std::shared_ptr>> DirtyDirectory(std::string SearchMask); + std::shared_ptr> ListFiles(std::string SearchMask); protected: void Start(); diff --git a/libultraship/libultraship/WasapiAudioPlayer.cpp b/libultraship/libultraship/WasapiAudioPlayer.cpp index 30cb10905..7ec56b898 100644 --- a/libultraship/libultraship/WasapiAudioPlayer.cpp +++ b/libultraship/libultraship/WasapiAudioPlayer.cpp @@ -30,8 +30,8 @@ namespace Ship { WAVEFORMATEX desired; desired.wFormatTag = WAVE_FORMAT_PCM; desired.nChannels = 2; - desired.nSamplesPerSec = 32000; - desired.nAvgBytesPerSec = 32000 * 2 * 2; + desired.nSamplesPerSec = 44000; // OTRTODO + desired.nAvgBytesPerSec = 44000 * 2 * 2; // OTRTODO desired.nBlockAlign = 4; desired.wBitsPerSample = 16; desired.cbSize = 0; diff --git a/soh/assets/xml/GC_NMQ_D/audio/Audio.xml b/soh/assets/xml/GC_NMQ_D/audio/Audio.xml index af810ab0c..a7b0d1af4 100644 --- a/soh/assets/xml/GC_NMQ_D/audio/Audio.xml +++ b/soh/assets/xml/GC_NMQ_D/audio/Audio.xml @@ -1,5 +1,1518 @@ - diff --git a/soh/assets/xml/GC_NMQ_PAL_F/audio/Audio.xml b/soh/assets/xml/GC_NMQ_PAL_F/audio/Audio.xml index af810ab0c..726e93dca 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/audio/Audio.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/audio/Audio.xml @@ -1,5 +1,6 @@ - diff --git a/soh/include/global.h b/soh/include/global.h index 2e4808fe0..65203c1aa 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -18,11 +18,6 @@ #define _AudiotableSegmentRomStart "Audiotable" - - - -#define _icon_item_gameover_staticSegmentRomStart 0 -#define _icon_item_gameover_staticSegmentRomEnd 0 #define _icon_item_staticSegmentRomStart 0 #define _icon_item_staticSegmentRomEnd 0 #define _map_i_staticSegmentRomStart 0 diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index 09840def7..9a50c1510 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -18,6 +18,8 @@ #define AIBUF_LEN 0x580 +#define CALC_RESAMPLE_FREQ(sampleRate) (sampleRate / (s32)gAudioContext.audioBufferParameters.frequency) + typedef enum { /* 0 */ ADSR_STATE_DISABLED, /* 1 */ ADSR_STATE_INITIAL, @@ -136,6 +138,8 @@ typedef struct /* 0x04 */ u8* sampleAddr; /* 0x08 */ AdpcmLoop* loop; /* 0x0C */ AdpcmBook* book; + u32 sampleRateMagicValue; // For wav samples only... + s32 sampleRate; // For wav samples only... } SoundFontSample; // size = 0x10 typedef struct { @@ -1062,6 +1066,16 @@ typedef enum { /* -1 */ OCARINA_NOTE_INVALID = 0xFF } OcarinaNoteIdx; +typedef struct { + char* seqData; + int32_t seqDataSize; + uint8_t seqNumber; + uint8_t medium; + uint8_t cachePolicy; + int32_t numFonts; + uint8_t fonts[16]; +} SequenceData; + #ifdef __cplusplus extern "C" { #endif diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 5bf4b29fc..7f554b8ee 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -59,6 +59,7 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len); extern "C" int AudioPlayer_Buffered(void); extern "C" int AudioPlayer_GetDesiredBuffered(void); extern "C" void ResourceMgr_CacheDirectory(const char* resName); +extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path); // C->C++ Bridge extern "C" void OTRAudio_Init() @@ -200,11 +201,16 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { //AudioMgr_ThreadEntry(&gAudioMgr); // 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333.. // in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528 - #define SAMPLES_HIGH 560 - #define SAMPLES_LOW 528 + //#define SAMPLES_HIGH 560 + //#define SAMPLES_LOW 528 // PAL values //#define SAMPLES_HIGH 656 //#define SAMPLES_LOW 624 + + // 44KHZ values + #define SAMPLES_HIGH 752 + #define SAMPLES_LOW 720 + #define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 ) #define NUM_AUDIO_CHANNELS 2 int samples_left = AudioPlayer_Buffered(); @@ -293,6 +299,22 @@ extern "C" void ResourceMgr_InvalidateCache() { OTRGlobals::Instance->context->GetResourceManager()->InvalidateResourceCache(); } +// OTRTODO: There is probably a more elegant way to go about this... +extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) { + auto lst = OTRGlobals::Instance->context->GetResourceManager()->ListFiles(searchMask); + char** result = (char**)malloc(lst->size() * sizeof(char*)); + + for (int i = 0; i < lst->size(); i++) { + char* str = (char*)malloc(lst.get()[0][i].size() + 1); + memcpy(str, lst.get()[0][i].data(), lst.get()[0][i].size()); + str[lst.get()[0][i].size()] = '\0'; + result[i] = str; + } + + *resultSize = lst->size(); + + return result; +} extern "C" void ResourceMgr_LoadFile(const char* resName) { OTRGlobals::Instance->context->GetResourceManager()->LoadResource(resName); @@ -517,35 +539,53 @@ extern "C" Vtx* ResourceMgr_LoadVtxByName(const char* path) return (Vtx*)res->vertices.data(); } -extern "C" char* ResourceMgr_LoadSeqByID(int seqID) -{ +extern "C" SequenceData ResourceMgr_LoadSeqByID(int seqID) { + if (seqID == 0xFF) { + SequenceData sDat; + sDat.numFonts = 0; + + return sDat; + } + std::string fmtStr = "audio/sequences/seq_%02X"; - return OTRGlobals::Instance->context->GetResourceManager()->LoadFile(StringHelper::Sprintf(fmtStr.c_str(), seqID)).get()->buffer.get(); + return ResourceMgr_LoadSeqByName(StringHelper::Sprintf(fmtStr.c_str(), seqID).c_str()); } -extern "C" int ResourceMgr_GetSeqSizeByID(int seqID) +extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) { - return OTRGlobals::Instance->context->GetResourceManager() - ->LoadFile(StringHelper::Sprintf("audio/sequences/seq_%02X", seqID)) - .get() - ->dwBufferSize; + auto file = OTRGlobals::Instance->context->GetResourceManager()->LoadFile(path).get(); + + char* data = file->buffer.get(); + + SequenceData seqData; + seqData.seqNumber = data[1]; + seqData.medium = data[2]; + seqData.cachePolicy = data[3]; + seqData.numFonts = data[4]; + + for (int i = 0; i < seqData.numFonts; i++) + seqData.fonts[i] = data[5 + i]; + + seqData.seqData = &data[5 + seqData.numFonts]; + seqData.seqDataSize = file->dwBufferSize - 5 - seqData.numFonts; + + return seqData; } std::map cachedCustomSFs; -extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(int romOffset) +extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path) { - auto str = StringHelper::Sprintf("audio/samples/sample_%08X", romOffset); + //auto str = StringHelper::Sprintf("audio/samples/sample_%08X", romOffset); - if (cachedCustomSFs.find(str) != cachedCustomSFs.end()) - return cachedCustomSFs[str]; + if (std::string(path) == "") + return nullptr; - if (romOffset == 0x14f0) { - int bp = 0; - } + if (cachedCustomSFs.find(path) != cachedCustomSFs.end()) + return cachedCustomSFs[path]; // Check if our file is actually a wav... - auto sampleRaw = OTRGlobals::Instance->context->GetResourceManager()->LoadFile(str); + auto sampleRaw = OTRGlobals::Instance->context->GetResourceManager()->LoadFile(path); uint32_t* strem = (uint32_t*)sampleRaw->buffer.get(); uint8_t* strem2 = (uint8_t*)strem; @@ -559,6 +599,8 @@ extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(int romOffset) *strem++; // fmt int fmtChunkSize = *strem++; + *strem++; // wFormatTag + wChannels + int32_t sampleRate = *strem++; // dwSamplesPerSec // OTRTODO: Make sure wav format is what the audio driver wants! strem = (uint32_t*)&strem2[0x0C + fmtChunkSize + 8 + 4]; @@ -571,12 +613,15 @@ extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(int romOffset) sampleC->loop->start = 0; sampleC->loop->end = sampleC->size / 2; sampleC->loop->count = 0; - - cachedCustomSFs[str] = sampleC; + sampleC->sampleRateMagicValue = 'RIFF'; + sampleC->sampleRate = sampleRate; + + cachedCustomSFs[path] = sampleC; return sampleC; } - auto sample = std::static_pointer_cast(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(str)); + auto sample = std::static_pointer_cast( + OTRGlobals::Instance->context->GetResourceManager()->LoadResource(path)); if (sample == nullptr) return NULL; @@ -584,7 +629,6 @@ extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(int romOffset) if (sample->cachedGameAsset != nullptr) { SoundFontSample* sampleC = (SoundFontSample*)sample->cachedGameAsset; - return (SoundFontSample*)sample->cachedGameAsset; } else @@ -664,7 +708,7 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex) { } } - drum->sound.sample = ResourceMgr_LoadAudioSample(soundFont->drums[i].offset); + drum->sound.sample = ResourceMgr_LoadAudioSample(soundFont->drums[i].sampleFileName.c_str()); drum->sound.tuning = soundFont->drums[i].tuning; soundFontC->drums[i] = drum; @@ -698,7 +742,7 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex) { if (soundFont->instruments[i].lowNotesSound != nullptr) { inst->lowNotesSound.sample = - ResourceMgr_LoadAudioSample(soundFont->instruments[i].lowNotesSound->sampleOffset); + ResourceMgr_LoadAudioSample(soundFont->instruments[i].lowNotesSound->sampleFileName.c_str()); inst->lowNotesSound.tuning = soundFont->instruments[i].lowNotesSound->tuning; } else { inst->lowNotesSound.sample = NULL; @@ -707,7 +751,7 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex) { if (soundFont->instruments[i].normalNotesSound != nullptr) { inst->normalNotesSound.sample = - ResourceMgr_LoadAudioSample(soundFont->instruments[i].normalNotesSound->sampleOffset); + ResourceMgr_LoadAudioSample(soundFont->instruments[i].normalNotesSound->sampleFileName.c_str()); inst->normalNotesSound.tuning = soundFont->instruments[i].normalNotesSound->tuning; } else { @@ -717,7 +761,7 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex) { if (soundFont->instruments[i].highNotesSound != nullptr) { inst->highNotesSound.sample = - ResourceMgr_LoadAudioSample(soundFont->instruments[i].highNotesSound->sampleOffset); + ResourceMgr_LoadAudioSample(soundFont->instruments[i].highNotesSound->sampleFileName.c_str()); inst->highNotesSound.tuning = soundFont->instruments[i].highNotesSound->tuning; } else { inst->highNotesSound.sample = NULL; @@ -735,7 +779,7 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex) { for (int i = 0; i < soundFont->soundEffects.size(); i++) { - soundFontC->soundEffects[i].sample = ResourceMgr_LoadAudioSample(soundFont->soundEffects[i]->sampleOffset); + soundFontC->soundEffects[i].sample = ResourceMgr_LoadAudioSample(soundFont->soundEffects[i]->sampleFileName.c_str()); soundFontC->soundEffects[i].tuning = soundFont->soundEffects[i]->tuning; } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index d21d94ca5..f5b3e25d3 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -35,6 +35,7 @@ uint16_t OTRGetPixelDepth(float x, float y); int32_t OTRGetLastScancode(); uint32_t ResourceMgr_GetGameVersion(); void ResourceMgr_CacheDirectory(const char* resName); +char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize); void ResourceMgr_LoadFile(const char* resName); char* ResourceMgr_LoadFileFromDisk(const char* filePath); char* ResourceMgr_LoadTexByName(const char* texPath); @@ -46,6 +47,10 @@ Gfx* ResourceMgr_LoadGfxByName(const char* path); Gfx* ResourceMgr_PatchGfxByName(const char* path, int size); Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc); Vtx* ResourceMgr_LoadVtxByName(const char* path); +SoundFont* ResourceMgr_LoadAudioSoundFont(int fontIndex); +SequenceData ResourceMgr_LoadSeqByID(int seqID); +SequenceData ResourceMgr_LoadSeqByName(const char* path); +SoundFontSample* ResourceMgr_LoadAudioSample(const char* path); CollisionHeader* ResourceMgr_LoadColByName(const char* path); uint64_t GetPerfCounter(); struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path); diff --git a/soh/soh/stubs.c b/soh/soh/stubs.c index 26f4d0ae6..0074bc16b 100644 --- a/soh/soh/stubs.c +++ b/soh/soh/stubs.c @@ -1875,7 +1875,9 @@ AudioTable gSampleBankTable = { 0x0007, }; #endif -// OTRTODO: Implement This in OTR File +#if 0 +u8 gSequenceFontTable[1] = { 0 }; +#else u8 gSequenceFontTable[0x1C0] = { 0xDC, 0x00, @@ -2111,3 +2113,4 @@ u8 gSequenceFontTable[0x1C0] = { 0x03, 0x01, 0x1F, 0x01, 0x20, 0x01, 0x20, 0x01, 0x09, 0x01, 0x21, 0x01, 0x22, 0x01, 0x21, 0x01, 0x09, 0x01, 0x20, 0x01, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +#endif \ No newline at end of file diff --git a/soh/src/code/audio_data.c b/soh/src/code/audio_data.c index 540eedca8..5fe49139b 100644 --- a/soh/src/code/audio_data.c +++ b/soh/src/code/audio_data.c @@ -544,16 +544,10 @@ u8 gDefaultShortNoteGateTimeTable[] = { }; AdsrEnvelope gDefaultEnvelope[] = { - // OTRTODO: Byteswapped manually for quick audio support. { 0x0100, 0x007D }, { 0xE803, 0x007D }, { 0xFFFF, 0x0000 }, { 0x0000, 0x0000 }, - /* { 1, 32000 }, - { 1000, 32000 }, - { -1, 0 }, - { 0, 0 }, - */ }; NoteSubEu gZeroNoteSub = { 0 }; diff --git a/soh/src/code/audio_init_params.c b/soh/src/code/audio_init_params.c index 0cebdf596..8d990b623 100644 --- a/soh/src/code/audio_init_params.c +++ b/soh/src/code/audio_init_params.c @@ -66,23 +66,24 @@ ReverbSettings D_80133420[][3] = { }, }; +// OTRTODO AudioSpec gAudioSpecs[18] = { - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 }, - { 32000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 }, - { 32000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 }, - { 32000, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 }, + { 44000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 }, + { 44000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 }, + { 44000, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, + { 44000, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, { 22050, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 }, - { 32000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 }, + { 44000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 }, }; diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c index ecb6eab2d..0732d2fa3 100644 --- a/soh/src/code/audio_load.c +++ b/soh/src/code/audio_load.c @@ -45,7 +45,7 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 tableId, s32* didAllocate); u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 tableId); void* AudioLoad_SearchCaches(s32 tableType, s32 id); AudioTable* AudioLoad_GetLoadTable(s32 tableType); -void AudioLoad_SyncDma(u32 devAddr, u8* addr, size_t size, s32 medium); +void AudioLoad_SyncDma(uintptr_t devAddr, u8* addr, size_t size, s32 medium); void AudioLoad_SyncDmaUnkMedium(u32 devAddr, u8* addr, size_t size, s32 unkMediumParam); s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void* ramAddr, size_t size, OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType); @@ -75,6 +75,8 @@ void* sUnusedHandler = NULL; s32 gAudioContextInitalized = false; +char* sequenceMap[256]; + uintptr_t fontStart; uint32_t fontOffsets[8192]; @@ -372,7 +374,7 @@ void AudioLoad_InitTable(AudioTable* table, uintptr_t romAddr, u16 unkMediumPara SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) { char pad[0x8]; s32 index; - SoundFontData* font; + SoundFontData* font = NULL; s32 numFonts; s32 fontId; s32 i; @@ -387,6 +389,7 @@ SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) { while (numFonts > 0) { fontId = gAudioContext.sequenceFontTable[index++]; + font = AudioLoad_SyncLoadFont(fontId); numFonts--; } @@ -479,13 +482,26 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { s32 index; - index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; + if (!gUseLegacySD) + { + if (seqId == 255) + return NULL; - *outNumFonts = gAudioContext.sequenceFontTable[index++]; - if (*outNumFonts == 0) { - return NULL; + SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]); + + if (sDat.numFonts == 0) + return NULL; + + return sDat.fonts; + } else { + index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; + + *outNumFonts = gAudioContext.sequenceFontTable[index++]; + if (*outNumFonts == 0) { + return NULL; + } + return &gAudioContext.sequenceFontTable[index]; } - return &gAudioContext.sequenceFontTable[index]; } void AudioLoad_DiscardSeqFonts(s32 seqId) { @@ -564,16 +580,29 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { AudioSeq_SequencePlayerDisable(seqPlayer); fontId = 0xFF; - index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; - numFonts = gAudioContext.sequenceFontTable[index++]; - while (numFonts > 0) { - fontId = gAudioContext.sequenceFontTable[index++]; - - //if (gUseLegacySD) - AudioLoad_SyncLoadFont(fontId); - - numFonts--; + if (gUseLegacySD) { + index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; + numFonts = gAudioContext.sequenceFontTable[index++]; + + while (numFonts > 0) { + fontId = gAudioContext.sequenceFontTable[index++]; + + AudioLoad_SyncLoadFont(fontId); // NOTE: If this is commented out, then enemies will play child link sounds... + + numFonts--; + } + } + else + { + SequenceData seqData2 = ResourceMgr_LoadSeqByName(sequenceMap[seqId]); + + for (int i = 0; i < seqData2.numFonts; i++) + { + fontId = seqData2.fonts[i]; + AudioLoad_SyncLoadFont(fontId); // NOTE: If this is commented out, then enemies will play child link sounds... + numFonts--; + } } seqData = AudioLoad_SyncLoadSeq(seqId); @@ -655,7 +684,6 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) { s32 didAllocate; RelocInfo relocInfo; s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId); - //s32 realFontId = fontId; if (gAudioContext.fontLoadStatus[realFontId] == 1) { return NULL; @@ -720,13 +748,12 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) { if (!gUseLegacySD && tableType == SEQUENCE_TABLE) { - seqData = ResourceMgr_LoadSeqByID(id); - size = ResourceMgr_GetSeqSizeByID(id); - size -= 2; - medium = seqData[0]; - cachePolicy = seqData[1]; + SequenceData sData = ResourceMgr_LoadSeqByName(sequenceMap[id]); + seqData = sData.seqData; + size = sData.seqDataSize; + medium = sData.medium; + cachePolicy = sData.cachePolicy; romAddr = 0; - seqData += 2; } else if (!gUseLegacySD && tableType == FONT_TABLE) { @@ -996,7 +1023,7 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo } } -void AudioLoad_SyncDma(u32 devAddr, u8* addr, size_t size, s32 medium) { +void AudioLoad_SyncDma(uintptr_t devAddr, u8* addr, size_t size, s32 medium) { OSMesgQueue* msgQueue = &gAudioContext.syncDmaQueue; OSIoMesg* ioMesg = &gAudioContext.syncDmaIoMesg; size = ALIGN16(size); @@ -1179,7 +1206,6 @@ s32 AudioLoad_AssertValidAddr(uintptr_t ramAddr, uintptr_t startAddr, size_t siz #define BASE_ROM_OFFSET(x) (void*)((u32)(x) + (u32)(romAddr)) void AudioLoad_InitSwapFontSampleHeaders(SoundFontSample* sample, uintptr_t romAddr) { - // OTRTODO: This will be removed when we actually extract the data. size_t maxSoundFontSize = 0x3AA0; // soundFont 0 is the largest size at 0x3AA0 AdpcmLoop* loop; AdpcmBook* book; @@ -1400,7 +1426,12 @@ void AudioLoad_Init(void* heap, u32 heapSize) { AudioLoad_InitTable(gAudioContext.sequenceTable, seqStart, 0); AudioLoad_InitTable(gAudioContext.soundFontTable, bankStart, 0); AudioLoad_InitTable(gAudioContext.sampleBankTable, tableStart, 0); - numFonts = gAudioContext.soundFontTable->numEntries; + + if (gUseLegacySD) + numFonts = gAudioContext.soundFontTable->numEntries; + else + numFonts = 0x26; // OTRTODO: Count the number of soundfonts that are inside the OTR(s) + gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont)); if (gUseLegacySD) { @@ -1409,6 +1440,23 @@ void AudioLoad_Init(void* heap, u32 heapSize) { } AudioLoad_InitSwapFont(); + } else { + int seqListSize = 0; + char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize); + + for (int i = 0; i < seqListSize; i++) + { + SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]); + + char* str = malloc(strlen(seqList[i]) + 1); + strcpy(str, seqList[i]); + + sequenceMap[sDat.seqNumber] = str; + } + + free(seqList); + + int bp = 0; } if (temp_v0_3 = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize), temp_v0_3 == NULL) { @@ -1429,7 +1477,6 @@ void AudioLoad_InitSlowLoads(void) { s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) { SoundFontSample* sample; AudioSlowLoad* slowLoad; - sample = AudioLoad_GetFontSample(fontId, instId); if (sample == NULL) { *isDone = 0; @@ -1601,11 +1648,13 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) { slowLoad->sample.sampleAddr = NULL; slowLoad->isDone = isDone; - if (!gUseLegacySD) { - char* seqData = ResourceMgr_LoadSeqByID(seqId); - size = ResourceMgr_GetSeqSizeByID(seqId) - 2; - slowLoad->curDevAddr = seqData + 2; - slowLoad->medium = seqData[0]; + if (!gUseLegacySD) + { + SequenceData sData = ResourceMgr_LoadSeqByName(sequenceMap[seqId]); + char* seqData = sData.seqData; + size = sData.seqDataSize; + slowLoad->curDevAddr = seqData; + slowLoad->medium = sData.medium; } else { size = seqTable->entries[seqId].size; size = ALIGN16(size); @@ -1829,41 +1878,23 @@ void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, void* ramAddr, size_t size, s16 ar #define RELOC(v, base) (reloc = (void*)((u32)(v) + (u32)(base))) void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo, int fontId) { - // OTRTODO: This is hack to detect whether or not the sample has been relocated. size_t maxSoundBankSize = 0x3EB2A0; // sample bank 0 is largest size at 0x3EB2A0 - if ((uintptr_t)mem <= maxSoundBankSize) { - // OTRTODO: This can be removed once we have properly byteswapped files on the disk. - assert("mem for sound font bank is too low."); + if (gUseLegacySD) + { + // NOTE: This is hack to detect whether or not the sample has been relocated. + if ((uintptr_t)mem <= maxSoundBankSize) { + assert("mem for sound font bank is too low."); + } } SoundFontSample* sample; void* reloc; - // OTRTODO: Seems precarious to assume the RAM is never <= 0x3EB2A0, but it largely works. + // NOTE: Seems precarious to assume the RAM is never <= 0x3EB2A0, but it largely works. if ((uintptr_t)sound->sample < maxSoundBankSize || !gUseLegacySD) { if (!gUseLegacySD) { SoundFontSample* sample2 = sound; - - if (sample2->unk_bit25 != 1) - { - //if (sample2->size == 0x5CC8) - //{ - // switch (sample2->medium) { - // case 0: - // sample2->medium = relocInfo->medium1; - // break; - // case 1: - // sample2->medium = relocInfo->medium2; - // break; - // } - - // sample2->unk_bit25 = 1; - // if (sample2->unk_bit26 && (sample2->medium != MEDIUM_RAM)) { - // // gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample2; - // } - //} - } } else { sample = sound->sample = RELOC(sound->sample, mem); @@ -2116,8 +2147,10 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) { void AudioLoad_AddUsedSample(SoundFontSound* sound) { SoundFontSample* sample = sound->sample; - if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) { - gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample; + if (sample != NULL) { + if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) { + gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample; + } } } diff --git a/soh/src/code/audio_playback.c b/soh/src/code/audio_playback.c index 5d43118b8..9992eee3d 100644 --- a/soh/src/code/audio_playback.c +++ b/soh/src/code/audio_playback.c @@ -286,7 +286,18 @@ void Audio_ProcessNotes(void) { } subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale; - subAttrs.frequency *= gAudioContext.audioBufferParameters.resampleRate; + + f32 resampRate = gAudioContext.audioBufferParameters.resampleRate; + + if (!gUseLegacySD && !noteSubEu2->bitField1.isSyntheticWave && noteSubEu2->sound.soundFontSound != NULL && + noteSubEu2->sound.soundFontSound->sample != NULL && + noteSubEu2->sound.soundFontSound->sample->sampleRateMagicValue == 'RIFF') { + resampRate = CALC_RESAMPLE_FREQ(noteSubEu2->sound.soundFontSound->sample->sampleRate); + } + + subAttrs.frequency *= resampRate; + + subAttrs.velocity *= scale; Audio_InitNoteSub(note, noteSubEu2, &subAttrs); noteSubEu->bitField1.bookOffset = bookOffset; diff --git a/soh/src/code/audio_seqplayer.c b/soh/src/code/audio_seqplayer.c index 52d14a9a1..beac78269 100644 --- a/soh/src/code/audio_seqplayer.c +++ b/soh/src/code/audio_seqplayer.c @@ -3,6 +3,9 @@ #include "ultra64.h" #include "global.h" +extern bool gUseLegacySD; +extern char* sequenceMap[256]; + #define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80) #define PORTAMENTO_MODE(x) ((x).mode & ~0x80) #define PORTAMENTO_MODE_1 1 @@ -1060,9 +1063,15 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { command = (u8)parameters[0]; if (seqPlayer->defaultFont != 0xFF) { - offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; - lowBits = gAudioContext.sequenceFontTable[offset]; - command = gAudioContext.sequenceFontTable[offset + lowBits - result]; + if (gUseLegacySD) { + offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; + lowBits = gAudioContext.sequenceFontTable[offset]; + command = gAudioContext.sequenceFontTable[offset + lowBits - result]; + } + else { + SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]); + command = sDat.fonts[sDat.numFonts - result - 1]; + } } if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) { @@ -1170,10 +1179,17 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { result = (u8)parameters[0]; command = (u8)parameters[0]; - if (seqPlayer->defaultFont != 0xFF) { - offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; - lowBits = gAudioContext.sequenceFontTable[offset]; - command = gAudioContext.sequenceFontTable[offset + lowBits - result]; + if (seqPlayer->defaultFont != 0xFF) + { + if (gUseLegacySD) { + offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; + lowBits = gAudioContext.sequenceFontTable[offset]; + command = gAudioContext.sequenceFontTable[offset + lowBits - result]; + } + else { + SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]); + command = sDat.fonts[sDat.numFonts - result - 1]; + } } if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) { @@ -1330,14 +1346,12 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xB2: offset = (u16)parameters[0]; - // OTRTODO: Byteswap added for quick audio channel->unk_22 = BOMSWAP16(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); break; case 0xB4: channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22]; break; case 0xB5: - // OTRTODO: Byteswap added for quick audio channel->unk_22 = BOMSWAP16(((u16*)(channel->dynTable))[scriptState->value]); break; case 0xB6: diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c index b567dd0ef..0f402b111 100644 --- a/soh/src/code/audio_synthesis.c +++ b/soh/src/code/audio_synthesis.c @@ -440,11 +440,11 @@ void func_800DBE64(void) { void func_800DBE6C(void) { } -void AudioSynth_LoadFilter(Acmd* cmd, s32 flags, s32 countOrBuf, s32 addr) { +void AudioSynth_LoadFilter(Acmd* cmd, s32 flags, s32 countOrBuf, uintptr_t addr) { aFilter(cmd, flags, countOrBuf, addr); } -void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, s32 addr) { +void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, uintptr_t addr) { aFilter(cmd, 2, count, addr); } @@ -561,6 +561,9 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat NoteSubEu* noteSubEu2; s32 unk14; + if (aiBufLen == 0) + return; + t = gAudioContext.numNotes * updateIndex; count = 0; if (gAudioContext.numSynthesisReverbs == 0) { diff --git a/soh/src/code/code_800F9280.c b/soh/src/code/code_800F9280.c index e23ede0e9..6ca2ad75d 100644 --- a/soh/src/code/code_800F9280.c +++ b/soh/src/code/code_800F9280.c @@ -363,7 +363,11 @@ void Audio_ProcessSeqCmd(u32 cmd) { } } -void Audio_QueueSeqCmd(u32 cmd) { +extern f32 D_80130F24; +extern f32 D_80130F28; + +void Audio_QueueSeqCmd(u32 cmd) +{ sAudioSeqCmds[sSeqCmdWrPos++] = cmd; }