[Scummvm-cvs-logs] SF.net SVN: scummvm: [31636] scummvm/trunk/engines/agi

buddha_ at users.sourceforge.net buddha_ at users.sourceforge.net
Mon Apr 21 06:04:25 CEST 2008


Revision: 31636
          http://scummvm.svn.sourceforge.net/scummvm/?rev=31636&view=rev
Author:   buddha_
Date:     2008-04-20 21:04:24 -0700 (Sun, 20 Apr 2008)

Log Message:
-----------
Fix timing in Apple IIGS MIDI parsing. Now sounds should get triggered at the correct times without the previously observed time jitter effect.

Modified Paths:
--------------
    scummvm/trunk/engines/agi/sound.cpp
    scummvm/trunk/engines/agi/sound.h

Modified: scummvm/trunk/engines/agi/sound.cpp
===================================================================
--- scummvm/trunk/engines/agi/sound.cpp	2008-04-21 03:55:10 UTC (rev 31635)
+++ scummvm/trunk/engines/agi/sound.cpp	2008-04-21 04:04:24 UTC (rev 31636)
@@ -61,6 +61,7 @@
 	_ptr = _data + 2; // Set current position to just after the header
 	_len  = len;  // Save the resource's length
 	_type = READ_LE_UINT16(data); // Read sound resource's type
+	_midiTicks = _soundBufTicks = 0;
 	_isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2);
 
 	if (!_isValid) // Check for errors
@@ -276,11 +277,6 @@
 	{GID_GOLDRUSH, "GR",   0x3003, 148268, 0x8979, instSetV2}
 };
 
-// Time (In milliseconds) in Apple IIGS mixing buffer time granularity
-// (i.e. in IIGS_BUFFER_SIZE / getRate() seconds granularity)
-static uint32 g_IIgsBufGranMillis = 0;
-static uint32 g_midiMillis = 0; // Time position (In milliseconds) in currently playing MIDI sound
-
 static const int16 waveformRamp[WAVEFORM_SIZE] = {
 	0, 8, 16, 24, 32, 40, 48, 56,
 	64, 72, 80, 88, 96, 104, 112, 120,
@@ -367,22 +363,7 @@
 		break;
 	}
 	case AGI_SOUND_MIDI:
-		g_IIgsBufGranMillis = g_midiMillis = 0;
-#if 0
-		debugC(3, kDebugLevelSound, "IIGS MIDI sequence");
-
-		for (i = 0; i < NUM_CHANNELS; i++) {
-			_chn[i].type = type;
-			_chn[i].flags = AGI_SOUND_LOOP | AGI_SOUND_ENVELOPE;
-			_chn[i].ins = _waveform;
-			_chn[i].size = WAVEFORM_SIZE;
-			_chn[i].vol = 0;
-			_chn[i].end = 0;
-		}
-
-		_chn[0].timer = *(song + 2);
-		_chn[0].ptr = (struct AgiNote *)(song + 3);
-#endif
+		((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind();
 		break;
 	case AGI_SOUND_4CHN:
 		PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
@@ -552,31 +533,33 @@
 	_playing = true;
 	p = midiObj->getPtr();
 
-	g_IIgsBufGranMillis += (IIGS_BUFFER_SIZE * 1000) / getRate();
+	midiObj->_soundBufTicks++;
 
-	while (g_midiMillis < g_IIgsBufGranMillis) {
-		uint8 readByte = *p++;
+	while (true) {
+		uint8 readByte = *p;
 
 		// Check for end of MIDI sequence marker (Can also be here before delta-time)
 		if (readByte == MIDI_BYTE_STOP_SEQUENCE) {
 			debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)");
-			g_IIgsBufGranMillis = g_midiMillis = 0;
 			_playing = false;
 			midiObj->rewind();
 			return;
 		} else if (readByte == MIDI_BYTE_TIMER_SYNC) {
 			debugC(3, kDebugLevelSound, "Timer sync");
+			p++; // Jump over the timer sync byte as it's not needed
 			continue;
 		}
 
 		uint8 deltaTime = readByte;
-		uint32 ticksPerSec = 60; // Approximation based on tests with Apple IIGS KQ1 and SQ1 under MESS 0.124a
-		g_midiMillis += (deltaTime * 1000) / ticksPerSec;
+		if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) {
+			break;
+		}
+		midiObj->_midiTicks += deltaTime;
+		p++; // Jump over the delta-time byte as it was already taken care of
 
 		// Check for end of MIDI sequence marker (This time it after reading delta-time)
 		if (*p == MIDI_BYTE_STOP_SEQUENCE) {
 			debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)");
-			g_IIgsBufGranMillis = g_midiMillis = 0;
 			_playing = false;
 			midiObj->rewind();
 			return;
@@ -921,10 +904,10 @@
 
 					if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) {
 						const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg];
-						double bufSecLen = IIGS_BUFFER_SIZE / (double) getRate();
-						double ticksPerSec = 60; // Currently a guess, 1000 would be way too much
-						double bufTickLen  = bufSecLen / (1.0/ticksPerSec);
-						frac_t envVolDelta = doubleToFrac((seg.inc/256.0)*bufTickLen);
+						// I currently assume enveloping works with the same speed as the MIDI
+						// (i.e. with 1/60ths of a second ticks).
+						// TODO: Check if enveloping really works with the same speed as MIDI
+						frac_t envVolDelta = doubleToFrac(seg.inc/256.0);
 						if (intToFrac(seg.bp) >= channel.envVol) {
 							channel.envVol += envVolDelta;
 							if (channel.envVol >= intToFrac(seg.bp)) {

Modified: scummvm/trunk/engines/agi/sound.h
===================================================================
--- scummvm/trunk/engines/agi/sound.h	2008-04-21 03:55:10 UTC (rev 31635)
+++ scummvm/trunk/engines/agi/sound.h	2008-04-21 04:04:24 UTC (rev 31636)
@@ -36,8 +36,15 @@
 namespace Agi {
 
 #define BUFFER_SIZE	410
-#define IIGS_BUFFER_SIZE 200
 
+// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS
+// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a
+// 1/60th of a second in length. That should be getSampleRate() / 60 samples
+// in length but as getSampleRate() is always 22050 at the moment we just use
+// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368).
+// FIXME: Use getSampleRate() / 60 rather than a hardcoded value
+#define IIGS_BUFFER_SIZE 368
+
 #define SOUND_EMU_NONE	0
 #define SOUND_EMU_PC	1
 #define SOUND_EMU_TANDY	2
@@ -309,12 +316,15 @@
 	virtual uint16 type() { return _type; }
 	virtual const uint8 *getPtr() { return _ptr; }
 	virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
-	virtual void rewind() { _ptr = _data + 2; }
+	virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; }
 protected:
 	uint8 *_data; ///< Raw sound resource data
 	const uint8 *_ptr; ///< Pointer to the current position in the MIDI data
 	uint32 _len; ///< Length of the raw sound resource
 	uint16 _type; ///< Sound resource type
+public:
+	uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second)
+	uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second)
 };
 
 class IIgsSample : public AgiSound {


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