[Scummvm-cvs-logs] SF.net SVN: scummvm: [32930] scummvm/trunk
eriktorbjorn at users.sourceforge.net
eriktorbjorn at users.sourceforge.net
Sun Jul 6 20:37:52 CEST 2008
Revision: 32930
http://scummvm.svn.sourceforge.net/scummvm/?rev=32930&view=rev
Author: eriktorbjorn
Date: 2008-07-06 11:37:52 -0700 (Sun, 06 Jul 2008)
Log Message:
-----------
Implemented Good Enough(TM) XMIDI looping. This is used by Kyrandia 2 (the
loop hack is no longer needed, and has been removed), and will be used by
Discworld.
Modified Paths:
--------------
scummvm/trunk/engines/kyra/sound.cpp
scummvm/trunk/sound/midiparser_xmidi.cpp
Modified: scummvm/trunk/engines/kyra/sound.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound.cpp 2008-07-06 17:33:37 UTC (rev 32929)
+++ scummvm/trunk/engines/kyra/sound.cpp 2008-07-06 18:37:52 UTC (rev 32930)
@@ -249,21 +249,6 @@
}
void SoundMidiPC::send(uint32 b) {
- // HACK: For Kyrandia, we make the simplifying assumption that a song
- // either loops in its entirety, or not at all. So if we see a FOR_LOOP
- // controller event, we turn on looping even if there isn't any
- // corresponding NEXT_BREAK event.
- //
- // This is a gross over-simplification of how XMIDI handles loops. If
- // anyone feels like doing a proper implementation, please refer to
- // the Exult project, and do it in midiparser_xmidi.cpp
-
- if ((b & 0xFFF0) == 0x74B0 && _eventFromMusic) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "SoundMidiPC: Looping song");
- _musicParser->property(MidiParser::mpAutoLoop, true);
- return;
- }
-
if (_passThrough) {
if ((b & 0xFFF0) == 0x007BB0)
return;
Modified: scummvm/trunk/sound/midiparser_xmidi.cpp
===================================================================
--- scummvm/trunk/sound/midiparser_xmidi.cpp 2008-07-06 17:33:37 UTC (rev 32929)
+++ scummvm/trunk/sound/midiparser_xmidi.cpp 2008-07-06 18:37:52 UTC (rev 32930)
@@ -38,6 +38,14 @@
NoteTimer _notes_cache[32];
uint32 _inserted_delta; // Track simulated deltas for note-off events
+ struct Loop {
+ byte *pos;
+ byte repeat;
+ };
+
+ Loop _loop[4];
+ int _loopCount;
+
protected:
uint32 readVLQ2(byte * &data);
void resetTracking();
@@ -83,11 +91,51 @@
info.basic.param2 = 0;
break;
- case 0x8: case 0xA: case 0xB: case 0xE:
+ case 0xB:
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = *(_position._play_pos++);
+
+ // Simplified XMIDI looping.
+ //
+ // I would really like to turn the loop events into some sort
+ // of NOP event (perhaps a dummy META event?), but for now we
+ // just pass them on to the MIDI driver. That has worked in the
+ // past, so it shouldn't cause any actual damage...
+
+ if (info.basic.param1 == 0x74) {
+ // XMIDI_CONTROLLER_FOR_LOOP
+ byte *pos = _position._play_pos - 3;
+ if (_loopCount < 0 || _loop[_loopCount].pos != pos) {
+ if (_loopCount < ARRAYSIZE(_loop) - 1)
+ _loopCount++;
+
+ _loop[_loopCount].pos = pos;
+ _loop[_loopCount].repeat = info.basic.param2;
+ }
+ } else if (info.basic.param1 == 0x75) {
+ // XMIDI_CONTROLLER_NEXT_BREAK
+ if (_loopCount >= 0) {
+ if (info.basic.param2 < 64) {
+ _loopCount--;
+ }
+
+ if (_loopCount >= 0) {
+ _position._play_pos = _loop[_loopCount].pos;
+ // Repeat 0 means "loop forever".
+ if (_loop[_loopCount].repeat) {
+ if (--_loop[_loopCount].repeat == 0)
+ _loopCount--;
+ }
+ }
+ }
+ }
break;
+ case 0x8: case 0xA: case 0xE:
+ info.basic.param1 = *(_position._play_pos++);
+ info.basic.param2 = *(_position._play_pos++);
+ break;
+
case 0xF: // Meta or SysEx event
switch (info.event & 0x0F) {
case 0x2: // Song Position Pointer
@@ -136,6 +184,8 @@
uint32 chunk_len;
char buf[32];
+ _loopCount = -1;
+
unloadMusic();
byte *pos = data;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list