From 38156b9243ecc3fd4820408fb0c18fa04adc2b41 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Tue, 27 Mar 2018 03:21:32 +0300 Subject: [PATCH] ADL&OPL: Added a fallback for a blank instruments in GS/XG banks --- src/sound/adlmidi/adlmidi_load.cpp | 4 +- src/sound/adlmidi/adlmidi_midiplay.cpp | 55 +++++++++++++++++--------- src/sound/opnmidi/opnmidi_load.cpp | 5 ++- src/sound/opnmidi/opnmidi_midiplay.cpp | 49 ++++++++++++++++------- 4 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/sound/adlmidi/adlmidi_load.cpp b/src/sound/adlmidi/adlmidi_load.cpp index 03206bcd69..00a4ce3de7 100644 --- a/src/sound/adlmidi/adlmidi_load.cpp +++ b/src/sound/adlmidi/adlmidi_load.cpp @@ -103,7 +103,8 @@ enum WOPL_InstrumentFlags { WOPL_Flags_NONE = 0, WOPL_Flag_Enable4OP = 0x01, - WOPL_Flag_Pseudo4OP = 0x02 + WOPL_Flag_Pseudo4OP = 0x02, + WOPL_Flag_NoSound = 0x04, }; struct WOPL_Inst @@ -151,6 +152,7 @@ static bool readInstrument(MIDIplay::fileReader &file, WOPL_Inst &ins, uint16_t 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_NoSound) ? adlinsdata::Flag_NoSound : 0; ins.fourOps = (flags & WOPL_Flag_Enable4OP) || (flags & WOPL_Flag_Pseudo4OP); ins.op[0].feedconn = (idata[40]); diff --git a/src/sound/adlmidi/adlmidi_midiplay.cpp b/src/sound/adlmidi/adlmidi_midiplay.cpp index 65e7af5efe..91270abf92 100644 --- a/src/sound/adlmidi/adlmidi_midiplay.cpp +++ b/src/sound/adlmidi/adlmidi_midiplay.cpp @@ -319,7 +319,7 @@ bool MIDIplay::buildTrackData() evtPos.delay = ReadVarLenEx(&trackPtr, end, 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)) errorString += std::string(error, (size_t)len); return false; @@ -347,7 +347,7 @@ bool MIDIplay::buildTrackData() event = parseEvent(&trackPtr, end, status); 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)) errorString += std::string(error, (size_t)len); 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)) { - 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); } } @@ -1046,7 +1046,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { 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); } } @@ -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 == 56) vol = vol*6/10; // HACK - //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; - 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(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(midiins)); + } + } + bank = 0; + midiins = Ch[channel].patch; + meta = opl.GetAdlMetaNumber(midiins); + ains = &opl.GetAdlMetaIns(meta); + } + } + + if(ains->tone) { /*if(ains.tone < 20) tone += ains.tone; else*/ - if(ains.tone < 128) - tone = ains.tone; + if(ains->tone < 128) + tone = ains->tone; else - tone -= ains.tone - 128; + tone -= ains->tone - 128; } //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] = { - {ains.adlno1, false}, - {ains.adlno2, pseudo_4op} + {ains->adlno1, false}, + {ains->adlno2, pseudo_4op} }; 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(!caugh_missing_instruments.count(static_cast(midiins)) && (ains.flags & adlinsdata::Flag_NoSound)) + if(!caugh_missing_instruments.count(static_cast(midiins)) && (ains->flags & adlinsdata::Flag_NoSound)) { hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins); caugh_missing_instruments.insert(static_cast(midiins)); @@ -2624,12 +2643,12 @@ ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) if(ains.tone) { /*if(ains.tone < 20) - std::sprintf(ToneIndication, "+%-2d", ains.tone); + std::snprintf(ToneIndication, 8, "+%-2d", ains.tone); else*/ if(ains.tone < 128) - std::sprintf(ToneIndication, "=%-2d", ains.tone); + std::snprintf(ToneIndication, 8, "=%-2d", ains.tone); else - std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); + std::snprintf(ToneIndication, 8, "-%-2d", ains.tone - 128); } std::printf("%s%s%s%u\t", ToneIndication, diff --git a/src/sound/opnmidi/opnmidi_load.cpp b/src/sound/opnmidi/opnmidi_load.cpp index 8e87cabc86..15d0a5d355 100644 --- a/src/sound/opnmidi/opnmidi_load.cpp +++ b/src/sound/opnmidi/opnmidi_load.cpp @@ -280,10 +280,14 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) size_t off = 37 + op * 7; std::memcpy(data.OPS[op].data, idata + off, 7); } + + meta.flags = 0; if(version >= 2) { meta.ms_sound_kon = toUint16BE(idata + 65); meta.ms_sound_koff = toUint16BE(idata + 67); + if((meta.ms_sound_kon == 0) && (meta.ms_sound_koff == 0)) + meta.flags |= opnInstMeta::Flag_NoSound; } else { @@ -295,7 +299,6 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) meta.opnno2 = uint16_t(opn.dynamic_instruments.size()); /* Junk, delete later */ - meta.flags = 0; meta.fine_tune = 0.0; /* Junk, delete later */ diff --git a/src/sound/opnmidi/opnmidi_midiplay.cpp b/src/sound/opnmidi/opnmidi_midiplay.cpp index 630df1c77a..58c4c350a4 100644 --- a/src/sound/opnmidi/opnmidi_midiplay.cpp +++ b/src/sound/opnmidi/opnmidi_midiplay.cpp @@ -280,7 +280,7 @@ bool OPNMIDIplay::buildTrackData() evtPos.delay = ReadVarLenEx(&trackPtr, end, 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)) errorString += std::string(error, (size_t)len); return false; @@ -308,7 +308,7 @@ bool OPNMIDIplay::buildTrackData() event = parseEvent(&trackPtr, end, status); 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)) errorString += std::string(error, (size_t)len); 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)) { - 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); } } @@ -996,7 +996,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit { 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); } } @@ -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 - const size_t meta = opn.GetAdlMetaNumber(midiins); - const opnInstMeta &ains = opn.GetAdlMetaIns(meta); + size_t meta = opn.GetAdlMetaNumber(midiins); + const opnInstMeta *ains = &opn.GetAdlMetaIns(meta); 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(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(midiins)); + } + } + bank = 0; + midiins = Ch[channel].patch; + meta = opn.GetAdlMetaNumber(midiins); + ains = &opn.GetAdlMetaIns(meta); + } + } + + if(ains->tone) { /*if(ains.tone < 20) tone += ains.tone; else*/ - if(ains.tone < 128) - tone = ains.tone; + if(ains->tone < 128) + tone = ains->tone; 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; //if((opn.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) i[1] = i[0]; if(hooks.onDebugMessage) { - if(!caugh_missing_instruments.count(static_cast(midiins)) && (ains.flags & opnInstMeta::Flag_NoSound)) + if(!caugh_missing_instruments.count(static_cast(midiins)) && (ains->flags & opnInstMeta::Flag_NoSound)) { hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins); caugh_missing_instruments.insert(static_cast(midiins)); @@ -2548,12 +2567,12 @@ retry_arpeggio: // if(ains.tone) // { // /*if(ains.tone < 20) -// std::sprintf(ToneIndication, "+%-2d", ains.tone); +// std::snprintf(ToneIndication, 8, "+%-2d", ains.tone); // else*/ // if(ains.tone < 128) -// std::sprintf(ToneIndication, "=%-2d", ains.tone); +// std::snprintf(ToneIndication, 8, "=%-2d", ains.tone); // else -// std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); +// std::snprintf(ToneIndication, 8, "-%-2d", ains.tone - 128); // } // std::printf("%s%s%s%u\t", // ToneIndication,