diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/adlmidi_midiplay.cpp | 3 | ||||
-rw-r--r-- | src/adlmidi_midiplay.hpp | 13 | ||||
-rw-r--r-- | src/adlmidi_sequencer.cpp | 10 | ||||
-rw-r--r-- | src/midi_sequencer.h | 6 | ||||
-rw-r--r-- | src/midi_sequencer.hpp | 17 | ||||
-rw-r--r-- | src/midi_sequencer_impl.hpp | 18 |
7 files changed, 52 insertions, 16 deletions
@@ -189,6 +189,7 @@ To build that example you will need to have installed SDL2 library. * Removed C++ extras. C++-binded instruments tester is useless since a real-time MIDI API can completely replace it * Added AIL volume model * Added Generic FM variant of Win9X volume model + * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details) ## 1.4.0 2018-10-01 * Implemented a full support for Portamento! (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 358e284..a7fb4ed 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -187,6 +187,7 @@ void MIDIplay::partialReset() synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); m_chipChannels.clear(); m_chipChannels.resize((size_t)synth.m_numChannels); + resetMIDIDefaults(); } void MIDIplay::resetMIDI() @@ -774,7 +775,7 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value) break; case 121: // Reset all controllers - m_midiChannels[channel].resetAllControllers(); + m_midiChannels[channel].resetAllControllers121(); noteUpdateAll(channel, Upd_Pan + Upd_Volume + Upd_Pitch); // Kill all sustained notes killSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_ANY); diff --git a/src/adlmidi_midiplay.hpp b/src/adlmidi_midiplay.hpp index 93b36e9..7eaf51d 100644 --- a/src/adlmidi_midiplay.hpp +++ b/src/adlmidi_midiplay.hpp @@ -327,11 +327,21 @@ public: */ void resetAllControllers() { + volume = def_volume; + brightness = 127; + + resetAllControllers121(); + } + + /** + * @brief Reset all MIDI controllers into initial state (CC121) + */ + void resetAllControllers121() + { bend = 0; bendsense_msb = def_bendsense_msb; bendsense_lsb = def_bendsense_lsb; updateBendSensitivity(); - volume = def_volume; expression = 127; sustain = false; softPedal = false; @@ -347,7 +357,6 @@ public: portamentoEnable = false; portamentoSource = -1; portamentoRate = HUGE_VAL; - brightness = 127; } /** diff --git a/src/adlmidi_sequencer.cpp b/src/adlmidi_sequencer.cpp index e6de2b3..bf3d86c 100644 --- a/src/adlmidi_sequencer.cpp +++ b/src/adlmidi_sequencer.cpp @@ -103,6 +103,13 @@ static size_t rtCurrentDevice(void *userdata, size_t track) MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata); return context->realTime_currentDevice(track); } + +static void rtSongBegin(void *userdata) +{ + MIDIplay *context = reinterpret_cast<MIDIplay *>(userdata); + return context->realTime_ResetState(); +} + /* NonStandard calls End */ @@ -131,6 +138,9 @@ void MIDIplay::initSequencerInterface() seq->rt_rawOPL = rtRawOPL; seq->rt_deviceSwitch = rtDeviceSwitch; seq->rt_currentDevice = rtCurrentDevice; + + seq->onSongStart = rtSongBegin; + seq->onSongStart_userData = this; /* NonStandard calls End */ m_sequencer->setInterface(seq); diff --git a/src/midi_sequencer.h b/src/midi_sequencer.h index b9b8982..4d35d06 100644 --- a/src/midi_sequencer.h +++ b/src/midi_sequencer.h @@ -79,6 +79,12 @@ typedef struct BW_MidiRtInterface /*! User data which will be passed through On-LoopStart hook */ void *onloopEnd_userData; + typedef void (*SongStartHook)(void *userdata); + /*! Song start hook which is calling when starting playing song at begin */ + SongStartHook onSongStart; + /*! User data which will be passed through On-SongStart hook */ + void *onSongStart_userData; + /*! MIDI Run Time event calls user data */ void *rtUserData; diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 7ff864c..69dead8 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -76,7 +76,7 @@ class BW_MidiSequencer //! System Exclusive message, type 2 T_SYSEX2 = 0xF7,//size == len //! Special event - T_SPECIAL = 0xFF + T_SPECIAL = 0xFF, }; /** * @brief Special MIDI event sub-types @@ -132,18 +132,21 @@ class BW_MidiSequencer //! [Non-Standard] Loop End point with support of multi-loops ST_LOOPSTACK_BREAK = 0xE6,//size == 0 <CUSTOM> //! [Non-Standard] Callback Trigger - ST_CALLBACK_TRIGGER = 0xE7//size == 1 <CUSTOM> + ST_CALLBACK_TRIGGER = 0xE7,//size == 1 <CUSTOM> + + // Built-in hooks + ST_SONG_BEGIN_HOOK = 0x101 }; //! Main type of event - uint8_t type; + uint_fast16_t type; //! Sub-type of the event - uint8_t subtype; + uint_fast16_t subtype; //! Targeted MIDI channel - uint8_t channel; + uint_fast16_t channel; //! Is valid event - uint8_t isValid; + uint_fast16_t isValid; //! Reserved 5 bytes padding - uint8_t __padding[4]; + uint_fast16_t __padding[4]; //! Absolute tick position (Used for the tempo calculation only) uint64_t absPosition; //! Raw data of this event diff --git a/src/midi_sequencer_impl.hpp b/src/midi_sequencer_impl.hpp index f0ba839..62e78c3 100644 --- a/src/midi_sequencer_impl.hpp +++ b/src/midi_sequencer_impl.hpp @@ -206,6 +206,7 @@ void BW_MidiSequencer::MidiTrackRow::sortEvents(bool *noteStates) else if((events[i].type == MidiEvent::T_SPECIAL) && ( (events[i].subtype == MidiEvent::ST_MARKER) || (events[i].subtype == MidiEvent::ST_DEVICESWITCH) || + (events[i].subtype == MidiEvent::ST_SONG_BEGIN_HOOK) || (events[i].subtype == MidiEvent::ST_LOOPSTART) || (events[i].subtype == MidiEvent::ST_LOOPEND) || (events[i].subtype == MidiEvent::ST_LOOPSTACK_BEGIN) || @@ -566,13 +567,11 @@ bool BW_MidiSequencer::buildSmfTrackData(const std::vector<std::vector<uint8_t> } // HACK: Begin every track with "Reset all controllers" event to avoid controllers state break came from end of song - for(uint8_t chan = 0; chan < 16; chan++) + if(tk == 0) { MidiEvent resetEvent; - resetEvent.type = MidiEvent::T_CTRLCHANGE; - resetEvent.channel = chan; - resetEvent.data.push_back(121); - resetEvent.data.push_back(0); + resetEvent.type = MidiEvent::T_SPECIAL; + resetEvent.subtype = MidiEvent::ST_SONG_BEGIN_HOOK; evtPos.events.push_back(resetEvent); } @@ -1677,7 +1676,7 @@ void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEve if(evt.type == MidiEvent::T_SPECIAL) { // Special event FF - uint8_t evtype = evt.subtype; + uint_fast16_t evtype = evt.subtype; uint64_t length = static_cast<uint64_t>(evt.data.size()); const char *data(length ? reinterpret_cast<const char *>(evt.data.data()) : ""); @@ -1771,6 +1770,13 @@ void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEve return; } + if(evtype == MidiEvent::ST_SONG_BEGIN_HOOK) + { + if(m_interface->onSongStart) + m_interface->onSongStart(m_interface->onSongStart_userData); + return; + } + return; } |