diff options
author | Wohlstand <admin@wohlnet.ru> | 2017-11-09 22:50:32 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2017-11-09 22:50:32 +0300 |
commit | 0be25a41ca793c3c03814f529890492adfac8ad5 (patch) | |
tree | a099d0025109b689bb0d6847e83b9890e34d5d35 /src | |
parent | 265ae7a37afb087b9e16f4ddd0eaef28a21826de (diff) | |
download | libADLMIDI-0be25a41ca793c3c03814f529890492adfac8ad5.tar.gz libADLMIDI-0be25a41ca793c3c03814f529890492adfac8ad5.tar.bz2 libADLMIDI-0be25a41ca793c3c03814f529890492adfac8ad5.zip |
Resolve weird crash caused by Tetris inside ADLMIDI2 and other changes
- Move most of inline classes methods into own CC file
- Move Input into own header with own CC file to share it with the puzzle game
- Created virtual destructors and resolved weak vtable trouble between of Tetris's classes
- Remove static declarisons of Tetris class. Instead, let it be member of UserInterface
- Fixed forgot note-offs while sorting events row with zero length notes
- Fixed crash caused by unsafe access by reference to element of array that was modified/reallocated one or multiple times
- Stabilize dealing with zero-length notes
Diffstat (limited to 'src')
-rw-r--r-- | src/adlmidi_midiplay.cpp | 60 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 4 |
2 files changed, 44 insertions, 20 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 220b18c..83517db 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -193,38 +193,59 @@ void MIDIplay::MidiTrackRow::sortEvents(bool *noteStates) } /* - * If Note-Off and it's Note-On is on the same row - move this danmed note off down! + * If Note-Off and it's Note-On is on the same row - move this damned note off down! */ if(noteStates) { + std::set<size_t> markAsOn; for(size_t i = 0; i < anyOther.size(); i++) { - MidiEvent &e = anyOther[i]; + const MidiEvent e = anyOther[i]; if(e.type == MidiEvent::T_NOTEON) { - size_t note_i = (e.channel * 255) + e.data[0]; + const size_t note_i = (e.channel * 255) + (e.data[0] & 0x7F); //Check, was previously note is on or off bool wasOn = noteStates[note_i]; - bool keepOn = true; + markAsOn.insert(note_i); + // Detect zero-length notes are following previously pressed note + int noteOffsOnSameNote = 0; for(EvtArr::iterator j = noteOffs.begin(); j != noteOffs.end();) { //If note was off, and note-off on same row with note-on - move it down! if( ((*j).channel == e.channel) && - ((*j).data[0] == e.data[0]) && - !wasOn // Also check, is this note already OFF!!! + ((*j).data[0] == e.data[0]) ) { - anyOther.push_back(*j); - j = noteOffs.erase(j); - keepOn = false; - continue; + //If note is already off OR more than one note-off on same row and same note + if(!wasOn || (noteOffsOnSameNote != 0)) + { + anyOther.push_back(*j); + j = noteOffs.erase(j); + markAsOn.erase(note_i); + continue; + } else { + //When same row has many note-offs on same row + //that means a zero-length note follows previous note + //it must be shuted down + noteOffsOnSameNote++; + } } j++; } - if(keepOn) noteStates[note_i] = true; } } + + //Mark other notes as released + for(EvtArr::iterator j = noteOffs.begin(); j != noteOffs.end(); j++) + { + size_t note_i = (j->channel * 255) + (j->data[0] & 0x7F); + noteStates[note_i] = false; + } + + for(std::set<size_t>::iterator j = markAsOn.begin(); j != markAsOn.end(); j++) + noteStates[*j] = true; + } /***********************************************************************************/ @@ -1543,10 +1564,17 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) PositionNew::TrackInfo &track = CurrentPositionNew.track[tk]; if((track.status >= 0) && (track.delay <= 0)) { + //Check is an end of track has been reached + if(track.pos == trackDataNew[tk].end()) + { + track.status = -1; + break; + } + // Handle event for(size_t i = 0; i < track.pos->events.size(); i++) { - MidiEvent &evt = track.pos->events[i]; + const MidiEvent &evt = track.pos->events[i]; #ifdef ENABLE_BEGIN_SILENCE_SKIPPING if(!CurrentPositionNew.began && (evt.type == MidiEvent::T_NOTEON)) CurrentPositionNew.began = true; @@ -1562,11 +1590,7 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) if(maxTime < track.pos->time) maxTime = track.pos->time; #endif - // Read next event time (unless the track just ended) - if(track.pos == trackDataNew[tk].end()) - track.status = -1; - if(track.status >= 0) { track.delay += track.pos->delay; @@ -1847,7 +1871,7 @@ void MIDIplay::setErrorString(const std::string &err) } -void MIDIplay::HandleEvent(size_t tk, MIDIplay::MidiEvent &evt, int &status) +void MIDIplay::HandleEvent(size_t tk, const MIDIplay::MidiEvent &evt, int &status) { if(hooks.onEvent) { @@ -2575,7 +2599,7 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) default: const char *p = strchr(notes, ch); if(p && *p) - DoNote((p - notes) - 12); + DoNote((int)(p - notes) - 12); } return true; } diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 37e0d25..58b4e10 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -257,7 +257,7 @@ struct MIDIEventHooks onDebugMessage_userData(NULL) {} //! Raw MIDI event hook - typedef void (*RawEventHook)(void *userdata, uint8_t type, uint8_t subtype, uint8_t channel, uint8_t *data, size_t len); + typedef void (*RawEventHook)(void *userdata, uint8_t type, uint8_t subtype, uint8_t channel, const uint8_t *data, size_t len); RawEventHook onEvent; void *onEvent_userData; @@ -886,7 +886,7 @@ private: bool ProcessEvents(); bool ProcessEventsNew(bool isSeek = false); void HandleEvent(size_t tk); - void HandleEvent(size_t tk, MidiEvent &evt, int &status); + void HandleEvent(size_t tk, const MidiEvent &evt, int &status); // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. |