diff options
author | Wohlstand <admin@wohlnet.ru> | 2016-01-15 17:42:26 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2016-01-15 17:42:26 +0300 |
commit | b0bdfa427ab177f4b6304a2a1d27ca77c35d9daf (patch) | |
tree | a95e377aadb9736806a3e55f7210484323df8f68 /src/adlmidi.cpp | |
parent | f59d6b3a20444b3f7cf58a3553098638f25a4d69 (diff) | |
download | libADLMIDI-b0bdfa427ab177f4b6304a2a1d27ca77c35d9daf.tar.gz libADLMIDI-b0bdfa427ab177f4b6304a2a1d27ca77c35d9daf.tar.bz2 libADLMIDI-b0bdfa427ab177f4b6304a2a1d27ca77c35d9daf.zip |
Fixed freezing on invalid loop points
Fixed freezing on invalid cases of loop points:
- loopEnd going before loopStart
- loopStart and loopEnd are at same position (tick) which
Both cases are causes infinite loop inside same tick
Diffstat (limited to 'src/adlmidi.cpp')
-rw-r--r-- | src/adlmidi.cpp | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index 246f5f7..bdf4eac 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -415,7 +415,9 @@ class MIDIplay std::vector<TrackInfo> track; Position(): began(false), wait(0.0), track() { } - } CurrentPosition, LoopBeginPosition; + }; + Position CurrentPosition, LoopBeginPosition, trackBeginPosition; + std::map<std::string, unsigned> devices; std::map<unsigned/*track*/, unsigned/*channel begin index*/> current_device; @@ -515,8 +517,12 @@ class MIDIplay public: std::string musTitle; fraction<long> InvDeltaTicks, Tempo; - bool loopStart, loopEnd, invalidLoop; - long loopStart_ticks, loopEnd_ticks; + bool trackStart, + loopStart, + loopEnd, + loopStart_passed /*Tells that "loopStart" already passed*/, + invalidLoop /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/, + loopStart_hit /*loopStart entry was hited in previous tick*/; OPL3 opl; public: static unsigned long ReadBEInt(const void* buffer, unsigned nbytes) @@ -830,8 +836,11 @@ public: CurrentPosition.track[tk].delay = ReadVarLen(tk); } } - loopStart = true; + trackStart = true; + loopStart = true; + loopStart_passed = false; invalidLoop = false; + loopStart_hit = false; opl.Reset(); // Reset AdLib //opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously) @@ -1029,17 +1038,33 @@ private: // ^HACK: CHRONO TRIGGER LOOP */ + if(loopStart_hit && (loopStart||loopEnd)) //Avoid invalid loops + { + invalidLoop=true; + loopStart = false; + loopEnd = false; + LoopBeginPosition=trackBeginPosition; + } else { + loopStart_hit=false; + } + if(loopStart) { + if(trackStart) + { + trackBeginPosition=RowBeginPosition; + trackStart=false; + } LoopBeginPosition = RowBeginPosition; loopStart = false; + loopStart_hit=true; } if(shortest < 0 || loopEnd) { // Loop if song end reached loopEnd = false; CurrentPosition = LoopBeginPosition; - shortest = 0; + shortest = 0; if(opl._parent->QuitWithoutLooping==1) { opl._parent->QuitFlag = 1; @@ -1068,8 +1093,28 @@ private: CurrentPosition.track[tk].ptr += length; if(evtype == 0x2F) { CurrentPosition.track[tk].status = -1; return; } if(evtype == 0x51) { Tempo = InvDeltaTicks * fraction<long>( (long) ReadBEInt(data.data(), data.size())); return; } - if(evtype == 6 && data == "loopStart") loopStart = true; - if(evtype == 6 && data == "loopEnd" ) loopEnd = true; + if(evtype == 6) + { + for(size_t i=0;i<data.size();i++) + { + if(data[i]<='Z' && data[i]>='A') + data[i]=data[i]-('Z'-'z'); + } + + if( (data == "loopstart") && (!invalidLoop) ) + { + loopStart = true; + loopStart_passed=true; + } + + if( (data == "loopend") && (!invalidLoop) ) + { + if((loopStart_passed) && (!loopStart)) + loopEnd=true; + else + invalidLoop=true; + } + } if(evtype == 9) current_device[tk] = ChooseDevice(data); // if(evtype >= 1 && evtype <= 6) // UI.PrintLn("Meta %d: %s", evtype, data.c_str()); |