summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2025-02-03 03:12:20 -0600
committerLywx <kiritodev01@gmail.com>2025-02-03 20:57:27 -0600
commit93199b4c02eca1364359e88fdd700386d6fc8bf0 (patch)
treed6f2d4da97efd2d04276cc2447d5ae1c65dcd812 /src
parent5f0bd6e9f052821ab8d0d8394b9df4467176b6a0 (diff)
We did partial success while loading this
Diffstat (limited to 'src')
-rw-r--r--src/audio/audio_synthesis.c2
-rw-r--r--src/port/Engine.cpp3
-rw-r--r--src/port/resource/importers/audio/SampleFactory.cpp14
-rw-r--r--src/port/resource/importers/audio/SoundFontFactory.cpp212
-rw-r--r--src/port/resource/importers/audio/SoundFontFactory.h15
5 files changed, 240 insertions, 6 deletions
diff --git a/src/audio/audio_synthesis.c b/src/audio/audio_synthesis.c
index f360229a..a9f16173 100644
--- a/src/audio/audio_synthesis.c
+++ b/src/audio/audio_synthesis.c
@@ -1042,7 +1042,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisSta
numSamplesProcessed += numSamplesToLoadAdj;
dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
- if (((synthState->samplePosInt * 2) + (numSamplesToLoadAdj)*SAMPLE_SIZE) < bookSample->size) {
+ if (((synthState->samplePosInt * 2) + (numSamplesToLoadAdj) * SAMPLE_SIZE) < bookSample->size) {
bytesToRead = (numSamplesToLoadAdj) * SAMPLE_SIZE;
} else {
bytesToRead = bookSample->size - (synthState->samplePosInt * 2);
diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp
index aaebe67a..dcedb08d 100644
--- a/src/port/Engine.cpp
+++ b/src/port/Engine.cpp
@@ -244,6 +244,9 @@ GameEngine::GameEngine() {
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinarySoundFontV0>(), RESOURCE_FORMAT_BINARY,
"SoundFont", static_cast<uint32_t>(SF64::ResourceType::SoundFont), 0);
+ loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryXMLSoundFontV0>(), RESOURCE_FORMAT_XML,
+ "SoundFont", static_cast<uint32_t>(SF64::ResourceType::SoundFont), 0);
+
prevAltAssets = CVarGetInteger("gEnhancements.Mods.AlternateAssets", 0);
gEnableGammaBoost = CVarGetInteger("gGraphics.GammaMode", 0) == 0;
context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets);
diff --git a/src/port/resource/importers/audio/SampleFactory.cpp b/src/port/resource/importers/audio/SampleFactory.cpp
index 8289266a..994a9131 100644
--- a/src/port/resource/importers/audio/SampleFactory.cpp
+++ b/src/port/resource/importers/audio/SampleFactory.cpp
@@ -101,12 +101,14 @@ static void Mp3DecoderWorker(std::shared_ptr<Sample> sample, std::shared_ptr<Shi
drmp3 mp3;
drwav_uint64 numFrames;
drmp3_bool32 ret =
- drmp3_init_memory(&mp3, sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size(), nullptr);
+ drmp3_init_memory(&mp3, sampleFile->Buffer->data(), sampleFile->Buffer->size(), nullptr);
numFrames = drmp3_get_pcm_frame_count(&mp3);
drwav_uint64 channels = mp3.channels;
drwav_uint64 sampleRate = mp3.sampleRate;
- sample->mSample.sampleAddr = new uint8_t[numFrames * channels * 2];
+ sample->mSample.tuning = (float)(sampleRate * channels) / 32000.0f;
+ sample->mSample.size = numFrames * channels * 2;
+ sample->mSample.sampleAddr = new uint8_t[sample->mSample.size];
drmp3_read_pcm_frames_s16(&mp3, numFrames, (int16_t*)sample->mSample.sampleAddr);
}
@@ -131,6 +133,7 @@ static void OggDecoderWorker(std::shared_ptr<Sample> sample, std::shared_ptr<Shi
int bitStream = 0;
size_t toRead = numFrames * numChannels * 2;
sample->mSample.sampleAddr = new uint8_t[toRead];
+ sample->mSample.tuning = (float)(sampleRate * numChannels) / 32000.0f;
do {
read = ov_read(&vf, dataBuff, 4096, 0, 2, 1, &bitStream);
memcpy(sample->mSample.sampleAddr + pos, dataBuff, read);
@@ -199,12 +202,13 @@ std::shared_ptr<Ship::IResource> ResourceFactoryXMLSampleV0::ReadResource(std::s
drwav_uint64 numFrames;
drwav_bool32 ret =
- drwav_init_memory(&wav, sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size(), nullptr);
+ drwav_init_memory(&wav, sampleFile->Buffer->data(), sampleFile->Buffer->size(), nullptr);
drwav_get_length_in_pcm_frames(&wav, &numFrames);
- sample->mSample.tuning = (wav.sampleRate * wav.channels) / 32000.0f;
- sample->mSample.sampleAddr = new uint8_t[numFrames * wav.channels * 2];
+ sample->mSample.tuning = (float)(wav.sampleRate * wav.channels) / 32000.0f;
+ sample->mSample.size = numFrames * wav.channels * 2;
+ sample->mSample.sampleAddr = new uint8_t[sample->mSample.size];
drwav_read_pcm_frames_s16(&wav, numFrames, (int16_t*)sample->mSample.sampleAddr);
return sample;
diff --git a/src/port/resource/importers/audio/SoundFontFactory.cpp b/src/port/resource/importers/audio/SoundFontFactory.cpp
index 431f9410..1fda2854 100644
--- a/src/port/resource/importers/audio/SoundFontFactory.cpp
+++ b/src/port/resource/importers/audio/SoundFontFactory.cpp
@@ -1,5 +1,7 @@
#include "SoundFontFactory.h"
#include "../ResourceUtil.h"
+#include "utils/StringHelper.h"
+#include <sf64audio_provisional.h>
#include "port/resource/type/audio/SoundFont.h"
namespace SF64 {
@@ -29,4 +31,214 @@ std::shared_ptr<Ship::IResource> ResourceFactoryBinarySoundFontV0::ReadResource(
return font;
}
+
+int8_t ResourceFactoryXMLSoundFontV0::MediumStrToInt(const char* str) {
+ if (!strcmp("Ram", str)) {
+ return MEDIUM_RAM;
+ } else if (!strcmp("Unk", str)) {
+ return MEDIUM_UNK;
+ } else if (!strcmp("Cart", str)) {
+ return MEDIUM_CART;
+ } else if (!strcmp("Disk", str)) {
+ return MEDIUM_DISK_DRIVE;
+ // 4 is skipped
+ } else {
+ throw std::runtime_error(
+ StringHelper::Sprintf("Bad medium value. Got %s, expected Ram, Unk, Cart, or Disk.", str));
+ }
+}
+
+int8_t ResourceFactoryXMLSoundFontV0::CachePolicyToInt(const char* str) {
+ if (!strcmp("Temporary", str)) {
+ return CACHE_TEMPORARY;
+ } else if (!strcmp("Persistent", str)) {
+ return CACHE_PERSISTENT;
+ } else if (!strcmp("Either", str)) {
+ return CACHE_EITHER;
+ } else if (!strcmp("Permanent", str)) {
+ return CACHE_PERMANENT;
+ } else {
+ throw std::runtime_error(StringHelper::Sprintf(
+ "Bad cache policy value. Got %s, expected Temporary, Persistent, Either, or Permanent.", str));
+ }
+}
+
+void ResourceFactoryXMLSoundFontV0::ParseDrums(SoundFont* soundFont, tinyxml2::XMLElement* element) {
+ element = (tinyxml2::XMLElement*)element->FirstChildElement();
+ // No drums
+ if (element == nullptr) {
+ soundFont->mFont.drums = nullptr;
+ soundFont->mFont.numDrums = 0;
+ return;
+ }
+
+ do {
+ auto drum = new DrumData;
+ std::vector<EnvelopePointData> envelopes;
+ drum->adsrDecayIndex = element->IntAttribute("ReleaseRate");
+ drum->pan = element->IntAttribute("Pan");
+ drum->isRelocated = element->IntAttribute("Loaded");
+ drum->tunedSample.tuning = element->FloatAttribute("Tuning");
+ const char* sampleStr = element->Attribute("SampleRef");
+
+ if (sampleStr != nullptr && sampleStr[0] != 0) {
+ auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr);
+ drum->tunedSample.sample = static_cast<SampleData*>(res ? res->GetRawPointer() : nullptr);
+ } else {
+ drum->tunedSample.sample = nullptr;
+ }
+
+ element = (tinyxml2::XMLElement*)element->FirstChildElement();
+ if (!strcmp(element->Name(), "Envelopes")) {
+ // element = (tinyxml2::XMLElement*)element->FirstChildElement();
+ unsigned int envCount = 0;
+ envelopes = ParseEnvelopes(soundFont, element, &envCount);
+ element = (tinyxml2::XMLElement*)element->Parent();
+ drum->envelope = new EnvelopePointData[envelopes.size()];
+ memcpy(drum->envelope, envelopes.data(), envelopes.size() * sizeof(EnvelopePointData));
+ } else {
+ drum->envelope = nullptr;
+ }
+
+ if (drum->tunedSample.sample == nullptr) {
+ soundFont->mDrums.push_back(nullptr);
+ } else {
+ soundFont->mDrums.push_back(drum);
+ }
+
+ element = element->NextSiblingElement();
+ } while (element != nullptr);
+
+ soundFont->mFont.numDrums = soundFont->mDrums.size();
+ soundFont->mFont.drums = soundFont->mDrums.data();
+}
+
+void ResourceFactoryXMLSoundFontV0::ParseInstruments(SoundFont* soundFont, tinyxml2::XMLElement* element) {
+ element = element->FirstChildElement();
+ do {
+ auto instrument = new InstrumentData;
+ unsigned int envCount = 0;
+ std::vector<EnvelopePointData> envelopes;
+
+ int isValid = element->BoolAttribute("IsValid");
+ instrument->isRelocated = element->IntAttribute("Loaded");
+ instrument->normalRangeLo = element->IntAttribute("NormalRangeLo");
+ instrument->normalRangeHi = element->IntAttribute("NormalRangeHi");
+ instrument->adsrDecayIndex = element->IntAttribute("ReleaseRate");
+ tinyxml2::XMLElement* instrumentElement = element->FirstChildElement();
+ tinyxml2::XMLElement* instrumentElementCopy = instrumentElement;
+
+ if (instrumentElement != nullptr && !strcmp(instrumentElement->Name(), "Envelopes")) {
+ envelopes = ParseEnvelopes(soundFont, instrumentElement, &envCount);
+ instrument->envelope = new EnvelopePointData[envelopes.size()];
+ memcpy(instrument->envelope, envelopes.data(), envelopes.size() * sizeof(EnvelopePointData));
+ instrumentElement = instrumentElement->NextSiblingElement();
+ }
+
+ if (instrumentElement != nullptr && !strcmp("LowNotesSound", instrumentElement->Name())) {
+ instrument->lowPitchTunedSample.tuning = instrumentElement->FloatAttribute("Tuning");
+ const char* sampleStr = instrumentElement->Attribute("SampleRef");
+ if (sampleStr != nullptr && sampleStr[0] != 0) {
+ auto res = static_pointer_cast<Sample>(
+ Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr, true));
+ auto sample = static_cast<SampleData*>(res ? res->GetRawPointer() : nullptr);
+ instrument->lowPitchTunedSample.sample = sample;
+ if (sample != nullptr && sample->tuning != 0.0f) {
+ instrument->lowPitchTunedSample.tuning = sample->tuning;
+ }
+ }
+ instrumentElement = instrumentElement->NextSiblingElement();
+ }
+
+ if (instrumentElement != nullptr && !strcmp("NormalNotesSound", instrumentElement->Name())) {
+ instrument->normalPitchTunedSample.tuning = instrumentElement->FloatAttribute("Tuning");
+ const char* sampleStr = instrumentElement->Attribute("SampleRef");
+ if (sampleStr != nullptr && sampleStr[0] != 0) {
+ auto res = static_pointer_cast<Sample>(
+ Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr, true));
+ auto sample = static_cast<SampleData*>(res ? res->GetRawPointer() : nullptr);
+ instrument->normalPitchTunedSample.sample = sample;
+ if (sample != nullptr && sample->tuning != 0.0f) {
+ instrument->normalPitchTunedSample.tuning = sample->tuning;
+ }
+ }
+ instrumentElement = instrumentElement->NextSiblingElement();
+ }
+
+ if (instrumentElement != nullptr && !strcmp("HighNotesSound", instrumentElement->Name())) {
+ instrument->highPitchTunedSample.tuning = instrumentElement->FloatAttribute("Tuning");
+ const char* sampleStr = instrumentElement->Attribute("SampleRef");
+ if (sampleStr != nullptr && sampleStr[0] != 0) {
+ auto res = static_pointer_cast<Sample>(
+ Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr, true));
+ auto sample = static_cast<SampleData*>(res ? res->GetRawPointer() : nullptr);
+ instrument->highPitchTunedSample.sample = sample;
+ if (sample != nullptr && sample->tuning != 0.0f) {
+ instrument->highPitchTunedSample.tuning = sample->tuning;
+ }
+ }
+ instrumentElement = instrumentElement->NextSiblingElement();
+ }
+
+ soundFont->mInstruments.push_back(instrument);
+
+ element = instrumentElementCopy;
+ element = (tinyxml2::XMLElement*)element->Parent();
+ element = element->NextSiblingElement();
+ } while (element != nullptr);
+
+ soundFont->mFont.instruments = soundFont->mInstruments.data();
+ soundFont->mFont.numInstruments = soundFont->mInstruments.size();
+}
+
+std::vector<EnvelopePointData> ResourceFactoryXMLSoundFontV0::ParseEnvelopes(SoundFont* soundFont,
+ tinyxml2::XMLElement* element,
+ unsigned int* count) {
+ std::vector<EnvelopePointData> envelopes;
+ unsigned int total = 0;
+ element = element->FirstChildElement("Envelope");
+ while (element != nullptr) {
+ EnvelopePointData env = {
+ .delay = (s16)element->IntAttribute("Delay"),
+ .arg = (s16)element->IntAttribute("Arg"),
+ };
+ envelopes.emplace_back(env);
+ element = element->NextSiblingElement("Envelope");
+ total++;
+ }
+ *count = total;
+ return envelopes;
+}
+
+std::shared_ptr<Ship::IResource> ResourceFactoryXMLSoundFontV0::ReadResource(std::shared_ptr<Ship::File> file) {
+ if (!FileHasValidFormatAndReader(file)) {
+ return nullptr;
+ }
+ auto audioSoundFont = std::make_shared<SoundFont>(file->InitData);
+ auto child = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
+ // Header data
+ memset(&audioSoundFont->mFont, 0, sizeof(audioSoundFont->mFont));
+
+ auto shortData1 = child->IntAttribute("Data1");
+ auto shortData2 = child->IntAttribute("Data2");
+
+ audioSoundFont->mFont.numInstruments = (shortData2 >> 8) & 0xFFu;
+ audioSoundFont->mFont.numDrums = shortData2 & 0xFFu;
+ audioSoundFont->mFont.sampleBankId1 = (shortData1 >> 8) & 0xFFu;
+ audioSoundFont->mFont.sampleBankId2 = shortData1 & 0xFFu;
+
+ child = (tinyxml2::XMLElement*)child->FirstChildElement();
+
+ while (child != nullptr) {
+ const char* name = child->Name();
+
+ if (!strcmp(name, "Drums")) {
+ ParseDrums(audioSoundFont.get(), child);
+ } else if (!strcmp(name, "Instruments")) {
+ ParseInstruments(audioSoundFont.get(), child);
+ }
+ child = child->NextSiblingElement();
+ }
+ return audioSoundFont;
+}
} // namespace LUS
diff --git a/src/port/resource/importers/audio/SoundFontFactory.h b/src/port/resource/importers/audio/SoundFontFactory.h
index 04823a55..b5afda9a 100644
--- a/src/port/resource/importers/audio/SoundFontFactory.h
+++ b/src/port/resource/importers/audio/SoundFontFactory.h
@@ -1,11 +1,26 @@
#pragma once
#include "Resource.h"
+#include "ResourceFactoryXML.h"
#include "ResourceFactoryBinary.h"
+#include "port/resource/type/audio/SoundFont.h"
namespace SF64 {
class ResourceFactoryBinarySoundFontV0 : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file) override;
};
+
+class ResourceFactoryXMLSoundFontV0 : public Ship::ResourceFactoryXML {
+ public:
+ std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file) override;
+ static int8_t MediumStrToInt(const char* str);
+ static int8_t CachePolicyToInt(const char* str);
+
+ private:
+ void ParseDrums(SoundFont* soundFont, tinyxml2::XMLElement* element);
+ void ParseInstruments(SoundFont* soundFont, tinyxml2::XMLElement* element);
+ std::vector<EnvelopePointData> ParseEnvelopes(SoundFont* soundFont, tinyxml2::XMLElement* element,
+ unsigned int* count);
+};
}; // namespace LUS