Skip to content

Commit 51602fe

Browse files
committed
implement support for JaiInit.AAF banks
1 parent 6e6889b commit 51602fe

File tree

3 files changed

+229
-23
lines changed

3 files changed

+229
-23
lines changed

src/main/formats/JaiSeqFormat.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
// JaiSeqFormat
99
// ************
1010

11-
BEGIN_FORMAT(JaiSeq)
12-
USING_SCANNER(JaiSeqScanner)
11+
BEGIN_FORMAT(JaiSeqBMS)
12+
USING_SCANNER(JaiSeqBMSScanner)
13+
END_FORMAT()
14+
15+
BEGIN_FORMAT(JaiSeqAAF)
16+
USING_SCANNER(JaiSeqAAFScanner)
17+
END_FORMAT()
18+
19+
BEGIN_FORMAT(JaiSeqBAA)
20+
USING_SCANNER(JaiSeqBAAScanner)
1321
END_FORMAT()

src/main/formats/JaiSeqScanner.cpp

Lines changed: 187 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#include <string>
1818
#include <stack>
1919

20-
DECLARE_FORMAT(JaiSeq);
20+
DECLARE_FORMAT(JaiSeqBMS);
21+
DECLARE_FORMAT(JaiSeqAAF);
22+
DECLARE_FORMAT(JaiSeqBAA);
2123

