diff options
| author | Nicholas Estelami <NEstelami@users.noreply.github.com> | 2022-06-10 13:37:50 -0400 |
|---|---|---|
| committer | Nicholas Estelami <NEstelami@users.noreply.github.com> | 2022-06-10 13:37:50 -0400 |
| commit | f1b81b7f82fcc12f925df3563c8b53f50cf40b91 (patch) | |
| tree | db2e6dfe860d9932dd889420f00dbfe5b8bbdf86 /ZAPDTR | |
| parent | fc7da35054a8e7a12fb6dd5dfa01082c2b049c63 (diff) | |
Audio support nearly complete.
Diffstat (limited to 'ZAPDTR')
| -rw-r--r-- | ZAPDTR/ZAPD/ZAudio.cpp | 125 | ||||
| -rw-r--r-- | ZAPDTR/ZAPD/ZAudio.h | 15 | ||||
| -rw-r--r-- | ZAPDTR/ZAPD/ZResource.cpp | 12 |
3 files changed, 118 insertions, 34 deletions
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<AdsrEnvelope*> ZAudio::ParseEnvelopeData(std::vector<uint8_t> audioB { std::vector<AdsrEnvelope*> result; - //bool process = true; - - //for (int i = 0; i < 4; i++) while (true) { AdsrEnvelope* env = new AdsrEnvelope(); @@ -49,13 +94,13 @@ std::vector<AdsrEnvelope*> ZAudio::ParseEnvelopeData(std::vector<uint8_t> audioB SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector<uint8_t> audioBank, std::vector<uint8_t> 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<uint8_t> audioBank, SampleEntry* ZAudio::ParseSampleEntry(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset) { @@ -74,6 +119,8 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector<uint8_t> 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<uint8_t> 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<uint8_t> codeData, std::vector<uint8_t> { 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<uint8_t> codeData, std::vector<uint8_t> 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<uint8_t> codeData, std::vector<uint8_t> 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<uint32_t> 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<int16_t> 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<AdsrEnvelope*> env; - //AdsrEnvelope* env = nullptr; SampleEntry* sample = nullptr; }; @@ -63,7 +64,6 @@ struct InstrumentEntry uint8_t normalRangeHi; uint8_t releaseRate; std::vector<AdsrEnvelope*> env; - //AdsrEnvelope* env = nullptr; SoundFontEntry* lowNotesSound = nullptr; SoundFontEntry* normalNotesSound = nullptr; SoundFontEntry* highNotesSound = nullptr; @@ -92,21 +92,26 @@ public: std::vector<AudioTableEntry> sampleBankTable; std::vector<std::vector<char>> sequences; std::map<uint32_t, SampleEntry*> samples; + std::vector<std::vector<uint32_t>> fontIndices; + std::vector<std::string> seqNames; + std::map<uint32_t, std::map<uint32_t, std::string>> sampleOffsets; ZAudio(ZFile* nParent); + void ParseXML(tinyxml2::XMLElement* reader) override; + void DecodeADPCMSample(SampleEntry* sample); std::vector<AdsrEnvelope*> ParseEnvelopeData(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, int envelopeOffset, int baseOffset); SoundFontEntry* ParseSoundFontEntry(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int soundFontOffset, int baseOffset); SampleEntry* ParseSampleEntry(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset); std::vector<AudioTableEntry> ParseAudioTable(std::vector<uint8_t> 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) { |
