[Scummvm-cvs-logs] SF.net SVN: scummvm: [25229] scummvm/trunk/sound/mods

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Sat Jan 27 22:55:27 CET 2007


Revision: 25229
          http://scummvm.svn.sourceforge.net/scummvm/?rev=25229&view=rev
Author:   drmccoy
Date:     2007-01-27 13:55:26 -0800 (Sat, 27 Jan 2007)

Log Message:
-----------
Implemented some missing effects (arpeggio, sample delay, fine slides, finetune, pattern delay)

Modified Paths:
--------------
    scummvm/trunk/sound/mods/module.cpp
    scummvm/trunk/sound/mods/module.h
    scummvm/trunk/sound/mods/protracker.cpp

Modified: scummvm/trunk/sound/mods/module.cpp
===================================================================
--- scummvm/trunk/sound/mods/module.cpp	2007-01-27 20:34:54 UTC (rev 25228)
+++ scummvm/trunk/sound/mods/module.cpp	2007-01-27 21:55:26 UTC (rev 25229)
@@ -29,6 +29,88 @@
 
 namespace Modules {
 
+const int16 Module::periods[16][60] = {
+	{1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960 , 906,
+	 856 , 808 , 762 , 720 , 678 , 640 , 604 , 570 , 538 , 508 , 480 , 453,
+	 428 , 404 , 381 , 360 , 339 , 320 , 302 , 285 , 269 , 254 , 240 , 226,
+	 214 , 202 , 190 , 180 , 170 , 160 , 151 , 143 , 135 , 127 , 120 , 113,
+	 107 , 101 , 95  , 90  , 85  , 80  , 75  , 71  , 67  , 63  , 60  , 56 },
+	{1700, 1604, 1514, 1430, 1348, 1274, 1202, 1134, 1070, 1010, 954 , 900,
+	 850 , 802 , 757 , 715 , 674 , 637 , 601 , 567 , 535 , 505 , 477 , 450,
+	 425 , 401 , 379 , 357 , 337 , 318 , 300 , 284 , 268 , 253 , 239 , 225,
+	 213 , 201 , 189 , 179 , 169 , 159 , 150 , 142 , 134 , 126 , 119 , 113,
+	 106 , 100 , 94  , 89  , 84  , 79  , 75  , 71  , 67  , 63  , 59  , 56 },
+	{1688, 1592, 1504, 1418, 1340, 1264, 1194, 1126, 1064, 1004, 948 , 894,
+	 844 , 796 , 752 , 709 , 670 , 632 , 597 , 563 , 532 , 502 , 474 , 447,
+	 422 , 398 , 376 , 355 , 335 , 316 , 298 , 282 , 266 , 251 , 237 , 224,
+	 211 , 199 , 188 , 177 , 167 , 158 , 149 , 141 , 133 , 125 , 118 , 112,
+	 105 , 99  , 94  , 88  , 83  , 79  , 74  , 70  , 66  , 62  , 59  , 56 },
+	{1676, 1582, 1492, 1408, 1330, 1256, 1184, 1118, 1056, 996 , 940 , 888,
+	 838 , 791 , 746 , 704 , 665 , 628 , 592 , 559 , 528 , 498 , 470 , 444,
+	 419 , 395 , 373 , 352 , 332 , 314 , 296 , 280 , 264 , 249 , 235 , 222,
+	 209 , 198 , 187 , 176 , 166 , 157 , 148 , 140 , 132 , 125 , 118 , 111,
+	 104 , 99  , 93  , 88  , 83  , 78  , 74  , 70  , 66  , 62  , 59  , 55 },
+	{1664, 1570, 1482, 1398, 1320, 1246, 1176, 1110, 1048, 990 , 934 , 882,
+	 832 , 785 , 741 , 699 , 660 , 623 , 588 , 555 , 524 , 495 , 467 , 441,
+	 416 , 392 , 370 , 350 , 330 , 312 , 294 , 278 , 262 , 247 , 233 , 220,
+	 208 , 196 , 185 , 175 , 165 , 156 , 147 , 139 , 131 , 124 , 117 , 110,
+	 104 , 98  , 92  , 87  , 82  , 78  , 73  , 69  , 65  , 62  , 58  , 55 },
+	{1652, 1558, 1472, 1388, 1310, 1238, 1168, 1102, 1040, 982 , 926 , 874,
+	 826 , 779 , 736 , 694 , 655 , 619 , 584 , 551 , 520 , 491 , 463 , 437,
+	 413 , 390 , 368 , 347 , 328 , 309 , 292 , 276 , 260 , 245 , 232 , 219,
+	 206 , 195 , 184 , 174 , 164 , 155 , 146 , 138 , 130 , 123 , 116 , 109,
+	 103 , 97  , 92  , 87  , 82  , 77  , 73  , 69  , 65  , 61  , 58  , 54 },
+	{1640, 1548, 1460, 1378, 1302, 1228, 1160, 1094, 1032, 974 , 920 , 868,
+	 820 , 774 , 730 , 689 , 651 , 614 , 580 , 547 , 516 , 487 , 460 , 434,
+	 410 , 387 , 365 , 345 , 325 , 307 , 290 , 274 , 258 , 244 , 230 , 217,
+	 205 , 193 , 183 , 172 , 163 , 154 , 145 , 137 , 129 , 122 , 115 , 109,
+	 102 , 96  , 91  , 86  , 81  , 77  , 72  , 68  , 64  , 61  , 57  , 54 },
+	{1628, 1536, 1450, 1368, 1292, 1220, 1150, 1086, 1026, 968 , 914 , 862,
+	 814 , 768 , 725 , 684 , 646 , 610 , 575 , 543 , 513 , 484 , 457 , 431,
+	 407 , 384 , 363 , 342 , 323 , 305 , 288 , 272 , 256 , 242 , 228 , 216,
+	 204 , 192 , 181 , 171 , 161 , 152 , 144 , 136 , 128 , 121 , 114 , 108,
+	 102 , 96  , 90  , 85  , 80  , 76  , 72  , 68  , 64  , 60  , 57  , 54 },
+	{1814, 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960,
+	 907 , 856 , 808 , 762 , 720 , 678 , 640 , 604 , 570 , 538 , 508 , 480,
+	 453 , 428 , 404 , 381 , 360 , 339 , 320 , 302 , 285 , 269 , 254 , 240,
+	 226 , 214 , 202 , 190 , 180 , 170 , 160 , 151 , 143 , 135 , 127 , 120,
+	 113 , 107 , 101 , 95  , 90  , 85  , 80  , 75  , 71  , 67  , 63  , 60 },
+	{1800, 1700, 1604, 1514, 1430, 1350, 1272, 1202, 1134, 1070, 1010, 954,
+	 900 , 850 , 802 , 757 , 715 , 675 , 636 , 601 , 567 , 535 , 505 , 477,
+	 450 , 425 , 401 , 379 , 357 , 337 , 318 , 300 , 284 , 268 , 253 , 238,
+	 225 , 212 , 200 , 189 , 179 , 169 , 159 , 150 , 142 , 134 , 126 , 119,
+	 112 , 106 , 100 , 94  , 89  , 84  , 79  , 75  , 71  , 67  , 63  , 59 },
+	{1788, 1688, 1592, 1504, 1418, 1340, 1264, 1194, 1126, 1064, 1004, 948,
+	 894 , 844 , 796 , 752 , 709 , 670 , 632 , 597 , 563 , 532 , 502 , 474,
+	 447 , 422 , 398 , 376 , 355 , 335 , 316 , 298 , 282 , 266 , 251 , 237,
+	 223 , 211 , 199 , 188 , 177 , 167 , 158 , 149 , 141 , 133 , 125 , 118,
+	 111 , 105 , 99  , 94  , 88  , 83  , 79  , 74  , 70  , 66  , 62  , 59 },
+	{1774, 1676, 1582, 1492, 1408, 1330, 1256, 1184, 1118, 1056, 996 , 940,
+	 887 , 838 , 791 , 746 , 704 , 665 , 628 , 592 , 559 , 528 , 498 , 470,
+	 444 , 419 , 395 , 373 , 352 , 332 , 314 , 296 , 280 , 264 , 249 , 235,
+	 222 , 209 , 198 , 187 , 176 , 166 , 157 , 148 , 140 , 132 , 125 , 118,
+	 111 , 104 , 99  , 93  , 88  , 83  , 78  , 74  , 70  , 66  , 62  , 59 },
+	{1762, 1664, 1570, 1482, 1398, 1320, 1246, 1176, 1110, 1048, 988 , 934,
+	 881 , 832 , 785 , 741 , 699 , 660 , 623 , 588 , 555 , 524 , 494 , 467,
+	 441 , 416 , 392 , 370 , 350 , 330 , 312 , 294 , 278 , 262 , 247 , 233,
+	 220 , 208 , 196 , 185 , 175 , 165 , 156 , 147 , 139 , 131 , 123 , 117,
+	 110 , 104 , 98  , 92  , 87  , 82  , 78  , 73  , 69  , 65  , 61  , 58 },
+	{1750, 1652, 1558, 1472, 1388, 1310, 1238, 1168, 1102, 1040, 982 , 926,
+	 875 , 826 , 779 , 736 , 694 , 655 , 619 , 584 , 551 , 520 , 491 , 463,
+	 437 , 413 , 390 , 368 , 347 , 328 , 309 , 292 , 276 , 260 , 245 , 232,
+	 219 , 206 , 195 , 184 , 174 , 164 , 155 , 146 , 138 , 130 , 123 , 116,
+	 109 , 103 , 97  , 92  , 87  , 82  , 77  , 73  , 69  , 65  , 61  , 58 },
+	{1736, 1640, 1548, 1460, 1378, 1302, 1228, 1160, 1094, 1032, 974 , 920,
+	 868 , 820 , 774 , 730 , 689 , 651 , 614 , 580 , 547 , 516 , 487 , 460,
+	 434 , 410 , 387 , 365 , 345 , 325 , 307 , 290 , 274 , 258 , 244 , 230,
+	 217 , 205 , 193 , 183 , 172 , 163 , 154 , 145 , 137 , 129 , 122 , 115,
+	 108 , 102 , 96  , 91  , 86  , 81  , 77  , 72  , 68  , 64  , 61  , 57 },
+	{1724, 1628, 1536, 1450, 1368, 1292, 1220, 1150, 1086, 1026, 968 , 914,
+	 862 , 814 , 768 , 725 , 684 , 646 , 610 , 575 , 543 , 513 , 484 , 457,
+	 431 , 407 , 384 , 363 , 342 , 323 , 305 , 288 , 272 , 256 , 242 , 228,
+	 216 , 203 , 192 , 181 , 171 , 161 , 152 , 144 , 136 , 128 , 121 , 114,
+	 108 , 101 , 96  , 90  , 85  , 80  , 76  , 72  , 68  , 64  , 60  , 57 }};
+
 bool Module::load(Common::ReadStream &st) {
 	st.read(songname, 20);
 	songname[20] = '\0';
@@ -70,6 +152,7 @@
 				pattern[i][j][k].sample = (note & 0xf0000000) >> 24 | (note & 0x0000f000) >> 12;
 				pattern[i][j][k].period = (note >> 16) & 0xfff;
 				pattern[i][j][k].effect = note & 0xfff;
+				pattern[i][j][k].note = periodToNote((note >> 16) & 0xfff);
 			}
 		}
 	}
