diff --git a/src/i_midimusic.c b/src/i_midimusic.c index 980839a8..d0eb9655 100644 --- a/src/i_midimusic.c +++ b/src/i_midimusic.c @@ -60,6 +60,7 @@ enum int midi_complevel = COMP_STANDARD; int midi_reset_type = RESET_TYPE_GM; int midi_reset_delay = -1; +boolean midi_ctf = true; static const byte gm_system_on[] = { @@ -86,7 +87,7 @@ static const byte ff_loopEnd[] = 'l', 'o', 'o', 'p', 'E', 'n', 'd' }; -static boolean use_fallback; +static boolean allow_bank_select; static byte channel_volume[MIDI_CHANNELS_PER_TRACK]; static float volume_factor = 0.0f; @@ -212,28 +213,64 @@ static void SendControlChange(byte channel, byte number, byte value) static void SendProgramChange(byte channel, byte program) { - const byte message[] = {MIDI_EVENT_PROGRAM_CHANGE | channel, program}; + byte message[] = {MIDI_EVENT_PROGRAM_CHANGE | channel, program}; + + if (midi_ctf) + { + const midi_fallback_t fallback = MIDI_ProgramFallback(channel, program); + + if (fallback.type == FALLBACK_DRUMS) + { + message[1] = fallback.value; + } + else if (fallback.type == FALLBACK_BANK_MSB) + { + SendControlChange(channel, MIDI_CONTROLLER_BANK_SELECT_MSB, + fallback.value); + } + } + MIDI_SendShortMsg(message, sizeof(message)); } -static void SendProgramChangeCTF(byte channel, byte program, - const midi_fallback_t *fallback) +static void SendBankSelectMSB(byte channel, byte value) { - switch (fallback->type) + if (allow_bank_select) { - case FALLBACK_DRUMS: - SendProgramChange(channel, fallback->value); - break; - - case FALLBACK_BANK_MSB: - SendControlChange(channel, MIDI_CONTROLLER_BANK_SELECT_MSB, - fallback->value); - // Fall through. - - default: - SendProgramChange(channel, program); - break; + if (midi_ctf) + { + MIDI_UpdateBankMSB(channel, value); + } } + else + { + value = 0; + } + + SendControlChange(channel, MIDI_CONTROLLER_BANK_SELECT_MSB, value); +} + +static void SendBankSelectLSB(byte channel, byte value) +{ + if (allow_bank_select) + { + if (midi_ctf) + { + const midi_fallback_t fallback = + MIDI_BankLSBFallback(channel, value); + + if (fallback.type == FALLBACK_BANK_LSB) + { + value = fallback.value; + } + } + } + else + { + value = 0; + } + + SendControlChange(channel, MIDI_CONTROLLER_BANK_SELECT_LSB, value); } // Writes an RPN message set to NULL (0x7F). Prevents accidental data entry. @@ -388,8 +425,10 @@ static void ResetDevice(void) // For notes/sound off called prior to this function. ResetDelayBytes(96); - MIDI_ResetFallback(); - use_fallback = false; + if (midi_ctf) + { + MIDI_ResetFallback(); + } switch (midi_reset_type) { @@ -401,7 +440,6 @@ static void ResetDevice(void) case RESET_TYPE_GS: MIDI_SendLongMsg(gs_reset, sizeof(gs_reset)); ResetDelayBytes(sizeof(gs_reset)); - use_fallback = (midi_complevel != COMP_VANILLA); break; case RESET_TYPE_XG: @@ -454,16 +492,21 @@ static void SendSysExMsg(const midi_event_t *event) switch (event->data.sysex.type) { case MIDI_SYSEX_RESET: - if (use_fallback) + if (midi_ctf) { MIDI_ResetFallback(); - use_fallback = false; } MIDI_SendLongMsg(data, length); ResetVolume(); break; case MIDI_SYSEX_RHYTHM_PART: + if (midi_ctf) + { + MIDI_UpdateDrumMap(event->data.sysex.channel, data[8]); + } + // Fall through. + case MIDI_SYSEX_OTHER: MIDI_SendLongMsg(data, length); break; @@ -507,8 +550,7 @@ static void CheckFFLoop(const midi_event_t *event) } } -static void SendEMIDI(const midi_event_t *event, midi_track_t *track, - const midi_fallback_t *fallback) +static void SendEMIDI(const midi_event_t *event, midi_track_t *track) { unsigned int i; unsigned int flag; @@ -560,8 +602,8 @@ static void SendEMIDI(const midi_event_t *event, midi_track_t *track, if (track->emidi_program || track->elapsed_time < ticks_per_beat) { track->emidi_program = true; - SendProgramChangeCTF(event->data.channel.channel, - event->data.channel.param2, fallback); + SendProgramChange(event->data.channel.channel, + event->data.channel.param2); } break; @@ -632,7 +674,7 @@ static void SendEMIDI(const midi_event_t *event, midi_track_t *track, } } -static void SendMetaMsg(const midi_event_t *event, midi_track_t *track) +static void ProcessMetaEvent(const midi_event_t *event, midi_track_t *track) { switch (event->data.meta.type) { @@ -663,20 +705,27 @@ static void ProcessEvent_Vanilla(const midi_event_t *event, midi_track_t *track) { switch (event->event_type) { - case MIDI_EVENT_SYSEX: - break; - case MIDI_EVENT_META: - SendMetaMsg(event, track); + ProcessMetaEvent(event, track); break; case MIDI_EVENT_CONTROLLER: switch (event->data.channel.param1) { case MIDI_CONTROLLER_BANK_SELECT_MSB: + // DMX has broken bank select support and runs in GM mode. + // Actual behavior (MSB is okay): + //SendBankSelectMSB(event->data.channel.channel, + // event->data.channel.param2); + SendBankSelectMSB(event->data.channel.channel, 0); + break; + case MIDI_CONTROLLER_BANK_SELECT_LSB: // DMX has broken bank select support and runs in GM mode. - SendChannelMsgZero(event); + // Actual behavior (LSB is sent as MSB!): + //SendBankSelectMSB(event->data.channel.channel, + // event->data.channel.param2); + SendBankSelectLSB(event->data.channel.channel, 0); break; case MIDI_CONTROLLER_MODULATION: @@ -717,7 +766,8 @@ static void ProcessEvent_Vanilla(const midi_event_t *event, midi_track_t *track) break; case MIDI_EVENT_PROGRAM_CHANGE: - SendChannelMsg(event, false); + SendProgramChange(event->data.channel.channel, + event->data.channel.param1); break; default: @@ -731,13 +781,6 @@ static void ProcessEvent_Vanilla(const midi_event_t *event, midi_track_t *track) static void ProcessEvent_Standard(const midi_event_t *event, midi_track_t *track) { - midi_fallback_t fallback = {FALLBACK_NONE, 0}; - - if (use_fallback) - { - MIDI_CheckFallback(event, &fallback, midi_complevel == COMP_FULL); - } - switch ((int)event->event_type) { case MIDI_EVENT_SYSEX: @@ -748,7 +791,7 @@ static void ProcessEvent_Standard(const midi_event_t *event, return; case MIDI_EVENT_META: - SendMetaMsg(event, track); + ProcessMetaEvent(event, track); return; } @@ -762,7 +805,6 @@ static void ProcessEvent_Standard(const midi_event_t *event, case MIDI_EVENT_CONTROLLER: switch (event->data.channel.param1) { - case MIDI_CONTROLLER_BANK_SELECT_MSB: case MIDI_CONTROLLER_MODULATION: case MIDI_CONTROLLER_DATA_ENTRY_MSB: case MIDI_CONTROLLER_PAN: @@ -786,15 +828,14 @@ static void ProcessEvent_Standard(const midi_event_t *event, case MIDI_CONTROLLER_VOLUME_LSB: break; + case MIDI_CONTROLLER_BANK_SELECT_MSB: + SendBankSelectMSB(event->data.channel.channel, + event->data.channel.param2); + break; + case MIDI_CONTROLLER_BANK_SELECT_LSB: - if (fallback.type == FALLBACK_BANK_LSB) - { - SendChannelMsgZero(event); - } - else - { - SendChannelMsg(event, true); - } + SendBankSelectLSB(event->data.channel.channel, + event->data.channel.param2); break; case MIDI_CONTROLLER_NRPN_LSB: @@ -864,7 +905,7 @@ static void ProcessEvent_Standard(const midi_event_t *event, case EMIDI_CONTROLLER_LOOP_END: case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: case EMIDI_CONTROLLER_GLOBAL_LOOP_END: - SendEMIDI(event, track, &fallback); + SendEMIDI(event, track); break; case MIDI_CONTROLLER_RESET_ALL_CTRLS: @@ -907,8 +948,8 @@ static void ProcessEvent_Standard(const midi_event_t *event, case MIDI_EVENT_PROGRAM_CHANGE: if (!track->emidi_program) { - SendProgramChangeCTF(event->data.channel.channel, - event->data.channel.param1, &fallback); + SendProgramChange(event->data.channel.channel, + event->data.channel.param1); } break; @@ -1216,9 +1257,23 @@ static boolean I_MID_InitMusic(int device) return false; } - ProcessEvent = (midi_complevel == COMP_VANILLA) ? ProcessEvent_Vanilla - : ProcessEvent_Standard; - MIDI_InitFallback(); + switch (midi_complevel) + { + case COMP_VANILLA: + ProcessEvent = ProcessEvent_Vanilla; + allow_bank_select = false; + break; + + case COMP_STANDARD: + ProcessEvent = ProcessEvent_Standard; + allow_bank_select = (midi_reset_type != RESET_TYPE_GM); + break; + + case COMP_FULL: + ProcessEvent = ProcessEvent_Standard; + allow_bank_select = true; + break; + } music_initialized = true; diff --git a/src/m_config.c b/src/m_config.c index 6bb35bca..961d9d77 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -93,6 +93,7 @@ extern int mus_gain; extern int midi_complevel; extern int midi_reset_type; extern int midi_reset_delay; +extern boolean midi_ctf; extern int opl_gain; extern boolean demobar; extern boolean smoothlight; @@ -558,6 +559,13 @@ default_t defaults[] = { "Delay after reset for native MIDI (-1 = Auto, 0 = None, 1-2000 = Milliseconds)" }, + { + "midi_ctf", + (config_t *) &midi_ctf, NULL, + {1}, {0, 1}, number, ss_none, wad_no, + "1 to fix invalid instruments by emulating SC-55 capital tone fallback" + }, + // // QOL features // diff --git a/src/midifallback.c b/src/midifallback.c index fbbc8ffb..55ee5bde 100644 --- a/src/midifallback.c +++ b/src/midifallback.c @@ -15,329 +15,257 @@ // MIDI instrument fallback support // -#include "midifallback.h" -#include "doomtype.h" -#include "i_printf.h" -#include "midifile.h" +#include -static const byte drums_table[128] = +#include "midifallback.h" +#include "i_printf.h" + +static const byte presets[128][128] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x18, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F + [1] = // Variation #1 + { + [38] = 1, + [57] = 1, + [60] = 1, + [80] = 1, + [81] = 1, + [98] = 1, + [102] = 1, + [104] = 1, + [120] = 1, + [121] = 1, + [122] = 1, + [123] = 1, + [124] = 1, + [125] = 1, + [126] = 1, + [127] = 1, + }, + [2] = // Variation #2 + { + [102] = 2, + [120] = 2, + [122] = 2, + [123] = 2, + [124] = 2, + [125] = 2, + [126] = 2, + [127] = 2, + }, + [3] = // Variation #3 + { + [122] = 3, + [123] = 3, + [124] = 3, + [125] = 3, + [126] = 3, + [127] = 3, + }, + [4] = // Variation #4 + { + [122] = 4, + [124] = 4, + [125] = 4, + [126] = 4, + }, + [5] = // Variation #5 + { + [122] = 5, + [124] = 5, + [125] = 5, + [126] = 5, + }, + [6] = // Variation #6 + { + [125] = 6, + }, + [7] = // Variation #7 + { + [125] = 7, + }, + [8] = // Variation #8 + { + [0] = 8, + [1] = 8, + [2] = 8, + [3] = 8, + [4] = 8, + [5] = 8, + [6] = 8, + [11] = 8, + [12] = 8, + [14] = 8, + [16] = 8, + [17] = 8, + [19] = 8, + [21] = 8, + [24] = 8, + [25] = 8, + [26] = 8, + [27] = 8, + [28] = 8, + [30] = 8, + [31] = 8, + [38] = 8, + [39] = 8, + [40] = 8, + [48] = 8, + [50] = 8, + [61] = 8, + [62] = 8, + [63] = 8, + [80] = 8, + [81] = 8, + [107] = 8, + [115] = 8, + [116] = 8, + [117] = 8, + [118] = 8, + [125] = 8, + }, + [9] = // Variation #9 + { + [14] = 9, + [118] = 9, + [125] = 9, + }, + [16] = // Variation #16 + { + [0] = 16, + [4] = 16, + [5] = 16, + [6] = 16, + [16] = 16, + [19] = 16, + [24] = 16, + [25] = 16, + [28] = 16, + [39] = 16, + [62] = 16, + [63] = 16, + }, + [24] = // Variation #24 + { + [4] = 24, + [6] = 24, + }, + [32] = // Variation #32 + { + [16] = 32, + [17] = 32, + [24] = 32, + [52] = 32, + }, +}; + +static const byte drums[128] = +{ + [8] = 8, + [16] = 16, + [24] = 24, + [25] = 25, + [32] = 32, + [40] = 40, + [48] = 48, + [56] = 56, }; -static byte variation[128][128]; static byte bank_msb[MIDI_CHANNELS_PER_TRACK]; static byte drum_map[MIDI_CHANNELS_PER_TRACK]; -static boolean selected[MIDI_CHANNELS_PER_TRACK]; - -static boolean GetProgramFallback(byte idx, byte program, - midi_fallback_t *fallback) -{ - if (drum_map[idx] == 0) // Normal channel - { - if (bank_msb[idx] == 0 || variation[bank_msb[idx]][program]) - { - // Found a capital or variation for this bank select MSB. - selected[idx] = true; - return false; - } - - fallback->type = FALLBACK_BANK_MSB; - - if (!selected[idx] || bank_msb[idx] > 63) - { - // Fall to capital when no instrument has (successfully) - // selected this variation or if the variation is above 63. - fallback->value = 0; - - I_Printf(VB_WARNING, - "midifallback: warning: ch=%d [bank_msb=%d prog=%d] " - "falling back to [bank_msb=%d prog=%d]", - idx, bank_msb[idx], program, fallback->value, program); - return true; - } - - // A previous instrument used this variation but it's not - // valid for the current instrument. Fall to the next valid - // "sub-capital" (next variation that is a multiple of 8). - fallback->value = (bank_msb[idx] / 8) * 8; - while (fallback->value > 0) - { - if (variation[fallback->value][program]) - { - break; - } - fallback->value -= 8; - } - - I_Printf(VB_WARNING, - "midifallback: warning: ch=%d [bank_msb=%d prog=%d] " - "falling back to [bank_msb=%d prog=%d]", - idx, bank_msb[idx], program, fallback->value, program); - return true; - } - else // Drums channel - { - if (program != drums_table[program]) - { - // Use drum set from drums fallback table. - // Drums 0-63 and 127: same as original SC-55 (1.00 - 1.21). - // Drums 64-126: standard drum set (0). - fallback->type = FALLBACK_DRUMS; - fallback->value = drums_table[program]; - selected[idx] = true; - - I_Printf(VB_WARNING, - "midifallback: warning: ch=%d [prog=%d] " - "falling back to [prog=%d] (drums)", - idx, program, fallback->value); - return true; - } - } - - return false; -} - -void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, - boolean allow_sysex) -{ - byte idx; - byte program; - - switch ((int)event->event_type) - { - case MIDI_EVENT_SYSEX: - if (allow_sysex && event->data.sysex.type == MIDI_SYSEX_RHYTHM_PART) - { - // GS allows drums on any channel using SysEx messages. - // The message format is: - // F0 41 10 42 12 40 15 F7 - // is [11-19, 10, 1A-1F] for channels 1-16. - // is 00-02 for off (normal part) or drum map 1/2. - // is checksum. - drum_map[event->data.sysex.channel] = event->data.sysex.data[8]; - } - break; - - case MIDI_EVENT_CONTROLLER: - idx = event->data.channel.channel; - switch (event->data.channel.param1) - { - case MIDI_CONTROLLER_BANK_SELECT_MSB: - bank_msb[idx] = event->data.channel.param2; - selected[idx] = false; - break; - - case MIDI_CONTROLLER_BANK_SELECT_LSB: - selected[idx] = false; - if (event->data.channel.param2 > 0) - { - // Bank select LSB > 0 not supported. This also - // preserves user's current SC-XX map. - fallback->type = FALLBACK_BANK_LSB; - fallback->value = 0; - - I_Printf(VB_WARNING, - "midifallback: warning: ch=%d [bank_lsb=%d] " - "replaced by [bank_lsb=%d]", - idx, event->data.channel.param2, - fallback->value); - return; - } - break; - - case EMIDI_CONTROLLER_PROGRAM_CHANGE: - program = event->data.channel.param2; - if (GetProgramFallback(idx, program, fallback)) - { - return; - } - break; - } - break; - - case MIDI_EVENT_PROGRAM_CHANGE: - idx = event->data.channel.channel; - program = event->data.channel.param1; - if (GetProgramFallback(idx, program, fallback)) - { - return; - } - break; - } - - fallback->type = FALLBACK_NONE; - fallback->value = 0; -} void MIDI_ResetFallback(void) { - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; i++) - { - bank_msb[i] = 0; - drum_map[i] = 0; - selected[i] = false; - } + memset(bank_msb, 0, sizeof(bank_msb)); + memset(drum_map, 0, sizeof(drum_map)); // Channel 10 (index 9) is set to drum map 1 by default. drum_map[9] = 1; } -void MIDI_InitFallback(void) +void MIDI_UpdateBankMSB(byte idx, byte value) { - byte program; - - MIDI_ResetFallback(); - - // Capital - for (program = 0; program < 128; program++) - { - variation[0][program] = 1; - } - - // Variation #1 - variation[1][38] = 1; - variation[1][57] = 1; - variation[1][60] = 1; - variation[1][80] = 1; - variation[1][81] = 1; - variation[1][98] = 1; - variation[1][102] = 1; - variation[1][104] = 1; - variation[1][120] = 1; - variation[1][121] = 1; - variation[1][122] = 1; - variation[1][123] = 1; - variation[1][124] = 1; - variation[1][125] = 1; - variation[1][126] = 1; - variation[1][127] = 1; - - // Variation #2 - variation[2][102] = 1; - variation[2][120] = 1; - variation[2][122] = 1; - variation[2][123] = 1; - variation[2][124] = 1; - variation[2][125] = 1; - variation[2][126] = 1; - variation[2][127] = 1; - - // Variation #3 - variation[3][122] = 1; - variation[3][123] = 1; - variation[3][124] = 1; - variation[3][125] = 1; - variation[3][126] = 1; - variation[3][127] = 1; - - // Variation #4 - variation[4][122] = 1; - variation[4][124] = 1; - variation[4][125] = 1; - variation[4][126] = 1; - - // Variation #5 - variation[5][122] = 1; - variation[5][124] = 1; - variation[5][125] = 1; - variation[5][126] = 1; - - // Variation #6 - variation[6][125] = 1; - - // Variation #7 - variation[7][125] = 1; - - // Variation #8 - variation[8][0] = 1; - variation[8][1] = 1; - variation[8][2] = 1; - variation[8][3] = 1; - variation[8][4] = 1; - variation[8][5] = 1; - variation[8][6] = 1; - variation[8][11] = 1; - variation[8][12] = 1; - variation[8][14] = 1; - variation[8][16] = 1; - variation[8][17] = 1; - variation[8][19] = 1; - variation[8][21] = 1; - variation[8][24] = 1; - variation[8][25] = 1; - variation[8][26] = 1; - variation[8][27] = 1; - variation[8][28] = 1; - variation[8][30] = 1; - variation[8][31] = 1; - variation[8][38] = 1; - variation[8][39] = 1; - variation[8][40] = 1; - variation[8][48] = 1; - variation[8][50] = 1; - variation[8][61] = 1; - variation[8][62] = 1; - variation[8][63] = 1; - variation[8][80] = 1; - variation[8][81] = 1; - variation[8][107] = 1; - variation[8][115] = 1; - variation[8][116] = 1; - variation[8][117] = 1; - variation[8][118] = 1; - variation[8][125] = 1; - - // Variation #9 - variation[9][14] = 1; - variation[9][118] = 1; - variation[9][125] = 1; - - // Variation #16 - variation[16][0] = 1; - variation[16][4] = 1; - variation[16][5] = 1; - variation[16][6] = 1; - variation[16][16] = 1; - variation[16][19] = 1; - variation[16][24] = 1; - variation[16][25] = 1; - variation[16][28] = 1; - variation[16][39] = 1; - variation[16][62] = 1; - variation[16][63] = 1; - - // Variation #24 - variation[24][4] = 1; - variation[24][6] = 1; - - // Variation #32 - variation[32][16] = 1; - variation[32][17] = 1; - variation[32][24] = 1; - variation[32][52] = 1; - - // CM-64 Map (PCM) - for (program = 0; program < 64; program++) - { - variation[126][program] = 1; - } - - // CM-64 Map (LA) - for (program = 0; program < 128; program++) - { - variation[127][program] = 1; - } + bank_msb[idx] = value; +} + +void MIDI_UpdateDrumMap(byte idx, byte value) +{ + drum_map[idx] = value; +} + +midi_fallback_t MIDI_BankLSBFallback(byte idx, byte value) +{ + midi_fallback_t fallback; + + if (value == 0) + { + // Bank select LSB is already zero. No fallback required. + fallback.type = FALLBACK_NONE; + fallback.value = 0; + } + else + { + // Bank select LSB is not supported. + fallback.type = FALLBACK_BANK_LSB; + fallback.value = 0; + + I_Printf(VB_DEBUG, "midifallback: ch=%d [lsb=%d] to [lsb=%d]", + idx, value, fallback.value); + } + + return fallback; +} + +midi_fallback_t MIDI_ProgramFallback(byte idx, byte program) +{ + midi_fallback_t fallback; + + if (drum_map[idx] == 0) // Normal channel + { + const byte variation = bank_msb[idx]; + + if (variation == 0 || variation == presets[variation][program]) + { + // Found a capital or variation. No fallback required. + fallback.type = FALLBACK_NONE; + fallback.value = 0; + } + else + { + fallback.type = FALLBACK_BANK_MSB; + + if (variation > 63 || program > 119) + { + // Fall to capital. + fallback.value = 0; + } + else + { + // Fall to sub-capital (next multiple of 8). + fallback.value = presets[variation & ~7][program]; + } + + I_Printf(VB_DEBUG, "midifallback: ch=%d pc=%d [msb=%d] to [msb=%d]", + idx, program, variation, fallback.value); + } + } + else // Drums Channel + { + if (program == 0 || program == drums[program]) + { + // Found a drum set. No fallback required. + fallback.type = FALLBACK_NONE; + fallback.value = 0; + } + else + { + // Fall to sub-drum set (next multiple of 8). + fallback.type = FALLBACK_DRUMS; + fallback.value = drums[program & ~7]; + + I_Printf(VB_DEBUG, "midifallback: ch=%d (drums) [pc=%d] to [pc=%d]", + idx, program, fallback.value); + } + } + + return fallback; } diff --git a/src/midifallback.h b/src/midifallback.h index dd96ff74..766af4ba 100644 --- a/src/midifallback.h +++ b/src/midifallback.h @@ -35,9 +35,10 @@ typedef struct midi_fallback_t byte value; } midi_fallback_t; -void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, - boolean allow_sysex); void MIDI_ResetFallback(void); -void MIDI_InitFallback(void); +void MIDI_UpdateBankMSB(byte idx, byte value); +void MIDI_UpdateDrumMap(byte idx, byte value); +midi_fallback_t MIDI_BankLSBFallback(byte idx, byte value); +midi_fallback_t MIDI_ProgramFallback(byte idx, byte program); #endif // MIDIFALLBACK_H