#include "2s2h/resource/importer/AudioSoundFontFactory.h" #include "2s2h/resource/type/AudioSoundFont.h" #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" namespace SOH { std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto audioSoundFont = std::make_shared(file->InitData); auto reader = std::get>(file->Reader); audioSoundFont->soundFont.fntIndex = reader->ReadInt32(); audioSoundFont->medium = reader->ReadInt8(); audioSoundFont->cachePolicy = reader->ReadInt8(); audioSoundFont->data1 = reader->ReadUInt16(); audioSoundFont->soundFont.sampleBankId1 = audioSoundFont->data1 >> 8; audioSoundFont->soundFont.sampleBankId2 = audioSoundFont->data1 & 0xFF; audioSoundFont->data2 = reader->ReadUInt16(); audioSoundFont->data3 = reader->ReadUInt16(); uint32_t drumCount = reader->ReadUInt32(); audioSoundFont->soundFont.numDrums = drumCount; uint32_t instrumentCount = reader->ReadUInt32(); audioSoundFont->soundFont.numInstruments = instrumentCount; uint32_t soundEffectCount = reader->ReadUInt32(); audioSoundFont->soundFont.numSfx = soundEffectCount; // πŸ₯ DRUMS πŸ₯ audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums); audioSoundFont->drumAddresses.reserve(audioSoundFont->soundFont.numDrums); for (uint32_t i = 0; i < audioSoundFont->soundFont.numDrums; i++) { Drum drum; drum.releaseRate = reader->ReadUByte(); drum.pan = reader->ReadUByte(); drum.loaded = reader->ReadUByte(); drum.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont uint32_t envelopeCount = reader->ReadUInt32(); audioSoundFont->drumEnvelopeCounts.push_back(envelopeCount); std::vector drumEnvelopes; drumEnvelopes.reserve(audioSoundFont->drumEnvelopeCounts[i]); for (uint32_t j = 0; j < audioSoundFont->drumEnvelopeCounts.back(); j++) { AdsrEnvelope env; int16_t delay = reader->ReadInt16(); int16_t arg = reader->ReadInt16(); env.delay = BE16SWAP(delay); env.arg = BE16SWAP(arg); drumEnvelopes.push_back(env); } audioSoundFont->drumEnvelopeArrays.push_back(drumEnvelopes); drum.envelope = audioSoundFont->drumEnvelopeArrays.back().data(); bool hasSample = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); drum.sound.tuning = reader->ReadFloat(); if (sampleFileName.empty()) { drum.sound.sample = nullptr; } else { auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); drum.sound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } audioSoundFont->drums.push_back(drum); // BENTODO clean this up in V3. if (drum.sound.sample == nullptr) { audioSoundFont->drumAddresses.push_back(nullptr); } else { audioSoundFont->drumAddresses.push_back(&audioSoundFont->drums.back()); } } audioSoundFont->soundFont.drums = audioSoundFont->drumAddresses.data(); // 🎺🎻🎷🎸🎹 INSTRUMENTS 🎹🎸🎷🎻🎺 audioSoundFont->instruments.reserve(audioSoundFont->soundFont.numInstruments); for (uint32_t i = 0; i < audioSoundFont->soundFont.numInstruments; i++) { Instrument instrument; uint8_t isValidEntry = reader->ReadUByte(); instrument.loaded = reader->ReadUByte(); instrument.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont instrument.normalRangeLo = reader->ReadUByte(); instrument.normalRangeHi = reader->ReadUByte(); instrument.releaseRate = reader->ReadUByte(); uint32_t envelopeCount = reader->ReadInt32(); audioSoundFont->instrumentEnvelopeCounts.push_back(envelopeCount); std::vector instrumentEnvelopes; for (uint32_t j = 0; j < audioSoundFont->instrumentEnvelopeCounts.back(); j++) { AdsrEnvelope env; int16_t delay = reader->ReadInt16(); int16_t arg = reader->ReadInt16(); env.delay = BE16SWAP(delay); env.arg = BE16SWAP(arg); instrumentEnvelopes.push_back(env); } audioSoundFont->instrumentEnvelopeArrays.push_back(instrumentEnvelopes); instrument.envelope = audioSoundFont->instrumentEnvelopeArrays.back().data(); bool hasLowNoteSoundFontEntry = reader->ReadInt8(); if (hasLowNoteSoundFontEntry) { bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.lowNotesSound.tuning = reader->ReadFloat(); auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.lowNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.lowNotesSound.sample = nullptr; instrument.lowNotesSound.tuning = 0; } bool hasNormalNoteSoundFontEntry = reader->ReadInt8(); if (hasNormalNoteSoundFontEntry) { bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.normalNotesSound.tuning = reader->ReadFloat(); auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.normalNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.normalNotesSound.sample = nullptr; instrument.normalNotesSound.tuning = 0; } bool hasHighNoteSoundFontEntry = reader->ReadInt8(); if (hasHighNoteSoundFontEntry) { bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.highNotesSound.tuning = reader->ReadFloat(); auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.highNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.highNotesSound.sample = nullptr; instrument.highNotesSound.tuning = 0; } audioSoundFont->instruments.push_back(instrument); audioSoundFont->instrumentAddresses.push_back(isValidEntry ? &audioSoundFont->instruments.back() : nullptr); } audioSoundFont->soundFont.instruments = audioSoundFont->instrumentAddresses.data(); // πŸ”Š SOUND EFFECTS πŸ”Š audioSoundFont->soundEffects.reserve(audioSoundFont->soundFont.numSfx); for (uint32_t i = 0; i < audioSoundFont->soundFont.numSfx; i++) { SoundFontSound soundEffect; bool hasSFEntry = reader->ReadInt8(); if (hasSFEntry) { bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); soundEffect.tuning = reader->ReadFloat(); auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); soundEffect.sample = static_cast(res ? res->GetRawPointer() : nullptr); } audioSoundFont->soundEffects.push_back(soundEffect); } audioSoundFont->soundFont.soundEffects = audioSoundFont->soundEffects.data(); return audioSoundFont; } } // namespace SOH