mirror of
https://github.com/HarbourMasters/Starship
synced 2026-07-05 21:59:05 -04:00
201 lines
6.2 KiB
C++
201 lines
6.2 KiB
C++
#include "AudioLoader.h"
|
|
#include "utils/binarytools/BinaryReader.h"
|
|
#include "assets/ast_audio.h"
|
|
#include "BitConverter.h"
|
|
#include "port/Engine.h"
|
|
#include <vector>
|
|
#include <fstream>
|
|
#include <filesystem>
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
Ship::BinaryReader Audio_MakeReader(const char* resource, u32 offset = 0){
|
|
auto data = (char*)ResourceGetDataByName(resource);
|
|
auto size = ResourceGetSizeByName(resource);
|
|
|
|
Ship::BinaryReader reader(data, size);
|
|
reader.SetEndianness(Ship::Endianness::Big);
|
|
reader.Seek(offset, Ship::SeekOffsetType::Start);
|
|
|
|
return reader;
|
|
}
|
|
|
|
char* Audio_LoadBlob(const char* resource, u32 offset){
|
|
auto data = (char*)ResourceGetDataByName(resource);
|
|
|
|
return data + offset;
|
|
}
|
|
|
|
EnvelopePoint* Audio_LoadEnvelope(uint32_t addr) {
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
|
|
std::vector<EnvelopePoint> temp;
|
|
while(true) {
|
|
int16_t delay = BSWAP16(reader.ReadInt16());
|
|
int16_t arg = BSWAP16(reader.ReadInt16());
|
|
|
|
temp.push_back({delay, arg});
|
|
|
|
if (1 <= (-delay) % (1 << 16) && (-delay) % (1 << 16) <= 3){
|
|
break;
|
|
}
|
|
}
|
|
|
|
EnvelopePoint* envelopes = memallocn(EnvelopePoint, temp.size());
|
|
memcpy(envelopes, temp.data(), sizeof(EnvelopePoint) * temp.size());
|
|
|
|
return envelopes;
|
|
}
|
|
|
|
extern "C" SoundFont* Audio_LoadFont(AudioTableEntry entry) {
|
|
auto reader = Audio_MakeReader(gAudioBank, entry.romAddr);
|
|
|
|
SoundFont* font = memalloc(SoundFont);
|
|
|
|
font->numInstruments = (entry.shortData2 >> 8) & 0xFFu;
|
|
font->numDrums = entry.shortData2 & 0xFFu;
|
|
font->sampleBankId1 = (entry.shortData1 >> 8) & 0xFFu;
|
|
font->sampleBankId2 = entry.shortData1 & 0xFFu;
|
|
font->instruments = memallocn(Instrument*, font->numInstruments);
|
|
font->drums = memallocn(Drum*, font->numDrums);
|
|
|
|
uint32_t drumBaseAddr = entry.romAddr + reader.ReadUInt32();
|
|
uint32_t instBaseAddr = 4;
|
|
|
|
if(font->drums != nullptr && drumBaseAddr != 0){
|
|
reader.Seek(drumBaseAddr, Ship::SeekOffsetType::Start);
|
|
for(size_t i = 0; i < font->numDrums; i++){
|
|
font->drums[i] = Audio_LoadDrum(entry.romAddr + reader.ReadUInt32(), entry.romAddr, font->sampleBankId1);
|
|
}
|
|
}
|
|
|
|
if(font->instruments != nullptr){
|
|
reader.Seek(instBaseAddr, Ship::SeekOffsetType::Start);
|
|
for(size_t i = 1; i < font->numInstruments; i++){
|
|
font->instruments[i] = Audio_LoadInstrument(reader.ReadUInt32(), font->sampleBankId1);
|
|
}
|
|
}
|
|
|
|
gSampleFontLoadStatus[font->sampleBankId1] = 2;
|
|
|
|
return font;
|
|
}
|
|
|
|
extern "C" AdpcmLoop* Audio_LoadLoop(uint32_t addr) {
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
AdpcmLoop* loop = memalloc(AdpcmLoop);
|
|
|
|
loop->start = reader.ReadInt32();
|
|
loop->end = reader.ReadUInt32();
|
|
loop->count = reader.ReadUInt32();
|
|
|
|
if(loop->count != 0){
|
|
for(size_t i = 0; i < 16; i++){
|
|
loop->predictorState[i] = reader.ReadInt16();
|
|
}
|
|
}
|
|
|
|
return loop;
|
|
}
|
|
|
|
extern "C" AdpcmBook* Audio_LoadBook(uint32_t addr) {
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
|
|
AdpcmBook* book = memalloc(AdpcmBook);
|
|
book->order = reader.ReadInt32();
|
|
book->numPredictors = reader.ReadInt32();
|
|
|
|
size_t length = 8 * book->order * book->numPredictors;
|
|
book->book = memallocn(int16_t, length);
|
|
|
|
if(length > 0x40){
|
|
return nullptr;
|
|
}
|
|
|
|
for(size_t i = 0; i < length; i++){
|
|
book->book[i] = reader.ReadInt16();
|
|
}
|
|
|
|
return book;
|
|
}
|
|
|
|
Sample* Audio_LoadSample(uint32_t sampleAddr, uint32_t baseAddr = 0, uint32_t sampleBankID = 0) {
|
|
auto reader = Audio_MakeReader(gAudioBank, sampleAddr);
|
|
|
|
Sample* sample = memalloc(Sample);
|
|
sample->size = reader.ReadUInt32();
|
|
uint32_t addr = reader.ReadUInt32();
|
|
sample->loop = Audio_LoadLoop(baseAddr + reader.ReadUInt32());
|
|
sample->book = Audio_LoadBook(baseAddr + reader.ReadUInt32());
|
|
|
|
sample->isRelocated = 1;
|
|
sample->sampleAddr = (uint8_t*) Audio_LoadBlob(gAudioTable, gSampleBankTable->entries[sampleBankID].romAddr + addr);
|
|
|
|
std::filesystem::path path{ "dumps/" + std::to_string(sampleAddr) + ".raw" };
|
|
std::ofstream ofs(path);
|
|
ofs.write(reinterpret_cast<const char*>(sample->sampleAddr), sample->size);
|
|
ofs.close();
|
|
|
|
gUsedSamples[gNumUsedSamples++] = sample;
|
|
return sample;
|
|
}
|
|
|
|
TunedSample Audio_LoadTunedSample(uint32_t addr, uint32_t baseAddr = 0, uint32_t sampleBankID = 0) {
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
auto sampleAddr = reader.ReadUInt32();
|
|
auto tuning = reader.ReadFloat();
|
|
|
|
if(sampleAddr == 0){
|
|
assert(tuning == 0.0f);
|
|
return { nullptr, 0.0f };
|
|
}
|
|
|
|
return {
|
|
.sample = Audio_LoadSample(baseAddr + sampleAddr, baseAddr, sampleBankID),
|
|
.tuning = tuning
|
|
};
|
|
}
|
|
|
|
extern "C" Instrument* Audio_LoadInstrument(uint32_t addr, uint32_t sampleBankID) {
|
|
if (addr == 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
|
|
Instrument* instrument = memalloc(Instrument);
|
|
instrument->isRelocated = reader.ReadUByte();
|
|
instrument->normalRangeLo = reader.ReadUByte();
|
|
instrument->normalRangeHi = reader.ReadUByte();
|
|
instrument->adsrDecayIndex = reader.ReadUByte();
|
|
instrument->envelope = Audio_LoadEnvelope(reader.ReadUInt32());
|
|
instrument->lowPitchTunedSample = Audio_LoadTunedSample(addr + 8, 0, sampleBankID);
|
|
instrument->normalPitchTunedSample = Audio_LoadTunedSample(addr + 16, 0, sampleBankID);
|
|
instrument->highPitchTunedSample = Audio_LoadTunedSample(addr + 24, 0, sampleBankID);
|
|
instrument->isRelocated = 1;
|
|
|
|
return instrument;
|
|
}
|
|
|
|
extern "C" Drum* Audio_LoadDrum(uint32_t addr, uint32_t baseAddr, uint32_t sampleBankID) {
|
|
|
|
if(baseAddr != 0 && addr >= baseAddr){
|
|
return nullptr;
|
|
}
|
|
|
|
auto reader = Audio_MakeReader(gAudioBank, addr);
|
|
Drum* drum = memalloc(Drum);
|
|
|
|
drum->adsrDecayIndex = reader.ReadInt8();
|
|
drum->pan = reader.ReadInt8();
|
|
drum->isRelocated = reader.ReadUByte();
|
|
reader.ReadUByte();
|
|
drum->isRelocated = 1;
|
|
|
|
|
|
drum->tunedSample = Audio_LoadTunedSample(addr + 4, baseAddr, sampleBankID);
|
|
reader.Seek(0x8, Ship::SeekOffsetType::Current);
|
|
drum->envelope = Audio_LoadEnvelope(reader.ReadUInt32());
|
|
|
|
return drum;
|
|
} |