ADL&OPL: Added a fallback for a blank instruments in GS/XG banks

This commit is contained in:
Vitaly Novichkov 2018-03-27 03:21:32 +03:00
parent 7296f8c018
commit 934441f9a2
4 changed files with 78 additions and 35 deletions

View file

@ -103,7 +103,8 @@ enum WOPL_InstrumentFlags
{ {
WOPL_Flags_NONE = 0, WOPL_Flags_NONE = 0,
WOPL_Flag_Enable4OP = 0x01, WOPL_Flag_Enable4OP = 0x01,
WOPL_Flag_Pseudo4OP = 0x02 WOPL_Flag_Pseudo4OP = 0x02,
WOPL_Flag_NoSound = 0x04,
}; };
struct WOPL_Inst struct WOPL_Inst
@ -151,6 +152,7 @@ static bool readInstrument(MIDIplay::fileReader &file, WOPL_Inst &ins, uint16_t
uint8_t flags = idata[39]; uint8_t flags = idata[39];
ins.adlins.flags = (flags & WOPL_Flag_Enable4OP) && (flags & WOPL_Flag_Pseudo4OP) ? adlinsdata::Flag_Pseudo4op : 0; ins.adlins.flags = (flags & WOPL_Flag_Enable4OP) && (flags & WOPL_Flag_Pseudo4OP) ? adlinsdata::Flag_Pseudo4op : 0;
ins.adlins.flags|= (flags & WOPL_Flag_NoSound) ? adlinsdata::Flag_NoSound : 0;
ins.fourOps = (flags & WOPL_Flag_Enable4OP) || (flags & WOPL_Flag_Pseudo4OP); ins.fourOps = (flags & WOPL_Flag_Enable4OP) || (flags & WOPL_Flag_Pseudo4OP);
ins.op[0].feedconn = (idata[40]); ins.op[0].feedconn = (idata[40]);

View file

@ -319,7 +319,7 @@ bool MIDIplay::buildTrackData()
evtPos.delay = ReadVarLenEx(&trackPtr, end, ok); evtPos.delay = ReadVarLenEx(&trackPtr, end, ok);
if(!ok) if(!ok)
{ {
int len = std::sprintf(error, "buildTrackData: Can't read variable-length value at begin of track %d.\n", (int)tk); int len = std::snprintf(error, 150, "buildTrackData: Can't read variable-length value at begin of track %d.\n", (int)tk);
if((len > 0) && (len < 150)) if((len > 0) && (len < 150))
errorString += std::string(error, (size_t)len); errorString += std::string(error, (size_t)len);
return false; return false;
@ -347,7 +347,7 @@ bool MIDIplay::buildTrackData()
event = parseEvent(&trackPtr, end, status); event = parseEvent(&trackPtr, end, status);
if(!event.isValid) if(!event.isValid)
{ {
int len = std::sprintf(error, "buildTrackData: Fail to parse event in the track %d.\n", (int)tk); int len = std::snprintf(error, 150, "buildTrackData: Fail to parse event in the track %d.\n", (int)tk);
if((len > 0) && (len < 150)) if((len > 0) && (len < 150))
errorString += std::string(error, (size_t)len); errorString += std::string(error, (size_t)len);
return false; return false;
@ -1031,7 +1031,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
{ {
if(!caugh_missing_banks_melodic.count(bank)) if(!caugh_missing_banks_melodic.count(bank))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion bank %i (patch %i)", channel, bank, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion MIDI bank %i (patch %i)", channel, bank, midiins);
caugh_missing_banks_melodic.insert(bank); caugh_missing_banks_melodic.insert(bank);
} }
} }
@ -1046,7 +1046,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
{ {
if(!caugh_missing_banks_percussion.count(bank)) if(!caugh_missing_banks_percussion.count(bank))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic bank %i (patch %i)", channel, bank, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic MIDI bank %i (patch %i)", channel, bank, midiins);
caugh_missing_banks_percussion.insert(bank); caugh_missing_banks_percussion.insert(bank);
} }
} }
@ -1060,29 +1060,48 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(midiins == 48 || midiins == 50) vol /= 4; // HACK if(midiins == 48 || midiins == 50) vol /= 4; // HACK
*/ */
//if(midiins == 56) vol = vol*6/10; // HACK //if(midiins == 56) vol = vol*6/10; // HACK
//int meta = banks[opl.AdlBank][midiins]; //int meta = banks[opl.AdlBank][midiins];
const size_t meta = opl.GetAdlMetaNumber(midiins);
const adlinsdata &ains = opl.GetAdlMetaIns(meta); size_t meta = opl.GetAdlMetaNumber(midiins);
const adlinsdata *ains = &opl.GetAdlMetaIns(meta);
int16_t tone = note; int16_t tone = note;
if(ains.tone) if(!isPercussion && !isXgPercussion && (bank > 0)) // For non-zero banks
{
if(ains->flags & adlinsdata::Flag_NoSound)
{
if(hooks.onDebugMessage)
{
if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)))
{
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caugh a blank instrument %i (offset %i) in the MIDI bank %u", channel, Ch[channel].patch, midiins, bank);
caugh_missing_instruments.insert(static_cast<uint8_t>(midiins));
}
}
bank = 0;
midiins = Ch[channel].patch;
meta = opl.GetAdlMetaNumber(midiins);
ains = &opl.GetAdlMetaIns(meta);
}
}
if(ains->tone)
{ {
/*if(ains.tone < 20) /*if(ains.tone < 20)
tone += ains.tone; tone += ains.tone;
else*/ else*/
if(ains.tone < 128) if(ains->tone < 128)
tone = ains.tone; tone = ains->tone;
else else
tone -= ains.tone - 128; tone -= ains->tone - 128;
} }
//uint16_t i[2] = { ains.adlno1, ains.adlno2 }; //uint16_t i[2] = { ains.adlno1, ains.adlno2 };
bool pseudo_4op = ains.flags & adlinsdata::Flag_Pseudo4op; bool pseudo_4op = ains->flags & adlinsdata::Flag_Pseudo4op;
MIDIchannel::NoteInfo::Phys voices[2] = MIDIchannel::NoteInfo::Phys voices[2] =
{ {
{ains.adlno1, false}, {ains->adlno1, false},
{ains.adlno2, pseudo_4op} {ains->adlno2, pseudo_4op}
}; };
if((opl.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) if((opl.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF])
@ -1090,7 +1109,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(hooks.onDebugMessage) if(hooks.onDebugMessage)
{ {
if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)) && (ains.flags & adlinsdata::Flag_NoSound)) if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)) && (ains->flags & adlinsdata::Flag_NoSound))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins);
caugh_missing_instruments.insert(static_cast<uint8_t>(midiins)); caugh_missing_instruments.insert(static_cast<uint8_t>(midiins));
@ -2624,12 +2643,12 @@ ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset)
if(ains.tone) if(ains.tone)
{ {
/*if(ains.tone < 20) /*if(ains.tone < 20)
std::sprintf(ToneIndication, "+%-2d", ains.tone); std::snprintf(ToneIndication, 8, "+%-2d", ains.tone);
else*/ else*/
if(ains.tone < 128) if(ains.tone < 128)
std::sprintf(ToneIndication, "=%-2d", ains.tone); std::snprintf(ToneIndication, 8, "=%-2d", ains.tone);
else else
std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); std::snprintf(ToneIndication, 8, "-%-2d", ains.tone - 128);
} }
std::printf("%s%s%s%u\t", std::printf("%s%s%s%u\t",
ToneIndication, ToneIndication,

View file

@ -280,10 +280,14 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr)
size_t off = 37 + op * 7; size_t off = 37 + op * 7;
std::memcpy(data.OPS[op].data, idata + off, 7); std::memcpy(data.OPS[op].data, idata + off, 7);
} }
meta.flags = 0;
if(version >= 2) if(version >= 2)
{ {
meta.ms_sound_kon = toUint16BE(idata + 65); meta.ms_sound_kon = toUint16BE(idata + 65);
meta.ms_sound_koff = toUint16BE(idata + 67); meta.ms_sound_koff = toUint16BE(idata + 67);
if((meta.ms_sound_kon == 0) && (meta.ms_sound_koff == 0))
meta.flags |= opnInstMeta::Flag_NoSound;
} }
else else
{ {
@ -295,7 +299,6 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr)
meta.opnno2 = uint16_t(opn.dynamic_instruments.size()); meta.opnno2 = uint16_t(opn.dynamic_instruments.size());
/* Junk, delete later */ /* Junk, delete later */
meta.flags = 0;
meta.fine_tune = 0.0; meta.fine_tune = 0.0;
/* Junk, delete later */ /* Junk, delete later */

View file

@ -280,7 +280,7 @@ bool OPNMIDIplay::buildTrackData()
evtPos.delay = ReadVarLenEx(&trackPtr, end, ok); evtPos.delay = ReadVarLenEx(&trackPtr, end, ok);
if(!ok) if(!ok)
{ {
int len = std::sprintf(error, "buildTrackData: Can't read variable-length value at begin of track %d.\n", (int)tk); int len = std::snprintf(error, 150, "buildTrackData: Can't read variable-length value at begin of track %d.\n", (int)tk);
if((len > 0) && (len < 150)) if((len > 0) && (len < 150))
errorString += std::string(error, (size_t)len); errorString += std::string(error, (size_t)len);
return false; return false;
@ -308,7 +308,7 @@ bool OPNMIDIplay::buildTrackData()
event = parseEvent(&trackPtr, end, status); event = parseEvent(&trackPtr, end, status);
if(!event.isValid) if(!event.isValid)
{ {
int len = std::sprintf(error, "buildTrackData: Fail to parse event in the track %d.\n", (int)tk); int len = std::snprintf(error, 150, "buildTrackData: Fail to parse event in the track %d.\n", (int)tk);
if((len > 0) && (len < 150)) if((len > 0) && (len < 150))
errorString += std::string(error, (size_t)len); errorString += std::string(error, (size_t)len);
return false; return false;
@ -981,7 +981,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit
{ {
if(!caugh_missing_banks_melodic.count(bank)) if(!caugh_missing_banks_melodic.count(bank))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion bank %i (patch %i)", channel, bank, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion MIDI bank %i (patch %i)", channel, bank, midiins);
caugh_missing_banks_melodic.insert(bank); caugh_missing_banks_melodic.insert(bank);
} }
} }
@ -996,7 +996,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit
{ {
if(!caugh_missing_banks_melodic.count(bank)) if(!caugh_missing_banks_melodic.count(bank))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic bank %i (patch %i)", channel, bank, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic MIDI bank %i (patch %i)", channel, bank, midiins);
caugh_missing_banks_melodic.insert(bank); caugh_missing_banks_melodic.insert(bank);
} }
} }
@ -1011,28 +1011,47 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit
*/ */
//if(midiins == 56) vol = vol*6/10; // HACK //if(midiins == 56) vol = vol*6/10; // HACK
const size_t meta = opn.GetAdlMetaNumber(midiins); size_t meta = opn.GetAdlMetaNumber(midiins);
const opnInstMeta &ains = opn.GetAdlMetaIns(meta); const opnInstMeta *ains = &opn.GetAdlMetaIns(meta);
int16_t tone = note; int16_t tone = note;
if(ains.tone) if(!isPercussion && !isXgPercussion && (bank > 0)) // For non-zero banks
{
if(ains->flags & opnInstMeta::Flag_NoSound)
{
if(hooks.onDebugMessage)
{
if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)))
{
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caugh a blank instrument %i (offset %i) in the MIDI bank %u", channel, Ch[channel].patch, midiins, bank);
caugh_missing_instruments.insert(static_cast<uint8_t>(midiins));
}
}
bank = 0;
midiins = Ch[channel].patch;
meta = opn.GetAdlMetaNumber(midiins);
ains = &opn.GetAdlMetaIns(meta);
}
}
if(ains->tone)
{ {
/*if(ains.tone < 20) /*if(ains.tone < 20)
tone += ains.tone; tone += ains.tone;
else*/ else*/
if(ains.tone < 128) if(ains->tone < 128)
tone = ains.tone; tone = ains->tone;
else else
tone -= ains.tone - 128; tone -= ains->tone - 128;
} }
uint16_t i[2] = { ains.opnno1, ains.opnno2 }; uint16_t i[2] = { ains->opnno1, ains->opnno2 };
//bool pseudo_4op = ains.flags & opnInstMeta::Flag_Pseudo8op; //bool pseudo_4op = ains.flags & opnInstMeta::Flag_Pseudo8op;
//if((opn.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) i[1] = i[0]; //if((opn.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) i[1] = i[0];
if(hooks.onDebugMessage) if(hooks.onDebugMessage)
{ {
if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)) && (ains.flags & opnInstMeta::Flag_NoSound)) if(!caugh_missing_instruments.count(static_cast<uint8_t>(midiins)) && (ains->flags & opnInstMeta::Flag_NoSound))
{ {
hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins); hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins);
caugh_missing_instruments.insert(static_cast<uint8_t>(midiins)); caugh_missing_instruments.insert(static_cast<uint8_t>(midiins));
@ -2548,12 +2567,12 @@ retry_arpeggio:
// if(ains.tone) // if(ains.tone)
// { // {
// /*if(ains.tone < 20) // /*if(ains.tone < 20)
// std::sprintf(ToneIndication, "+%-2d", ains.tone); // std::snprintf(ToneIndication, 8, "+%-2d", ains.tone);
// else*/ // else*/
// if(ains.tone < 128) // if(ains.tone < 128)
// std::sprintf(ToneIndication, "=%-2d", ains.tone); // std::snprintf(ToneIndication, 8, "=%-2d", ains.tone);
// else // else
// std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); // std::snprintf(ToneIndication, 8, "-%-2d", ains.tone - 128);
// } // }
// std::printf("%s%s%s%u\t", // std::printf("%s%s%s%u\t",
// ToneIndication, // ToneIndication,