@@ -103,4 +186,32 @@
 	}
 }
 
+byte Module::periodToNote(int16 period, byte finetune) {
+	int16 diff1;
+	int16 diff2;
+
+	diff1 = ABS(periods[finetune][0] - period);
+	if (diff1 == 0)
+		return 0;
+
+	for (int i = 1; i < 60; i++) {
+		diff2 = ABS(periods[finetune][i] - period);
+		if (diff2 == 0)
+			return i;
+		else if (diff2 > diff1)
+			return i-1;
+		diff1 = diff2;
+	}
+	return 59;
+}
+
+int16 Module::noteToPeriod(byte note, byte finetune) {
+	if (finetune > 15)
+		finetune = 15;
+	if (note > 59)
+		note = 59;
+
+	return periods[finetune][note];
+}
+
 } // End of namespace Modules

Modified: scummvm/trunk/sound/mods/module.h
===================================================================
--- scummvm/trunk/sound/mods/module.h	2007-01-27 20:34:54 UTC (rev 25228)
+++ scummvm/trunk/sound/mods/module.h	2007-01-27 21:55:26 UTC (rev 25229)
@@ -32,6 +32,7 @@
 
 struct note_t {
 	byte sample;
+	byte note;
 	uint16 period;
 	uint16 effect;
 };
