diff options
| author | Nicholas Estelami <NEstelami@users.noreply.github.com> | 2022-06-01 13:06:32 -0400 |
|---|---|---|
| committer | Nicholas Estelami <NEstelami@users.noreply.github.com> | 2022-06-01 13:06:32 -0400 |
| commit | 6f5ce7d7157d60c22ca7cd43ff576fc54dc50dbc (patch) | |
| tree | e1951884c7dc3dd77b45e46d8a615361c0ae9dd4 /ZAPDTR/ZAPD/ZAudio.cpp | |
| parent | 72bacabf4556ea6c3bc49fdd333d84e49e54b8b3 (diff) | |
Audio decompiled and WIP custom sample support
Diffstat (limited to 'ZAPDTR/ZAPD/ZAudio.cpp')
| -rw-r--r-- | ZAPDTR/ZAPD/ZAudio.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp new file mode 100644 index 000000000..1c24c824a --- /dev/null +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -0,0 +1,325 @@ +#include "ZAudio.h" + +#include "Globals.h" +#include "Utils/BitConverter.h" +#include "Utils/File.h" +#include "Utils/Path.h" +#include "Utils/StringHelper.h" +#include "ZFile.h" + +REGISTER_ZFILENODE(Audio, ZAudio); + +ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent) +{ + //RegisterRequiredAttribute("CodeOffset"); + //RegisterOptionalAttribute("LangOffset", "0"); +} + +void ZAudio::DecodeADPCMSample(SampleEntry* sample) +{ + int16_t buffer[1024 * 128]; + + int16_t* out = &buffer[0]; +} + +std::vector<AdsrEnvelope*> ZAudio::ParseEnvelopeData(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, int envelopeOffset, int baseOffset) +{ + std::vector<AdsrEnvelope*> result; + + //bool process = true; + + //for (int i = 0; i < 4; i++) + while (true) + { + AdsrEnvelope* env = new AdsrEnvelope(); + + env->delay = BitConverter::ToInt16BE(audioBank, envelopeOffset + 0); + env->arg = BitConverter::ToInt16BE(audioBank, envelopeOffset + 2); + + envelopeOffset += 4; + + result.push_back(env); + + if (env->delay < 0) + break; + } + + return result; +} + +SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector<uint8_t> audioBank, + std::vector<uint8_t> audioTable, + AudioTableEntry audioSampleBankEntry, + int soundFontOffset, + int baseOffset) +{ + SoundFontEntry* soundFont = new SoundFontEntry(); + soundFont->sampleEntry = ParseSampleEntry( + audioBank, audioTable, audioSampleBankEntry, + BitConverter::ToInt32BE(audioBank, soundFontOffset + 0) + baseOffset, baseOffset); + soundFont->tuning = BitConverter::ToFloatBE(audioBank, soundFontOffset + 4); + + return soundFont; +} + +SampleEntry* ZAudio::ParseSampleEntry(std::vector<uint8_t> audioBank, + std::vector<uint8_t> audioTable, + AudioTableEntry audioSampleBankEntry, + int sampleOffset, + int baseOffset) +{ + int sampleDataOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 4) + audioSampleBankEntry.ptr; + + if (samples.find(sampleOffset) == samples.end()) + { + SampleEntry* sample = new SampleEntry(); + + int sampleSize = BitConverter::ToInt32BE(audioBank, sampleOffset + 0) & 0x00FFFFFF; + int loopOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 8) + baseOffset; + int bookOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 12) + baseOffset; + + char* sampleData = (char*)malloc(sampleSize); + memcpy(sampleData, audioTable.data() + sampleDataOffset, sampleSize); + sample->data = std::vector<uint8_t>(sampleSize); + memcpy(sample->data.data(), sampleData, sampleSize); + + uint32_t origField = (BitConverter::ToUInt32BE(audioBank, sampleOffset + 0)); + sample->codec = (origField >> 28) & 0x0F; + sample->medium = (origField >> 24) & 0x03; + sample->unk_bit26 = (origField >> 22) & 0x01; + sample->unk_bit25 = (origField >> 21) & 0x01; + + sample->loop.start = BitConverter::ToInt32BE(audioBank, loopOffset + 0); + sample->loop.end = BitConverter::ToInt32BE(audioBank, loopOffset + 4); + sample->loop.count = BitConverter::ToInt32BE(audioBank, loopOffset + 8); + + if (sample->loop.count != 0xFFFFFFFF) + { + for (int i = 0; i < sample->loop.count; i++) + { + int16_t state = BitConverter::ToInt16BE(sample->data, loopOffset + 16 + (i * 2)); + sample->loop.states.push_back(state); + } + } + + sample->book.order = BitConverter::ToInt32BE(audioBank, bookOffset + 0); + sample->book.npredictors = BitConverter::ToInt32BE(audioBank, bookOffset + 4); + + for (int i = 0; i < sample->book.npredictors * sample->book.order * 8; i++) + { + sample->book.books.push_back( + BitConverter::ToInt16BE(audioBank, bookOffset + 8 + (i * 2))); + } + + samples[sampleOffset] = sample; + + return sample; + } + else + { + return samples[sampleOffset]; + } +} + +std::vector<AudioTableEntry> ZAudio::ParseAudioTable(std::vector<uint8_t> codeData, int baseOffset) +{ + std::vector<AudioTableEntry> entries; + + int numEntries = BitConverter::ToInt16BE(codeData, baseOffset + 0); + int romAddr = BitConverter::ToInt16BE(codeData, baseOffset + 4); + + int currentOffset = baseOffset + 16; + + for (int i = 0; i < numEntries; i++) + { + AudioTableEntry entry; + + entry.ptr = BitConverter::ToInt32BE(codeData, currentOffset + 0); + entry.size = BitConverter::ToInt32BE(codeData, currentOffset + 4); + entry.medium = codeData[currentOffset + 8]; + entry.cachePolicy = codeData[currentOffset + 9]; + entry.data1 = BitConverter::ToInt16BE(codeData, currentOffset + 10); + entry.data2 = BitConverter::ToInt16BE(codeData, currentOffset + 12); + entry.data3 = BitConverter::ToInt16BE(codeData, currentOffset + 14); + + entries.push_back(entry); + + currentOffset += 16; + } + + return entries; +} + +void ZAudio::ParseSoundFont(std::vector<uint8_t> codeData, std::vector<uint8_t> audioTable, + std::vector<AudioTableEntry> audioSampleBank, + AudioTableEntry& entry) +{ + int ptr = entry.ptr; + int size = entry.size; + int sampleBankId1 = (entry.data1 >> 8) & 0xFF; + int sampleBankId2 = (entry.data1) & 0xFF; + int numInstruments = (entry.data2 >> 8) & 0xFF; + int numDrums = entry.data2 & 0xFF; + int numSfx = entry.data3; + + int currentOffset = BitConverter::ToInt32BE(codeData, ptr) + ptr; + for (int i = 0; i < numDrums; i++) + { + DrumEntry drum; + + int samplePtr = BitConverter::ToInt32BE(codeData, currentOffset); + + if (samplePtr != 0) + { + samplePtr += ptr; + + drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[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); + } + + entry.drums.push_back(drum); + + currentOffset += 4; + } + + currentOffset = BitConverter::ToInt32BE(codeData, ptr + 4) + ptr; + for (int i = 0; i < numSfx; i++) + { + SoundFontEntry* sfx; + sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + currentOffset, ptr); + entry.soundEffects.push_back(sfx); + + currentOffset += 8; + } + + for (int i = 0; i < numInstruments; i++) + { + InstrumentEntry instrument; + + currentOffset = BitConverter::ToInt32BE(codeData, ptr + 8 + (i * 4)); + + instrument.isValidInstrument = currentOffset != 0; + + if (currentOffset != 0) + { + currentOffset += ptr; + + instrument.loaded = codeData[currentOffset + 0]; + instrument.normalRangeLo = codeData[currentOffset + 1]; + instrument.normalRangeHi = codeData[currentOffset + 2]; + instrument.releaseRate = codeData[currentOffset + 3]; + instrument.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, currentOffset + 4) + ptr, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 8) != 0) + instrument.lowNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 8, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 16) != 0) + instrument.normalNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 16, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 24) != 0 && + instrument.normalRangeHi != 0x7F) + instrument.highNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 24, ptr); + } + + entry.instruments.push_back(instrument); + } +} + +void ZAudio::ParseRawData() +{ + ZResource::ParseRawData(); + + std::vector<uint8_t> codeData; + std::vector<uint8_t> audioTableData; + std::vector<uint8_t> audioBankData; + std::vector<uint8_t> audioSeqData; + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + codeData = Globals::Instance->GetBaseromFile("code"); + else + codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioTableData = Globals::Instance->GetBaseromFile("Audiotable"); + else + audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioBankData = Globals::Instance->GetBaseromFile("Audiobank"); + else + audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioSeqData = Globals::Instance->GetBaseromFile("Audioseq"); + else + audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + + "Audioseq"); + + // TABLE PARSING + //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 + soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); + sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); + sampleBankTable = ParseAudioTable(codeData, gSampleBankTableOffset); + // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + + // SAMPLE/FONT PARSING + for (int i = 0; i < soundFontTable.size(); i++) + { + 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++) + { + int seqDestIdx = i; + + if (sequenceTable[i].size == 0) + seqDestIdx = sequenceTable[i].ptr; + + std::vector<char> seqVec = std::vector<char>(sequenceTable[seqDestIdx].size); + memcpy(seqVec.data(), audioSeqData.data() + sequenceTable[seqDestIdx].ptr, + sequenceTable[seqDestIdx].size); + + sequences.push_back(seqVec); + } +} + +std::string ZAudio::GetSourceTypeName() const +{ + return "u8"; +} + +size_t ZAudio::GetRawDataSize() const +{ + return 1; +} + +ZResourceType ZAudio::GetResourceType() const +{ + return ZResourceType::Audio; +} |