2224
/* Names from JASystem::TSeqParser from framework.map in The Wind Waker. */
2325
enum MML {
@@ -95,9 +97,10 @@ class JaiSeqTrack : public SeqTrack {
9597
void SetParam(uint32_t beginOffset, uint8_t param, uint16_t value) {
9698
if (param == MML_PROG)
9799
AddProgramChange(beginOffset, curOffset - beginOffset, value);
98-
else if (param == MML_BANK)
100+
else if (param == MML_BANK) {
101+
AddBankSelectNoItem(value);
99102
AddUnknown(beginOffset, curOffset - beginOffset, L"Bank Select");
100-
else
103+
} else
101104
AddUnknown(beginOffset, curOffset - beginOffset);
102105
}
103106

@@ -399,7 +402,7 @@ class JaiSeqTrack : public SeqTrack {
399402
class JaiSeqSeq : public VGMSeq {
400403
public:
401404
JaiSeqSeq(RawFile *file, uint32_t offset, uint32_t length) :
402-
VGMSeq(JaiSeqFormat::name, file, offset, length) {
405+
VGMSeq(JaiSeqBMSFormat::name, file, offset, length) {
403406
bAllowDiscontinuousTrackData = true;
404407
}
405408

@@ -445,8 +448,6 @@ static bool MatchMagic(RawFile *file, uint32_t offs, const char *magic) {
445448

446449
class JaiSeqSamp : public VGMSamp {
447450
public:
448-
uint8_t unityKey;
449-
450451
JaiSeqSamp(VGMSampColl *sampColl, uint32_t offset, RawFile *waFile_) :
451452
VGMSamp(sampColl, offset, 0x2C, 0, 0), waFile(waFile_) {
452453
Load();
@@ -538,6 +539,7 @@ class JaiSeqSamp : public VGMSamp {
538539
SetNumChannels(1);
539540

540541
/* unknown */
542+
541543
unityKey = GetByte(dwOffset + 0x02);
542544
SetRate(GetShortBE(dwOffset + 0x05) / 2);
543545
/* unknown */
@@ -567,7 +569,7 @@ class JaiSeqSampCollWSYS : public VGMSampColl {
567569
public:
568570
JaiSeqSampCollWSYS(RawFile *file, uint32_t offset, uint32_t length,
569571
std::wstring name = L"WSYS Sample Collection")
570-
: VGMSampColl(JaiSeqFormat::name, file, offset, length, name) {}
572+
: VGMSampColl(JaiSeqAAFFormat::name, file, offset, length, name) {}
571573
private:
572574

573575
virtual bool GetSampleInfo() override {
@@ -677,7 +679,6 @@ class JaiSeqInstrBNK : public VGMInstr {
677679
uint32_t numSamples = GetWordBE(regionTableIdx);
678680
uint32_t sampleNum;
679681
VGMRgn *rgn;
680-
JaiSeqSamp *samp;
681682

682683
regionTableIdx += 0x04;
683684
if (numSamples == 0x00)
@@ -693,8 +694,6 @@ class JaiSeqInstrBNK : public VGMInstr {
693694
regionTableIdx += 0x04; /* frequency multiplier */
694695

695696
rgn = AddRgn(regionTableIdx, 0x18, sampleNum, keyLow, keyHigh);
696-
samp = (JaiSeqSamp *)parInstrSet->sampColl->samples[sampleNum];
697-
rgn->SetUnityKey(samp->unityKey);
698697

699698
/* Fake ADSR for now. */
700699
rgn->attack_time = ((double)attack) / 0x3FFF;
@@ -743,7 +742,7 @@ class JaiSeqInstrSetBNK : public VGMInstrSet {
743742
uint32_t offset,
744743
uint32_t length,
745744
VGMSampColl *sampColl,
746-
std::wstring name = L"JaiSeq Instrument Bank") : VGMInstrSet(JaiSeqFormat::name, file, offset, length, name, sampColl) {}
745+
std::wstring name = L"JaiSeq Instrument Bank") : VGMInstrSet(JaiSeqBAAFormat::name, file, offset, length, name, sampColl) {}
747746

748747
private:
749748

@@ -861,7 +860,182 @@ static bool LoadBAA(RawFile *file) {
861860
return true;
862861
}
863862

864-
void JaiSeqScanner::Scan(RawFile *file, void *info) {
863+
static double FrequencyRatioToCents(double freqRatio) {
864+
return round(1000000 * 1200 * log2(freqRatio)) / 1000000.0;
865+
}
866+
867+
class JaiSeqInstrAAF : public VGMInstr {
868+
public:
869+
JaiSeqInstrAAF(VGMInstrSet *instrSet, uint32_t offset, uint32_t length, uint32_t theInstrNum, uint32_t theBank = 0)
870+
: VGMInstr(instrSet, offset, length, theBank, theInstrNum) {}
871+
872+
private:
873+
virtual bool LoadInstr() override {
874+
if (!MatchMagic(vgmfile->rawfile, dwOffset, "INST"))
875+
return false;
876+
877+
uint32_t keyRgnCount = GetWordBE(dwOffset + 0x28);
878+
uint32_t keyRgnIdx = dwOffset + 0x2C;
879+
uint8_t keyLow = 0;
880+
for (uint32_t i = 0; i < keyRgnCount; i++) {
881+
uint32_t keyRgnBase = parInstrSet->dwOffset + GetWordBE(keyRgnIdx);
882+
keyRgnIdx += 0x04;
883+
884+
uint8_t keyHigh = GetByte(keyRgnBase);
885+
886+
uint32_t velRgnCount = GetWordBE(keyRgnBase + 0x04);
887+
uint32_t velRgnIdx = keyRgnBase + 0x08;
888+
uint8_t velLow = 0;
889+
for (uint32_t j = 0; j < velRgnCount; j++) {
890+
uint32_t velRgnBase = parInstrSet->dwOffset + GetWordBE(velRgnIdx);
891+
uint8_t velHigh = GetByte(velRgnBase);
892+
893+
/* 0x04 is some sort of bank identifier? Doesn't seem to match the WSYS ID... */
894+
uint32_t sampleNum = GetShortBE(velRgnBase + 0x06);
895+
/* 0x08 = unknown float */
896+
uint32_t freqMultBits = GetWordBE(velRgnBase + 0x0C);
897+
float freqMult = *((float *) &freqMultBits);
898+
899+
VGMRgn *rgn = AddRgn(keyRgnBase, 0, sampleNum, keyLow, keyHigh, velLow, velHigh);
900+
rgn->SetFineTune(FrequencyRatioToCents(freqMult));
901+
velLow = velHigh + 1;
902+
velRgnIdx += 0x04;
903+
}
904+
905+
keyLow = keyHigh + 1;
906+
}
907+
}
908+
};
909+
910+
class JaiSeqInstrSetAAF : public VGMInstrSet {
911+
public:
912+
uint32_t wsysId;
913+
uint32_t bnkId;
914+
915+
JaiSeqInstrSetAAF(RawFile *file,
916+
uint32_t offset,
917+
uint32_t length,
918+
uint32_t wsysId_,
919+
VGMSampColl *sampColl = nullptr,
920+
std::wstring name = L"JaiSeq AAF Instrument Bank") :
921+
VGMInstrSet(JaiSeqAAFFormat::name, file, offset, length, name, sampColl), wsysId(wsysId_) {}
922+
923+
private:
924+
virtual bool GetInstrPointers() override {
925+
if (!MatchMagic(rawfile, dwOffset, "IBNK"))
926+
return false;
927+
928+
unLength = GetWordBE(dwOffset + 0x04);
929+
bnkId = GetWordBE(dwOffset + 0x08);
930+
931+
wchar_t buf[64] = {};
932+
swprintf(buf, sizeof(buf) / sizeof(*buf), L"Bank_%04x", bnkId);
933+
name = buf;
934+
935+
uint32_t bankOffs = dwOffset + 0x20;
936+
if (!MatchMagic(rawfile, bankOffs, "BANK"))
937+
return false;
938+
939+
uint32_t listIdx = bankOffs + 0x04;
940+
uint32_t instrNum = 0;
941+
while (true) {
942+
uint32_t instrOffs = GetWordBE(listIdx);
943+
if (instrOffs == 0x00)
944+
break;
945+
uint32_t instrBase = dwOffset + instrOffs;
946+
aInstrs.push_back(new JaiSeqInstrAAF(this, instrBase, 0, instrNum++));
947+
listIdx += 0x04;
948+
}
949+
950+
return true;
951+
}
952+
953+
};
954+
955+
/* Handle the AAF (Audio Archive File?) format from Wind Waker. */
956+
static bool LoadAAF(RawFile *file) {
957+
uint32_t offset = 0x00;
958+
959+
std::vector<VGMSampColl *> wsys;
960+
std::map<uint32_t, VGMInstrSet *> bnk;
961+
962+
while (true) {
963+
uint32_t chunkType = file->GetWordBE(offset);
964+
offset += 0x04;
965+
966+
switch (chunkType) {
967+
case 0x00:
968+
/* End of archive. */
969+
goto end;
970+
case 0x01:
971+
case 0x05:
972+
case 0x06:
973+
case 0x07:
974+
while (true) {
975+
uint32_t start = file->GetWordBE(offset);
976+
offset += 0x04;
977+
if (start == 0x00)
978+
break;
979+
offset += 0x04; /* size */
980+
}
981+
break;
982+
case 0x02: {
983+
/* bnk */
984+
while (true) {
985+
uint32_t start = file->GetWordBE(offset);
986+
offset += 0x04;
987+
if (start == 0x00)
988+
break;
989+
offset += 0x04; /* size */
990+
uint32_t wsysId = file->GetWordBE(offset);
991+
offset += 0x04;
992+
JaiSeqInstrSetAAF *instrSet = new JaiSeqInstrSetAAF(file, start, 0, wsysId);
993+
instrSet->LoadVGMFile();
994+
bnk[instrSet->bnkId] = instrSet;
995+
}
996+
break;
997+
}
998+
case 0x03: {
999+
/* wsys */
1000+
while (true) {
1001+
uint32_t start = file->GetWordBE(offset);
1002+
offset += 0x04;
1003+
if (start == 0x00)
1004+
break;
1005+
offset += 0x04; /* size */
1006+
offset += 0x04; /* flag */
1007+
JaiSeqSampCollWSYS *sampColl = new JaiSeqSampCollWSYS(file, start, 0);
1008+
sampColl->LoadVGMFile();
1009+
wsys.push_back(sampColl);
1010+
}
1011+
break;
1012+
}
1013+
}
1014+
}
1015+
1016+
end:
1017+
1018+
for (auto const &pair : bnk) {
1019+
VGMInstrSet *instrSet = pair.second;
1020+
1021+
VGMSampColl *sampColl = wsys[((JaiSeqInstrSetAAF *)instrSet)->wsysId];
1022+
VGMColl *coll = new VGMColl(*instrSet->GetName());
1023+
coll->AddInstrSet(instrSet);
1024+
coll->AddSampColl(sampColl);
1025+
coll->Load();
1026+
}
1027+
1028+
return true;
1029+
}
1030+
1031+
void JaiSeqBMSScanner::Scan(RawFile *file, void *info) {
8651032
JaiSeqSeq *seq = new JaiSeqSeq(file, 0, 0); seq->Load();
866-
// LoadBAA(file);
8671033
}
1034+
1035+
void JaiSeqAAFScanner::Scan(RawFile *file, void *info) {
1036+
LoadAAF(file);
1037+
}
1038+
1039+
void JaiSeqBAAScanner::Scan(RawFile *file, void *info) {
1040+
LoadBAA(file);
1041+
}

src/main/formats/JaiSeqScanner.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
11
#pragma once
22
#include "Scanner.h"
33

4-
class JaiSeqScanner :
5-
public VGMScanner {
4+
class JaiSeqBMSScanner :
5+
public VGMScanner {
66
public:
7-
JaiSeqScanner(void) {
8-
USE_EXTENSION(L"bms")
9-
}
10-
virtual ~JaiSeqScanner(void) {
11-
}
7+
JaiSeqBMSScanner(void) {
8+
USE_EXTENSION(L"bms")
9+
}
10+
virtual ~JaiSeqBMSScanner(void) {
11+
}
1212

13-
virtual void Scan(RawFile *file, void *info = 0);
13+
virtual void Scan(RawFile *file, void *info = 0);
14+
};
15+
16+
class JaiSeqAAFScanner :
17+
public VGMScanner {
18+
public:
19+
JaiSeqAAFScanner(void) {
20+
USE_EXTENSION(L"aaf")
21+
}
22+
virtual ~JaiSeqAAFScanner(void) {
23+
}
24+
25+
virtual void Scan(RawFile *file, void *info = 0);
26+
};
27+
28+
class JaiSeqBAAScanner :
29+
public VGMScanner {
30+
public:
31+
JaiSeqBAAScanner(void) {
32+
USE_EXTENSION(L"baa")
33+
}
34+
virtual ~JaiSeqBAAScanner(void) {
35+
}
36+
37+
virtual void Scan(RawFile *file, void *info = 0);
1438
};

0 commit comments

Comments
 (0)