@@ -67,6 +68,11 @@
 	~Module();
 
 	bool load(Common::ReadStream &stream);
+	byte static periodToNote(int16 period, byte finetune = 0);
+	int16 static noteToPeriod(byte note, byte finetune = 0);
+
+private:
+	static const int16 periods[16][60];
 };
 
 } // End of namespace Modules

Modified: scummvm/trunk/sound/mods/protracker.cpp
===================================================================
--- scummvm/trunk/sound/mods/protracker.cpp	2007-01-27 20:34:54 UTC (rev 25228)
+++ scummvm/trunk/sound/mods/protracker.cpp	2007-01-27 21:55:26 UTC (rev 25229)
@@ -41,8 +41,6 @@
 	int _row;
 	int _pos;
 
-	int _patternDelay;
-
 	int _speed;
 	int _bpm;
 
@@ -59,13 +57,23 @@
 	int _patternLoopCount;
 	int _patternLoopRow;
 
+	// For effect 0xEE - Pattern Delay
+	byte _patternDelay;
+
+	static const int16 sinetable[];
+
 	struct {
 		byte sample;
 		uint16 period;
 		double offset;
 
 		byte vol;
+		byte finetune;
 
+		// For effect 0x0 - Arpeggio
+		bool arpeggio;
+		byte arpeggioNotes[3];
+
 		// For effect 0x3 - Porta to note
 		uint16 portaToNote;
 		byte portaToNoteSpeed;
@@ -75,6 +83,10 @@
 		byte vibratoPos;
 		byte vibratoSpeed;
 		byte vibratoDepth;
+
+		// For effect 0xED - Delay sample
+		byte delaySample;
+		byte delaySampleTick;
 	} _track[4];
 
 public:
