mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-16 01:35:07 +00:00
WOPN complete
This commit is contained in:
parent
25abf4c733
commit
f8ffe04869
1 changed files with 40 additions and 23 deletions
|
@ -659,6 +659,7 @@ void DivEngine::loadOPLI(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
String insName = reader.readString(32);
|
String insName = reader.readString(32);
|
||||||
insName = stringNotBlank(insName) ? insName : stripPath;
|
insName = stringNotBlank(insName) ? insName : stripPath;
|
||||||
ins->name = insName;
|
ins->name = insName;
|
||||||
|
// TODO adapt MIDI key offset to transpose?
|
||||||
reader.seek(7, SEEK_CUR); // skip MIDI params
|
reader.seek(7, SEEK_CUR); // skip MIDI params
|
||||||
uint8_t instTypeFlags = reader.readC(); // [0EEEDCBA] - see WOPL/OPLI spec
|
uint8_t instTypeFlags = reader.readC(); // [0EEEDCBA] - see WOPL/OPLI spec
|
||||||
|
|
||||||
|
@ -746,6 +747,7 @@ void DivEngine::loadOPNI(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
if (!(version >= 2) || version > 0xF) {
|
if (!(version >= 2) || version > 0xF) {
|
||||||
// version 1 doesn't have a version field........
|
// version 1 doesn't have a version field........
|
||||||
reader.seek(-2, SEEK_CUR);
|
reader.seek(-2, SEEK_CUR);
|
||||||
|
version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.readC(); // skip isPerc
|
reader.readC(); // skip isPerc
|
||||||
|
@ -754,6 +756,7 @@ void DivEngine::loadOPNI(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
|
|
||||||
String insName = reader.readString(32);
|
String insName = reader.readString(32);
|
||||||
ins->name = stringNotBlank(insName) ? insName : stripPath;
|
ins->name = stringNotBlank(insName) ? insName : stripPath;
|
||||||
|
// TODO adapt MIDI key offset to transpose?
|
||||||
if (!reader.seek(3, SEEK_CUR)) { // skip MIDI params
|
if (!reader.seek(3, SEEK_CUR)) { // skip MIDI params
|
||||||
throw EndOfFileException(&reader, reader.tell() + 3);
|
throw EndOfFileException(&reader, reader.tell() + 3);
|
||||||
}
|
}
|
||||||
|
@ -1398,6 +1401,7 @@ void DivEngine::loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
String insName = reader.readString(32);
|
String insName = reader.readString(32);
|
||||||
insName = stringNotBlank(insName) ? insName : stripPath;
|
insName = stringNotBlank(insName) ? insName : stripPath;
|
||||||
ins->name = insName;
|
ins->name = insName;
|
||||||
|
// TODO adapt MIDI key offset to transpose?
|
||||||
reader.seek(7, SEEK_CUR); // skip MIDI params
|
reader.seek(7, SEEK_CUR); // skip MIDI params
|
||||||
uint8_t instTypeFlags = reader.readC(); // [0EEEDCBA] - see WOPL/OPLI spec
|
uint8_t instTypeFlags = reader.readC(); // [0EEEDCBA] - see WOPL/OPLI spec
|
||||||
|
|
||||||
|
@ -1509,10 +1513,10 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
total += (op.ssgEnv = ssgEg);
|
total += (op.ssgEnv = ssgEg);
|
||||||
return total;
|
return total;
|
||||||
};
|
};
|
||||||
auto doParseWopnInstrument = [&](midibank_t*& metadata, int patchNum) {
|
auto doParseWopnInstrument = [&](bool isPerc, midibank_t*& metadata, int patchNum) {
|
||||||
DivInstrument* ins = new DivInstrument;
|
DivInstrument* ins = new DivInstrument;
|
||||||
try {
|
try {
|
||||||
int patchTotal = 0;
|
long patchTotal = 0;
|
||||||
ins->type = DIV_INS_FM;
|
ins->type = DIV_INS_FM;
|
||||||
ins->fm.ops = 4;
|
ins->fm.ops = 4;
|
||||||
|
|
||||||
|
@ -1520,6 +1524,7 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
String insName = reader.readString(32);
|
String insName = reader.readString(32);
|
||||||
patchTotal += insName.size();
|
patchTotal += insName.size();
|
||||||
|
|
||||||
|
// TODO adapt MIDI key offset to transpose?
|
||||||
if (!reader.seek(3, SEEK_CUR)) { // skip MIDI params
|
if (!reader.seek(3, SEEK_CUR)) { // skip MIDI params
|
||||||
throw EndOfFileException(&reader, reader.tell() + 3);
|
throw EndOfFileException(&reader, reader.tell() + 3);
|
||||||
}
|
}
|
||||||
|
@ -1534,15 +1539,17 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 2) {
|
if (version >= 2) {
|
||||||
patchTotal += reader.readS_BE(); // skip keyon delay
|
reader.readS_BE(); // skip keyon delay
|
||||||
patchTotal += reader.readS_BE(); // skip keyoff delay
|
reader.readS_BE(); // skip keyoff delay
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patchTotal > 0) {
|
if (patchTotal > 0) {
|
||||||
// Write instrument
|
// Write instrument
|
||||||
|
// TODO: OPN2BankEditor hardcodes GM1 Melodic patch names which are not included in the bank file......
|
||||||
ins->name = stringNotBlank(insName)
|
ins->name = stringNotBlank(insName)
|
||||||
? insName
|
? insName
|
||||||
: fmt::sprintf("%s[%d/%d] Patch %d", stripPath, metadata->bankMsb, metadata->bankLsb, patchNum);
|
: fmt::sprintf("%s[%s] %s Patch %d",
|
||||||
|
stripPath, metadata->name, (isPerc) ? "Drum" : "Melodic", patchNum);
|
||||||
ret.push_back(ins);
|
ret.push_back(ins);
|
||||||
++readCount;
|
++readCount;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1565,13 +1572,14 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
if (!(version >= 2) || version > 0xF) {
|
if (!(version >= 2) || version > 0xF) {
|
||||||
// version 1 doesn't have a version field........
|
// version 1 doesn't have a version field........
|
||||||
reader.seek(-2, SEEK_CUR);
|
reader.seek(-2, SEEK_CUR);
|
||||||
|
version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 2) {
|
meloBankCount = reader.readS_BE();
|
||||||
meloBankCount = reader.readS_BE();
|
percBankCount = reader.readS_BE();
|
||||||
percBankCount = reader.readS_BE();
|
reader.readC(); // skip chip-global LFO
|
||||||
reader.readC(); // skip chip-global LFO
|
|
||||||
|
|
||||||
|
if (version >= 2) {
|
||||||
for (int i = 0; i < meloBankCount; ++i) {
|
for (int i = 0; i < meloBankCount; ++i) {
|
||||||
meloMetadata.push_back(new midibank_t);
|
meloMetadata.push_back(new midibank_t);
|
||||||
String bankName = reader.readString(32);
|
String bankName = reader.readString(32);
|
||||||
|
@ -1579,7 +1587,7 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
meloMetadata[i]->bankMsb = reader.readC();
|
meloMetadata[i]->bankMsb = reader.readC();
|
||||||
meloMetadata[i]->name = stringNotBlank(bankName)
|
meloMetadata[i]->name = stringNotBlank(bankName)
|
||||||
? bankName
|
? bankName
|
||||||
: fmt::sprintf("Bank[%d/%d]", meloMetadata[i]->bankMsb, meloMetadata[i]->bankLsb);
|
: fmt::sprintf("%d/%d", meloMetadata[i]->bankMsb, meloMetadata[i]->bankLsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < percBankCount; ++i) {
|
for (int i = 0; i < percBankCount; ++i) {
|
||||||
|
@ -1589,23 +1597,32 @@ void DivEngine::loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, S
|
||||||
percMetadata[i]->bankMsb = reader.readC();
|
percMetadata[i]->bankMsb = reader.readC();
|
||||||
percMetadata[i]->name = stringNotBlank(bankName)
|
percMetadata[i]->name = stringNotBlank(bankName)
|
||||||
? bankName
|
? bankName
|
||||||
: fmt::sprintf("Bank[%d/%d]", percMetadata[i]->bankMsb, percMetadata[i]->bankLsb);
|
: fmt::sprintf("%d/%d", percMetadata[i]->bankMsb, percMetadata[i]->bankLsb);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// TODO do version 1 multibank sets even exist?
|
||||||
|
meloMetadata.push_back(new midibank_t);
|
||||||
|
meloMetadata[0]->bankLsb = 0;
|
||||||
|
meloMetadata[0]->bankMsb = 0;
|
||||||
|
meloMetadata[0]->name = "0/0";
|
||||||
|
percMetadata.push_back(new midibank_t);
|
||||||
|
percMetadata[0]->bankLsb = 0;
|
||||||
|
percMetadata[0]->bankMsb = 0;
|
||||||
|
percMetadata[0]->name = "0/0";
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < meloBankCount; ++i) {
|
for (int i = 0; i < meloBankCount; ++i) {
|
||||||
for (int j = 0; j < 128; ++j) {
|
for (int j = 0; j < 128; ++j) {
|
||||||
doParseWopnInstrument(meloMetadata[i], j);
|
doParseWopnInstrument(false, meloMetadata[i], j);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < percBankCount; ++i) {
|
}
|
||||||
for (int j = 0; j < 128; ++j) {
|
for (int i = 0; i < percBankCount; ++i) {
|
||||||
doParseWopnInstrument(percMetadata[i], j);
|
for (int j = 0; j < 128; ++j) {
|
||||||
}
|
doParseWopnInstrument(true, percMetadata[i], j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (EndOfFileException& e) {
|
||||||
catch (EndOfFileException& e) {
|
|
||||||
lastError = "premature end of file";
|
lastError = "premature end of file";
|
||||||
logE("premature end of file");
|
logE("premature end of file");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue