#pragma once #include #include #include #include #include #include "binarytools/BinaryWriter.h" #include #include #define NONE 0xFFFF #define ALIGN(val, al) (size_t) ((val + (al - 1)) & -al) namespace AIFC { enum MagicValues { FORM = 0x464f524d, AIFC = 0x41494643, COMM = 0x434f4d4d, INST = 0x494e5354, VAPC = 0x56415043, SSND = 0x53534e44, AAPL = 0x4150504c, stoc = 0x73746f63, }; } struct Entry { uint32_t offset; uint32_t length; }; struct AudioBankSound { uint32_t offset; float tuning; bool operator==(const AudioBankSound& other) const { return offset == other.offset && tuning == other.tuning; } }; struct Instrument { bool valid; std::string name; uint32_t offset; uint8_t releaseRate; uint8_t normalRangeLo; uint8_t normalRangeHi; uint32_t envelope; std::optional soundLo; std::optional soundMed; std::optional soundHi; }; struct AdpcmBook { int32_t order{}; int32_t npredictors{}; std::vector table; bool operator==(const AdpcmBook& other) const { return order == other.order && npredictors == other.npredictors && table == other.table; } }; struct Drum { std::string name; uint32_t offset; uint8_t releaseRate; uint8_t pan; uint32_t envelope; AudioBankSound sound; bool operator==(const Drum& other) const { return name == other.name && offset == other.offset && releaseRate == other.releaseRate && pan == other.pan && envelope == other.envelope && sound == other.sound; } }; struct AdpcmLoop { uint32_t start{}; uint32_t end{}; int32_t count{}; uint32_t pad{}; std::optional> state; bool operator==(const AdpcmLoop& other) const { return start == other.start && end == other.end && count == other.count && pad == other.pad && state == other.state; } }; struct AudioBankSample { std::string name; std::vector data; AdpcmBook book; AdpcmLoop loop; std::vector tunings; }; struct SampleBank { std::string name; uint32_t offset; std::vector data; std::map entries; AudioBankSample* AddSample(uint32_t addr, size_t sampleSize, const AdpcmBook& book, const AdpcmLoop& loop); }; struct TBLFile { std::vector banks; std::vector tbls; std::map map; }; struct CTLHeader { uint32_t instruments; uint32_t numDrums; uint32_t shared; }; struct AdsrEnvelope { int16_t delay; int16_t arg; }; struct Envelope { std::string name; std::vector entries; }; struct Bank { std::string name; SampleBank* sampleBank; std::vector insts; std::vector drums; std::vector>> allInsts; std::vector instOffsets; std::map envelopes; std::map samples; void print() const; }; class AudioManager { public: static AudioManager* Instance; void initialize(std::vector& buffer, YAML::Node& data); void bind_sample(YAML::Node& node, const std::string& path); void create_aifc(int32_t index, LUS::BinaryWriter& writer); std::string& get_sample(uint32_t id); AudioBankSample get_aifc(int32_t index); std::map get_banks(); uint32_t get_index(AudioBankSample* bank); private: std::map banks; std::map sampleMap; TBLFile loaded_tbl; static std::vector parse_seq_file(std::vector& buffer, uint32_t offset, bool isCTL); static CTLHeader parse_ctl_header(std::vector& data); static std::optional parse_sound(std::vector data); static Drum parse_drum(std::vector& data, uint32_t addr); static Instrument parse_inst(std::vector& data, uint32_t addr); static AdpcmLoop parse_loop(uint32_t addr, std::vector& bankData); static AdpcmBook parse_book(uint32_t addr, std::vector& bankData); static AudioBankSample* parse_sample(std::vector& data, std::vector& bankData, SampleBank* sampleBank); static std::vector parse_envelope(uint32_t addr, std::vector& dataBank); static Bank parse_ctl(CTLHeader header, std::vector data, SampleBank* bank, uint32_t index); static TBLFile parse_tbl(std::vector& data, std::vector& entries); static void write_aifc(AudioBankSample* entry, LUS::BinaryWriter& writer); };