@@ -84,11 +96,56 @@
 	void startPlay() { _playing = true; _end = false; }
 	void interrupt();
 
+	void doPorta(int track) {
+		if (_track[track].portaToNote && _track[track].portaToNoteSpeed) {
+			if (_track[track].period < _track[track].portaToNote) {
+				_track[track].period += _track[track].portaToNoteSpeed;
+				if (_track[track].period > _track[track].portaToNote)
+					_track[track].period = _track[track].portaToNote;
+			} else if (_track[track].period > _track[track].portaToNote) {
+				_track[track].period -= _track[track].portaToNoteSpeed;
+				if (_track[track].period < _track[track].portaToNote)
+					_track[track].period = _track[track].portaToNote;
+			}
+		}
+	}
+	void doVibrato(int track) {
+		_track[track].vibrato =
+				(_track[track].vibratoDepth * sinetable[_track[track].vibratoPos]) / 128;
+		_track[track].vibratoPos += _track[track].vibratoSpeed;
+		_track[track].vibratoPos %= 64;
+	}
+	void doVolSlide(int track, byte ex, byte ey) {
+		int vol = _track[track].vol;
+		if (ex == 0)
+			vol -= ey;
+		else if (ey == 0)
+			vol += ex;
+
+		if (vol < 0)
+			vol = 0;
+		else if (vol > 64)
+			vol = 64;
+
+		_track[track].vol = vol;
+	}
+
 	void updateRow();
 	void updateEffects();
 
 };
 
+const int16 ProtrackerStream::sinetable[64] = {
+		 0,   24,   49,   74,   97,  120,  141,  161,
+	 180,  197,  212,  224,  235,  244,  250,  253,
+	 255,  253,  250,  244,  235,  224,  212,  197,
+	 180,  161,  141,  120,   97,   74,   49,   24,
+		 0,  -24,  -49,  -74,  -97, -120, -141, -161,
+	-180, -197, -212, -224, -235, -244, -250, -253,
+	-255, -253, -250, -244, -235, -224, -212, -197,
+	-180, -161, -141, -120,  -97,  -74,  -49,  -24
+};
+
 ProtrackerStream::ProtrackerStream(Common::ReadStream *stream, int rate, bool stereo) :
 		Paula(stereo, rate, rate/50) {
 	_module = new Module();
@@ -111,6 +168,8 @@
 		_track[t].period = 0;
 		_track[t].offset = 0.0;
 		_track[t].vibrato = 0;
+		_track[t].delaySampleTick = 0;
+		_track[t].arpeggio = false;
 	}	
 
 	startPlay();
@@ -118,7 +177,9 @@
 
 void ProtrackerStream::updateRow() {
 	for (int track = 0; track < 4; track++) {
+		_track[track].arpeggio = false;
 		_track[track].vibrato = 0;
+		_track[track].delaySampleTick = 0;
 		note_t note =
 		    _module->pattern[_module->songpos[_pos]][_row][track];
 
@@ -129,21 +190,36 @@
 				_track[track].vibratoPos = 0;
 			}
 			_track[track].sample = note.sample;
+			_track[track].finetune = _module->sample[note.sample - 1].finetune;
 			_track[track].vol = _module->sample[note.sample - 1].vol;
 		}
+
 		if (note.period) {
 			if (effect != 3 && effect != 5) {
-				_track[track].period = note.period;
+				if (_track[track].finetune)
+					_track[track].period = _module->noteToPeriod(note.note, _track[track].finetune);
+				else
+					_track[track].period = note.period;
 				_track[track].offset = 0.0;
 			}
 		}
 
 		int exy = note.effect & 0xff;
+		if (exy);
 		int ex = (note.effect >> 4) & 0xf;
 		int ey = note.effect & 0xf;
 
+		int vol;
 		switch (effect) {
 		case 0x0:
+			if (ex || ey) {
+				_track[track].arpeggio = true;
+				if (note.period) {
+					_track[track].arpeggioNotes[0] = note.note;
+					_track[track].arpeggioNotes[1] = note.note + ex;
+					_track[track].arpeggioNotes[2] = note.note + ey;
+				}
+			}
 			break;
 		case 0x1:
 			break;
@@ -152,7 +228,6 @@
 		case 0x3:
 			if (note.period)
 				_track[track].portaToNote = note.period;
-
 			if (exy)
 				_track[track].portaToNoteSpeed = exy;
 			break;
@@ -163,7 +238,19 @@
 			}
 			break;
 		case 0x5:
+			doPorta(track);
+			doVolSlide(track, ex, ey);
 			break;
+		case 0x6:
+			doVibrato(track);
+			doVolSlide(track, ex, ey);
+			break;
+		case 0x9: // Set sample offset
+			if (exy) {
+				_track[track].offset = exy * 256;
+				_voice[track].offset = _track[track].offset;
+			}
+			break;
 		case 0xA:
 			break;
 		case 0xB:
@@ -180,6 +267,24 @@
 
 		case 0xE:
 			switch (ex) {
+			case 0x0: // Switch filters off
+				break;
+			case 0x1: // Fine slide up
+				_track[track].period -= exy;
+				break;
+			case 0x2: // Fine slide down
+				_track[track].period += exy;
+				break;
+			case 0x5: // Set finetune
+				_track[track].finetune = ey;
+				_module->sample[_track[track].sample].finetune = ey;
+				if (note.period) {
+					if (ey)
+						_track[track].period = _module->noteToPeriod(note.note, ey);
+					else
+						_track[track].period = note.period;
+				}
+				break;
 			case 0x6:
 				if (ey == 0) {
 					_patternLoopRow = _row;
@@ -193,6 +298,27 @@
 				break;
 			case 0x9:
 				break;	// Retrigger note
+			case 0xA: // Fine volume slide up
+				vol = _track[track].vol + ey;
+				if (vol > 64)
+					vol = 64;
+				_track[track].vol = vol;
+				break;
+			case 0xB: // Fine volume slide down
+				vol = _track[track].vol - ey;
+				if (vol < 0)
+					vol = 0;
+				_track[track].vol = vol;
+				break;
+			case 0xD: // Delay sample
+				_track[track].delaySampleTick = ey;
+				_track[track].delaySample = _track[track].sample;
+				_track[track].sample = 0;
+				_track[track].vol = 0;
+				break;
+			case 0xE: // Pattern delay
+				_patternDelay = ey;
+				break;
 			default:
 				warning("Unimplemented effect %X\n", note.effect);
 			}
@@ -213,18 +339,6 @@
 }
 
 void ProtrackerStream::updateEffects() {
-
-	static const int16 sinetable[64] = {
-		   0,   24,   49,   74,   97,  120,  141,  161,
-		 180,  197,  212,  224,  235,  244,  250,  253,
-		 255,  253,  250,  244,  235,  224,  212,  197,
-		 180,  161,  141,  120,   97,   74,   49,   24,
-		   0,  -24,  -49,  -74,  -97, -120, -141, -161,
-		-180, -197, -212, -224, -235, -244, -250, -253,
-		-255, -253, -250, -244, -235, -224, -212, -197,
-		-180, -161, -141, -120,  -97,  -74,  -49,  -24
-	};
-
 	for (int track = 0; track < 4; track++) {
 		_track[track].vibrato = 0;
 
@@ -237,9 +351,18 @@
 		int ex = (note.effect >> 4) & 0xf;
 		int ey = (note.effect) & 0xf;
 
-		int vol;
 		switch (effect) {
 		case 0x0:
+			if (ex || ey) {
+				if (_tick == 1)
+					_track[track].period =
+						_module->noteToPeriod(_track[track].arpeggioNotes[0],
+								_track[track].finetune);
+				else
+					_track[track].period =
+						_module->noteToPeriod(_track[track].arpeggioNotes[_tick % 3],
+								_track[track].finetune);
+			}
 			break;
 		case 0x1:
 			_track[track].period -= exy;
@@ -248,89 +371,21 @@
 			_track[track].period += exy;
 			break;
 		case 0x3:
-			if (_track[track].portaToNote && _track[track].portaToNoteSpeed) {
-				if (_track[track].period < _track[track].portaToNote) {
-					_track[track].period += _track[track].portaToNoteSpeed;
-					if (_track[track].period > _track[track].portaToNote)
-						_track[track].period = _track[track].portaToNote;
-				} else if (_track[track].period > _track[track].portaToNote) {
-					_track[track].period -= _track[track].portaToNoteSpeed;
-					if (_track[track].period < _track[track].portaToNote)
-						_track[track].period = _track[track].portaToNote;
-				}
-			}
+			doPorta(track);
 			break;
 		case 0x4:
-			_track[track].vibrato =
-			    (_track[track].vibratoDepth * sinetable[_track[track].vibratoPos]) / 128;
-			_track[track].vibratoPos += _track[track].vibratoSpeed;
-			_track[track].vibratoPos %= 64;
+			doVibrato(track);
 			break;
-
 		case 0x5:
-			if (_track[track].portaToNote
-			    && _track[track].portaToNoteSpeed) {
-				if (_track[track].period < _track[track].portaToNote) {
-					_track[track].period += _track[track].portaToNoteSpeed;
-					if (_track[track].period > _track[track].portaToNote)
-						_track[track].period = _track[track].portaToNote;
-				} else if (_track[track].period > _track[track].portaToNote) {
-					_track[track].period -= _track[track].portaToNoteSpeed;
-					if (_track[track].period < _track[track].portaToNote)
-						_track[track].period = _track[track].portaToNote;
-				}
-			}
-
-			vol = _track[track].vol;
-			if (ex == 0)
-				vol -= ey;
-			else if (ey == 0)
-				vol += ex;
-
-			if (vol < 0)
-				vol = 0;
-			else if (vol > 64)
-				vol = 64;
-
-			_track[track].vol = vol;
-
+			doPorta(track);
+			doVolSlide(track, ex, ey);
 			break;
-
 		case 0x6:
-			_track[track].vibrato =
-			    (_track[track].vibratoDepth * sinetable[_track[track].vibratoPos]) / 128;
-			_track[track].vibratoPos += _track[track].vibratoSpeed;
-			_track[track].vibratoPos %= 64;
-
-			vol = _track[track].vol;
-			if (ex == 0)
-				vol -= ey;
-			else if (ey == 0)
-				vol += ex;
-
-			if (vol < 0)
-				vol = 0;
-			else if (vol > 64)
-				vol = 64;
-
-			_track[track].vol = vol;
-
+			doVibrato(track);
+			doVolSlide(track, ex, ey);
 			break;
-
 		case 0xA:
-			vol = _track[track].vol;
-			if (ex == 0)
-				vol -= ey;
-			else if (ey == 0)
-				vol += ex;
-
-			if (vol < 0)
-				vol = 0;
-			else if (vol > 64)
-				vol = 64;
-
-			_track[track].vol = vol;
-
+			doVolSlide(track, ex, ey);
 			break;
 
 		case 0xE:
@@ -341,6 +396,14 @@
 				if (ey && _tick % ey == 0)
 					_track[track].offset = 0.0;
 				break;
+			case 0xD: // Delay sample
+				if (_tick == _track[track].delaySampleTick) {
+					_track[track].sample = _track[track].delaySample;
+					_track[track].offset = 0.0;
+					if (_track[track].sample)
+						_track[track].vol = _module->sample[_track[track].sample - 1].vol;
+				}
+				break;
 			}
 			break;
 		}
@@ -354,6 +417,10 @@
 		_track[track].offset = _voice[track].offset;
 
 	if (_tick == 0) {
+		if (_track[track].arpeggio) {
+			_track[track].period = _module->noteToPeriod(_track[track].arpeggioNotes[0],
+					_track[track].finetune);
+		}
 		if (_hasJumpToPattern) {
 			_hasJumpToPattern = false;
 			_pos = _jumpToPattern;
@@ -373,17 +440,15 @@
 			_patternLoopRow = 0;
 		}
 
-		if (_patternDelay == 0) {
-			updateRow();
-		} else {
-			_patternDelay--;
-		}
+		updateRow();
 	} else
 		updateEffects();
 
-	_tick = (_tick + 1) % _speed;
-	if (_tick == 0)
+	_tick = (_tick + 1) % (_speed + _patternDelay * _speed);
+	if (_tick == 0) {
 		_row++;
+		_patternDelay = 0;
+	}
 
 	for (track = 0; track < 4; track++) {
 		_voice[track].period = _track[track].period + _track[track].vibrato;


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