[Scummvm-cvs-logs] SF.net SVN: scummvm:[41633] scummvm/trunk/engines/gob

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Thu Jun 18 15:27:35 CEST 2009


Revision: 41633
          http://scummvm.svn.sourceforge.net/scummvm/?rev=41633&view=rev
Author:   drmccoy
Date:     2009-06-18 13:27:35 +0000 (Thu, 18 Jun 2009)

Log Message:
-----------
Splitting an ADLPlayer and MDYPlayer from the AdLib class

Modified Paths:
--------------
    scummvm/trunk/engines/gob/inter_fascin.cpp
    scummvm/trunk/engines/gob/inter_v1.cpp
    scummvm/trunk/engines/gob/sound/adlib.cpp
    scummvm/trunk/engines/gob/sound/adlib.h
    scummvm/trunk/engines/gob/sound/sound.cpp
    scummvm/trunk/engines/gob/sound/sound.h

Modified: scummvm/trunk/engines/gob/inter_fascin.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_fascin.cpp	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/inter_fascin.cpp	2009-06-18 13:27:35 UTC (rev 41633)
@@ -129,8 +129,8 @@
 }
 
 void Inter_Fascination::oFascin_geUnknown2(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("extasy.tbr");
-	_vm->_sound->adlibLoadMdy("extasy.mdy");
+	_vm->_sound->adlibLoadTBR("extasy.tbr");
+	_vm->_sound->adlibLoadMDY("extasy.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown3(OpGobParams &params) {
@@ -146,33 +146,33 @@
 }
 
 void Inter_Fascination::oFascin_geUnknown6(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("music1.tbr");
-	_vm->_sound->adlibLoadMdy("music1.mdy");
+	_vm->_sound->adlibLoadTBR("music1.tbr");
+	_vm->_sound->adlibLoadMDY("music1.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown7(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("music2.tbr");
-	_vm->_sound->adlibLoadMdy("music2.mdy");
+	_vm->_sound->adlibLoadTBR("music2.tbr");
+	_vm->_sound->adlibLoadMDY("music2.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown8(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("music3.tbr");
-	_vm->_sound->adlibLoadMdy("music3.mdy");
+	_vm->_sound->adlibLoadTBR("music3.tbr");
+	_vm->_sound->adlibLoadMDY("music3.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown9(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("batt1.tbr");
-	_vm->_sound->adlibLoadMdy("batt1.mdy");
+	_vm->_sound->adlibLoadTBR("batt1.tbr");
+	_vm->_sound->adlibLoadMDY("batt1.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown10(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("batt2.tbr");
-	_vm->_sound->adlibLoadMdy("batt2.mdy");
+	_vm->_sound->adlibLoadTBR("batt2.tbr");
+	_vm->_sound->adlibLoadMDY("batt2.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown11(OpGobParams &params) {
-	_vm->_sound->adlibLoadTbr("batt3.tbr");
-	_vm->_sound->adlibLoadMdy("batt3.mdy");
+	_vm->_sound->adlibLoadTBR("batt3.tbr");
+	_vm->_sound->adlibLoadMDY("batt3.mdy");
 }
 
 void Inter_Fascination::oFascin_geUnknown1000(OpGobParams &params) {

Modified: scummvm/trunk/engines/gob/inter_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v1.cpp	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/inter_v1.cpp	2009-06-18 13:27:35 UTC (rev 41633)
@@ -1520,7 +1520,7 @@
 	}
 
 	if (sample->getType() == SOUND_ADL) {
-		_vm->_sound->adlibLoad(sample->getData(), sample->size(), index);
+		_vm->_sound->adlibLoadADL(sample->getData(), sample->size(), index);
 		_vm->_sound->adlibSetRepeating(repCount - 1);
 		_vm->_sound->adlibPlay();
 	} else {

Modified: scummvm/trunk/engines/gob/sound/adlib.cpp
===================================================================
--- scummvm/trunk/engines/gob/sound/adlib.cpp	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/sound/adlib.cpp	2009-06-18 13:27:35 UTC (rev 41633)
@@ -39,21 +39,34 @@
 };
 
 AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {
+	init();
+}
+
+AdLib::~AdLib() {
+	Common::StackLock slock(_mutex);
+
+	_mixer->stopHandle(_handle);
+	OPLDestroy(_opl);
+	if (_data && _freeData)
+		delete[] _data;
+}
+
+void AdLib::init() {
 	_index = -1;
 	_data = 0;
 	_playPos = 0;
 	_dataSize = 0;
 
 	_rate = _mixer->getOutputRate();
+
 	_opl = makeAdlibOPL(_rate);
 
 	_first = true;
 	_ended = false;
 	_playing = false;
-	_needFree = false;
-	_mdySong = false;
+
+	_freeData = false;
 	
-	_soundMode = 0;
 	_repCount = -1;
 	_samplesTillPoll = 0;
 
@@ -65,15 +78,6 @@
 			this, -1, 255, 0, false, true);
 }
 
-AdLib::~AdLib() {
-	Common::StackLock slock(_mutex);
-
-	_mixer->stopHandle(_handle);
-	OPLDestroy(_opl);
-	if (_data && _needFree)
-		delete[] _data;
-}
-
 int AdLib::readBuffer(int16 *buffer, const int numSamples) {
 	Common::StackLock slock(_mutex);
 	int samples;
@@ -109,25 +113,17 @@
 	if (_ended) {
 		_first = true;
 		_ended = false;
-		if (_mdySong)
-			_playPos = _data;
-		else
-			_playPos = _data + 3 + (_data[1] + 1) * 0x38;
 
+		rewind();
+
 		_samplesTillPoll = 0;
 		if (_repCount == -1) {
 			reset();
-			if (_mdySong)
-				setVoicesTbr();
-			else
-				setVoices();
+			setVoices();
 		} else if (_repCount > 0) {
 			_repCount--;
 			reset();
-			if (_mdySong)
-				setVoicesTbr();
-			else
-				setVoices();
+			setVoices();
 		}
 		else
 			_playing = false;
@@ -182,126 +178,8 @@
 
 	// Authorize the control of the waveformes
 	writeOPL(0x01, 0x20);
-
-// _soundMode 1 : Percussive mode. 
-	if (_soundMode == 1) { 
-		writeOPL(0xA6, 0);
-		writeOPL(0xB6, 0);
-		writeOPL(0xA7, 0);
-		writeOPL(0xB7, 0);
-		writeOPL(0xA8, 0);
-		writeOPL(0xB8, 0);
-
-// TODO set the correct frequency for the last 4 percussive voices
-
-	}
 }
 
-void AdLib::setVoices() {
-	// Definitions of the 9 instruments
-	for (int i = 0; i < 9; i++)
-		setVoice(i, i, true);
-}
-
-void AdLib::setVoice(byte voice, byte instr, bool set) {
-	int i;
-	int j;
-	uint16 strct[27];
-	byte channel;
-	byte *dataPtr;
-
-	// i = 0 :  0  1  2  3  4  5  6  7  8  9 10 11 12 26
-	// i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
-	for (i = 0; i < 2; i++) {
-		dataPtr = _data + 3 + instr * 0x38 + i * 0x1A;
-		for (j = 0; j < 27; j++) {
-			strct[j] = READ_LE_UINT16(dataPtr);
-			dataPtr += 2;
-		}
-		channel = _operators[voice] + i * 3;
-		writeOPL(0xBD, 0x00);
-		writeOPL(0x08, 0x00);
-		writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
-		if (!i)
-			writeOPL(0xC0 | voice,
-					((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
-		writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
-		writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
-		writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
-			((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
-			((strct[11] & 1) << 4) |  (strct[1] & 0xF));
-		if (!i)
-			writeOPL(0xE0 | channel, (strct[26] & 3));
-		else
-			writeOPL(0xE0 | channel, (strct[14] & 3));
-		if (i && set)
-			writeOPL(0x40 | channel, 0);
-	}
-}
-
-void AdLib::setVoicesTbr() {
-	int i;
-	byte *timbrePtr;
-
-	timbrePtr = _timbres;
-	debugC(6, kDebugSound, "TBR version: %X.%X", timbrePtr[0], timbrePtr[1]);
-	timbrePtr += 2;
-
-	_tbrCount = READ_LE_UINT16(timbrePtr);
-	debugC(6, kDebugSound, "Timbres counter: %d", _tbrCount);
-	timbrePtr += 2;
-	_tbrStart = READ_LE_UINT16(timbrePtr);
- 
-	timbrePtr += 2;
-	for (i = 0; i < _tbrCount ; i++)
-	{
-		setVoiceTbr (i, i, true);
-	}
-}
-
-void AdLib::setVoiceTbr (byte voice, byte instr, bool set) {
-	int i;
-	int j;
-	uint16 strct[27];
-	byte channel;
-	byte *timbrePtr;
-	char timbreName[10];
-
-	timbreName[9] = '\0';
-	for (j = 0; j < 9; j++)
-		timbreName[j] = _timbres[6 + j + (instr * 9)]; 
-	debugC(6, kDebugSound, "Loading timbre %s", timbreName);
-	
-	// i = 0 :  0  1  2  3  4  5  6  7  8  9 10 11 12 26
-	// i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
-	for (i = 0; i < 2; i++) {
-		timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A;
-		for (j = 0; j < 27; j++) {
-			strct[j] = READ_LE_UINT16(timbrePtr);
-			timbrePtr += 2;
-		}
-		channel = _operators[voice] + i * 3;
-		writeOPL(0xBD, 0x00);
-		writeOPL(0x08, 0x00);
-		writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
-		if (!i)
-			writeOPL(0xC0 | voice,
-					((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
-		writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
-		writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
-		writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
-			((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
-			((strct[11] & 1) << 4) |  (strct[1] & 0xF));
-		if (!i)
-			writeOPL(0xE0 | channel, (strct[26] & 3));
-		else {
-			writeOPL(0xE0 | channel, (strct[14] & 3));
-			writeOPL(0x40 | channel, 0);
-		}
-	}
-}
-
-
 void AdLib::setKey(byte voice, byte note, bool on, bool spec) {
 	short freq = 0;
 	short octa = 0;
@@ -374,206 +252,56 @@
 }
 
 void AdLib::pollMusic() {
-	unsigned char instr;
-	byte channel;
-	byte note;
-	byte volume;
-	uint16 tempo;
-
-	uint8 i, tempoMult, tempoFrac, ctrlByte1, ctrlByte2, timbre;
-
 	if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) {
 		_ended = true;
 		return;
 	}
 
-	if (_mdySong)
-	{
-		if (_first) {
-			for (i = 0; i < 11; i ++)
-				setVolume(i, 0);
+	interpret();
+}
 
-//	TODO : Set pitch range
+void AdLib::unload() {
+	_playing = false;
+	_index = -1;
 
-			_tempo = _basicTempo;
-			_wait = *(_playPos++);
-			_first = false;
-		}
-		do {
-			instr = *_playPos;
-//			printf("instr 0x%X\n", instr);
-			switch(instr) {
-			case 0xF8:
-				_wait = *(_playPos++);
-				break;
-			case 0xFC:
-				_ended = true;
-				_samplesTillPoll = 0;
-				return;
-			case 0xF0:
-				_playPos++;
-				ctrlByte1 = *(_playPos++);
-				ctrlByte2 = *(_playPos++);
-				if (ctrlByte1 != 0x7F || ctrlByte2 != 0) {
-					_playPos -= 2;
-					while (*(_playPos++) != 0xF7);
-				} else {
-					tempoMult = *(_playPos++);
-					tempoFrac = *(_playPos++);
-					_tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7);
-					_playPos++;      
-				}
-				_wait = *(_playPos++);
-				break;
-			default:
-				if (instr >= 0x80) {
-					_playPos++;
-				}
-				channel = (int)(instr & 0x0f);
+	if (_data && _freeData)
+		delete[] _data;
 
-				switch(instr & 0xf0) {
-				case 0x90:
-					note = *(_playPos++);
-					volume = *(_playPos++);
-					_pollNotes[channel] = note;
-					setVolume(channel, volume);
-					setKey(channel, note, true, false);
-					break;
-				case 0x80:
-					_playPos += 2;
-					note = _pollNotes[channel];
-					setKey(channel, note, false, false);
-					break;
-				case 0xA0:
-					setVolume(channel, *(_playPos++));
-					break;
-				case 0xC0:
-					timbre = *(_playPos++);
-					setVoiceTbr(channel, timbre, false);
-					break;
-				case 0xE0:
-					warning("Pitch bend not yet implemented\n");
-    	
-					note = *(_playPos)++;
-					note += (unsigned)(*(_playPos++)) << 7;
+	_freeData = false;
+}
 
-					setKey(channel, note, _notOn[channel], true);
+bool AdLib::isPlaying() const {
+	return _playing;
+}
 
-					break;
-				case 0xB0:
-					_playPos += 2;
-					break;
-				case 0xD0:
-					_playPos++;
-					break;
-				default:
-					warning("Bad MIDI instr byte: 0%X", instr);
-					while ((*_playPos) < 0x80)
-						_playPos++;
-					if (*_playPos != 0xF8)
-						_playPos--;
-					break;
-				} //switch instr & 0xF0
-				_wait = *(_playPos++);
-				break;
-			} //switch instr
-		} while (_wait == 0);
+bool AdLib::getRepeating() const {
+	return _repCount != 0;
+}
 
-		if (_wait == 0xF8) {
-			_wait = 0xF0;
-			if (*_playPos != 0xF8)
-				_wait += *(_playPos++);
-		}
-//		_playPos++;
-		_samplesTillPoll = _wait * (_rate / 1000);
-	} else {
-		// First tempo, we'll ignore it...
-		if (_first) {
-			tempo = *(_playPos++);
-			// Tempo on 2 bytes
-			if (tempo & 0x80)
-				tempo = ((tempo & 3) << 8) | *(_playPos++);
-		}
-		_first = false;
-  	
-		// Instruction
-		instr = *(_playPos++);
-		channel = instr & 0x0F;
-  	
-		switch (instr & 0xF0) {
-			// Note on + Volume
-			case 0x00:
-				note = *(_playPos++);
-				_pollNotes[channel] = note;
-				setVolume(channel, *(_playPos++));
-				setKey(channel, note, true, false);
-				break;
-			// Note on
-			case 0x90:
-				note = *(_playPos++);
-				_pollNotes[channel] = note;
-				setKey(channel, note, true, false);
-				break;
-			// Last note off
-			case 0x80:
-				note = _pollNotes[channel];
-				setKey(channel, note, false, false);
-				break;
-			// Frequency on/off
-			case 0xA0:
-				note = *(_playPos++);
-				setKey(channel, note, _notOn[channel], true);
-				break;
-			// Volume
-			case 0xB0:
-				volume = *(_playPos++);
-				setVolume(channel, volume);
-				break;
-			// Program change
-			case 0xC0:
-				setVoice(channel, *(_playPos++), false);
-				break;
-			// Special
-			case 0xF0:
-				switch (instr & 0x0F) {
-				case 0xF: // End instruction
-					_ended = true;
-					_samplesTillPoll = 0;
-					return;
-				default:
-					warning("Unknown special command in ADL, stopping playback: %X",
-							instr & 0x0F);
-					_repCount = 0;
-					_ended = true;
-					break;
-				}
-				break;
-			default:
-				warning("Unknown command in ADL, stopping playback: %X",
-						instr & 0xF0);
-				_repCount = 0;
-				_ended = true;
-				break;
-		}
-  	
-		// Temporization
-		tempo = *(_playPos++);
-		// End tempo
-		if (tempo == 0xFF) {
-			_ended = true;
-			return;
-		}
-		// Tempo on 2 bytes
-		if (tempo & 0x80)
-			tempo = ((tempo & 3) << 8) | *(_playPos++);
-		if (!tempo)
-			tempo ++;
-  	
-		_samplesTillPoll = tempo * (_rate / 1000);
-	}
+void AdLib::setRepeating(int32 repCount) {
+	_repCount = repCount;
 }
 
-bool AdLib::load(const char *fileName) {
+int AdLib::getIndex() const {
+	return _index;
+}
+
+void AdLib::startPlay() {
+	if (_data) _playing = true;
+}
+
+void AdLib::stopPlay() {
+	Common::StackLock slock(_mutex);
+	_playing = false;
+}
+
+ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
+}
+
+ADLPlayer::~ADLPlayer() {
+}
+
+bool ADLPlayer::load(const char *fileName) {
 	Common::File song;
 
 	unload();
@@ -581,9 +309,7 @@
 	if (!song.isOpen())
 		return false;
 
-	_soundMode = 0;
-
-	_needFree = true;
+	_freeData = true;
 	_dataSize = song.size();
 	_data = new byte[_dataSize];
 	song.read(_data, _dataSize);
@@ -596,12 +322,10 @@
 	return true;
 }
 
-bool AdLib::load(byte *data, uint32 size, int index) {
+bool ADLPlayer::load(byte *data, uint32 size, int index) {
 	unload();
 	_repCount = 0;
 
-	_soundMode = 0;
-
 	_dataSize = size;
 	_data = data;
 	_index = index;
@@ -613,7 +337,168 @@
 	return true;
 }
 
-bool AdLib::loadMdy(const char *fileName) {
+void ADLPlayer::unload() {
+	AdLib::unload();
+}
+
+void ADLPlayer::interpret() {
+	unsigned char instr;
+	byte channel;
+	byte note;
+	byte volume;
+	uint16 tempo;
+
+	// First tempo, we'll ignore it...
+	if (_first) {
+		tempo = *(_playPos++);
+		// Tempo on 2 bytes
+		if (tempo & 0x80)
+			tempo = ((tempo & 3) << 8) | *(_playPos++);
+	}
+	_first = false;
+	
+	// Instruction
+	instr = *(_playPos++);
+	channel = instr & 0x0F;
+	
+	switch (instr & 0xF0) {
+		// Note on + Volume
+		case 0x00:
+			note = *(_playPos++);
+			_pollNotes[channel] = note;
+			setVolume(channel, *(_playPos++));
+			setKey(channel, note, true, false);
+			break;
+		// Note on
+		case 0x90:
+			note = *(_playPos++);
+			_pollNotes[channel] = note;
+			setKey(channel, note, true, false);
+			break;
+		// Last note off
+		case 0x80:
+			note = _pollNotes[channel];
+			setKey(channel, note, false, false);
+			break;
+		// Frequency on/off
+		case 0xA0:
+			note = *(_playPos++);
+			setKey(channel, note, _notOn[channel], true);
+			break;
+		// Volume
+		case 0xB0:
+			volume = *(_playPos++);
+			setVolume(channel, volume);
+			break;
+		// Program change
+		case 0xC0:
+			setVoice(channel, *(_playPos++), false);
+			break;
+		// Special
+		case 0xF0:
+			switch (instr & 0x0F) {
+			case 0xF: // End instruction
+				_ended = true;
+				_samplesTillPoll = 0;
+				return;
+			default:
+				warning("Unknown special command in ADL, stopping playback: %X",
+						instr & 0x0F);
+				_repCount = 0;
+				_ended = true;
+				break;
+			}
+			break;
+		default:
+			warning("Unknown command in ADL, stopping playback: %X",
+					instr & 0xF0);
+			_repCount = 0;
+			_ended = true;
+			break;
+	}
+	
+	// Temporization
+	tempo = *(_playPos++);
+	// End tempo
+	if (tempo == 0xFF) {
+		_ended = true;
+		return;
+	}
+	// Tempo on 2 bytes
+	if (tempo & 0x80)
+		tempo = ((tempo & 3) << 8) | *(_playPos++);
+	if (!tempo)
+		tempo ++;
+	
+	_samplesTillPoll = tempo * (_rate / 1000);
+}
+
+void ADLPlayer::reset() {
+	AdLib::reset();
+}
+
+void ADLPlayer::rewind() {
+	_playPos = _data + 3 + (_data[1] + 1) * 0x38;
+}
+
+void ADLPlayer::setVoices() {
+	// Definitions of the 9 instruments
+	for (int i = 0; i < 9; i++)
+		setVoice(i, i, true);
+}
+
+void ADLPlayer::setVoice(byte voice, byte instr, bool set) {
+	uint16 strct[27];
+	byte channel;
+	byte *dataPtr;
+
+	// i = 0 :  0  1  2  3  4  5  6  7  8  9 10 11 12 26
+	// i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
+	for (int i = 0; i < 2; i++) {
+		dataPtr = _data + 3 + instr * 0x38 + i * 0x1A;
+		for (int j = 0; j < 27; j++) {
+			strct[j] = READ_LE_UINT16(dataPtr);
+			dataPtr += 2;
+		}
+		channel = _operators[voice] + i * 3;
+		writeOPL(0xBD, 0x00);
+		writeOPL(0x08, 0x00);
+		writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
+		if (!i)
+			writeOPL(0xC0 | voice,
+					((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
+		writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
+		writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
+		writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
+			((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
+			((strct[11] & 1) << 4) |  (strct[1] & 0xF));
+		if (!i)
+			writeOPL(0xE0 | channel, (strct[26] & 3));
+		else
+			writeOPL(0xE0 | channel, (strct[14] & 3));
+		if (i && set)
+			writeOPL(0x40 | channel, 0);
+	}
+}
+
+
+MDYPlayer::MDYPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
+	init();
+}
+
+MDYPlayer::~MDYPlayer() {
+}
+
+void MDYPlayer::init() {
+	_soundMode = 0;
+
+	_timbres = 0;
+	_tbrCount = 0;
+	_tbrStart = 0;
+	_timbresSize = 0;
+}
+
+bool MDYPlayer::loadMDY(const char *fileName) {
 	Common::File song;
 	byte mdyHeader[70];
 
@@ -622,8 +507,7 @@
 	if (!song.isOpen())
 		return false;
 
-	_needFree = true;
-	_mdySong = true;
+	_freeData = true;
 
 	song.read(mdyHeader, 70);
 
@@ -652,7 +536,7 @@
 	return true;
 }
 
-bool AdLib::loadTbr(const char *fileName) {
+bool MDYPlayer::loadTBR(const char *fileName) {
 	Common::File timbres;
 
 	unload();
@@ -666,44 +550,203 @@
 	timbres.close();
 
 	reset();
-	setVoicesTbr();
+	setVoices();
 
 	return true;
 }
 
-void AdLib::unload() {
-	_playing = false;
-	_index = -1;
+void MDYPlayer::unload() {
+	AdLib::unload();
 
-	if (_data && _needFree)
-		delete[] _data;
+	delete[] _timbres;
 
-	_needFree = false;
+	_timbres = 0;
+	_timbresSize = 0;
 }
 
-bool AdLib::isPlaying() const {
-	return _playing;
-}
+void MDYPlayer::interpret() {
+	unsigned char instr;
+	byte channel;
+	byte note;
+	byte volume;
+	uint8 tempoMult, tempoFrac;
+	uint8 ctrlByte1, ctrlByte2;
+	uint8 timbre;	
 
-bool AdLib::getRepeating() const {
-	return _repCount != 0;
+	if (_first) {
+		for (int i = 0; i < 11; i ++)
+			setVolume(i, 0);
+
+//	TODO : Set pitch range
+
+		_tempo = _basicTempo;
+		_wait = *(_playPos++);
+		_first = false;
+	}
+	do {
+		instr = *_playPos;
+//			printf("instr 0x%X\n", instr);
+		switch(instr) {
+		case 0xF8:
+			_wait = *(_playPos++);
+			break;
+		case 0xFC:
+			_ended = true;
+			_samplesTillPoll = 0;
+			return;
+		case 0xF0:
+			_playPos++;
+			ctrlByte1 = *(_playPos++);
+			ctrlByte2 = *(_playPos++);
+			if (ctrlByte1 != 0x7F || ctrlByte2 != 0) {
+				_playPos -= 2;
+				while (*(_playPos++) != 0xF7);
+			} else {
+				tempoMult = *(_playPos++);
+				tempoFrac = *(_playPos++);
+				_tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7);
+				_playPos++;      
+			}
+			_wait = *(_playPos++);
+			break;
+		default:
+			if (instr >= 0x80) {
+				_playPos++;
+			}
+			channel = (int)(instr & 0x0f);
+
+			switch(instr & 0xf0) {
+			case 0x90:
+				note = *(_playPos++);
+				volume = *(_playPos++);
+				_pollNotes[channel] = note;
+				setVolume(channel, volume);
+				setKey(channel, note, true, false);
+				break;
+			case 0x80:
+				_playPos += 2;
+				note = _pollNotes[channel];
+				setKey(channel, note, false, false);
+				break;
+			case 0xA0:
+				setVolume(channel, *(_playPos++));
+				break;
+			case 0xC0:
+				timbre = *(_playPos++);
+				setVoice(channel, timbre, false);
+				break;
+			case 0xE0:
+				warning("Pitch bend not yet implemented\n");
+		
+				note = *(_playPos)++;
+				note += (unsigned)(*(_playPos++)) << 7;
+
+				setKey(channel, note, _notOn[channel], true);
+
+				break;
+			case 0xB0:
+				_playPos += 2;
+				break;
+			case 0xD0:
+				_playPos++;
+				break;
+			default:
+				warning("Bad MIDI instr byte: 0%X", instr);
+				while ((*_playPos) < 0x80)
+					_playPos++;
+				if (*_playPos != 0xF8)
+					_playPos--;
+				break;
+			} //switch instr & 0xF0
+			_wait = *(_playPos++);
+			break;
+		} //switch instr
+	} while (_wait == 0);
+
+	if (_wait == 0xF8) {
+		_wait = 0xF0;
+		if (*_playPos != 0xF8)
+			_wait += *(_playPos++);
+	}
+//		_playPos++;
+	_samplesTillPoll = _wait * (_rate / 1000);
 }
 
-void AdLib::setRepeating(int32 repCount) {
-	_repCount = repCount;
+void MDYPlayer::reset() {
+	AdLib::reset();
+
+// _soundMode 1 : Percussive mode. 
+	if (_soundMode == 1) { 
+		writeOPL(0xA6, 0);
+		writeOPL(0xB6, 0);
+		writeOPL(0xA7, 0);
+		writeOPL(0xB7, 0);
+		writeOPL(0xA8, 0);
+		writeOPL(0xB8, 0);
+
+// TODO set the correct frequency for the last 4 percussive voices
+	}
 }
 
-int AdLib::getIndex() const {
-	return _index;
+void MDYPlayer::rewind() {
+	_playPos = _data;
 }
 
-void AdLib::startPlay() {
-	if (_data) _playing = true;
+void MDYPlayer::setVoices() {
+	byte *timbrePtr;
+
+	timbrePtr = _timbres;
+	debugC(6, kDebugSound, "TBR version: %X.%X", timbrePtr[0], timbrePtr[1]);
+	timbrePtr += 2;
+
+	_tbrCount = READ_LE_UINT16(timbrePtr);
+	debugC(6, kDebugSound, "Timbres counter: %d", _tbrCount);
+	timbrePtr += 2;
+	_tbrStart = READ_LE_UINT16(timbrePtr);
+ 
+	timbrePtr += 2;
+	for (int i = 0; i < _tbrCount ; i++)
+		setVoice(i, i, true);
 }
 
-void AdLib::stopPlay() {
-	Common::StackLock slock(_mutex);
-	_playing = false;
+void MDYPlayer::setVoice(byte voice, byte instr, bool set) {
+	uint16 strct[27];
+	byte channel;
+	byte *timbrePtr;
+	char timbreName[10];
+
+	timbreName[9] = '\0';
+	for (int j = 0; j < 9; j++)
+		timbreName[j] = _timbres[6 + j + (instr * 9)]; 
+	debugC(6, kDebugSound, "Loading timbre %s", timbreName);
+	
+	// i = 0 :  0  1  2  3  4  5  6  7  8  9 10 11 12 26
+	// i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
+	for (int i = 0; i < 2; i++) {
+		timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A;
+		for (int j = 0; j < 27; j++) {
+			strct[j] = READ_LE_UINT16(timbrePtr);
+			timbrePtr += 2;
+		}
+		channel = _operators[voice] + i * 3;
+		writeOPL(0xBD, 0x00);
+		writeOPL(0x08, 0x00);
+		writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
+		if (!i)
+			writeOPL(0xC0 | voice,
+					((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
+		writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
+		writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
+		writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
+			((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
+			((strct[11] & 1) << 4) |  (strct[1] & 0xF));
+		if (!i)
+			writeOPL(0xE0 | channel, (strct[26] & 3));
+		else {
+			writeOPL(0xE0 | channel, (strct[14] & 3));
+			writeOPL(0x40 | channel, 0);
+		}
+	}
 }
 
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/sound/adlib.h
===================================================================
--- scummvm/trunk/engines/gob/sound/adlib.h	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/sound/adlib.h	2009-06-18 13:27:35 UTC (rev 41633)
@@ -38,7 +38,7 @@
 class AdLib : public Audio::AudioStream {
 public:
 	AdLib(Audio::Mixer &mixer);
-	~AdLib();
+	virtual ~AdLib();
 
 	bool isPlaying() const;
 	int getIndex() const;
@@ -49,11 +49,7 @@
 	void startPlay();
 	void stopPlay();
 
-	bool load(const char *fileName);
-	bool load(byte *data, uint32 size, int index = -1);
-	bool loadMdy(const char *fileName);
-	bool loadTbr(const char *fileName);
-	void unload();
+	virtual void unload();
 
 // AudioStream API
 	int  readBuffer(int16 *buffer, const int numSamples);
@@ -75,10 +71,8 @@
 	uint32 _rate;
 
 	byte *_data;
-	byte *_timbres;
 	byte *_playPos;
 	uint32 _dataSize;
-	uint32 _timbresSize;
 
 	short _freqs[25][12];
 	byte _notes[11];
@@ -93,34 +87,85 @@
 	bool _playing;
 	bool _first;
 	bool _ended;
-	bool _needFree;
-	bool _mdySong;
 
+	bool _freeData;
+
 	int _index;
-	uint16 _tbrCount;
-	uint16 _tbrStart;
 
 	unsigned char _wait;
 	uint8 _tickBeat;
 	uint8 _beatMeasure;
 	uint32 _totalTick;
 	uint32 _nrCommand;
-	byte _soundMode;
 	uint16 _pitchBendRangeStep;
 	uint16 _basicTempo, _tempo;
 
 	void writeOPL(byte reg, byte val);
 	void setFreqs();
-	void reset();
-	void setVoices();
-	void setVoice(byte voice, byte instr, bool set);
-	void setVoicesTbr();
-	void setVoiceTbr(byte voice, byte instr, bool set);
 	void setKey(byte voice, byte note, bool on, bool spec);
 	void setVolume(byte voice, byte volume);
 	void pollMusic();
+
+	virtual void interpret() = 0;
+
+	virtual void reset();
+	virtual void rewind() = 0;
+	virtual void setVoices() = 0;
+
+private:
+	void init();
 };
 
+class ADLPlayer : public AdLib {
+public:
+	ADLPlayer(Audio::Mixer &mixer);
+	~ADLPlayer();
+
+	bool load(const char *fileName);
+	bool load(byte *data, uint32 size, int index = -1);
+
+	void unload();
+
+protected:
+	void interpret();
+
+	void reset();
+	void rewind();
+
+	void setVoices();
+	void setVoice(byte voice, byte instr, bool set);
+};
+
+class MDYPlayer : public AdLib {
+public:
+	MDYPlayer(Audio::Mixer &mixer);
+	~MDYPlayer();
+
+	bool loadMDY(const char *fileName);
+	bool loadTBR(const char *fileName);
+
+	void unload();
+
+protected:
+	byte _soundMode;
+
+	byte *_timbres;
+	uint16 _tbrCount;
+	uint16 _tbrStart;
+	uint32 _timbresSize;
+
+	void interpret();
+
+	void reset();
+	void rewind();
+
+	void setVoices();
+	void setVoice(byte voice, byte instr, bool set);
+
+private:
+	void init();
+};
+
 } // End of namespace Gob
 
 #endif // GOB_SOUND_ADLIB_H

Modified: scummvm/trunk/engines/gob/sound/sound.cpp
===================================================================
--- scummvm/trunk/engines/gob/sound/sound.cpp	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/sound/sound.cpp	2009-06-18 13:27:35 UTC (rev 41633)
@@ -44,14 +44,15 @@
 	_pcspeaker = new PCSpeaker(*_vm->_mixer);
 	_blaster = new SoundBlaster(*_vm->_mixer);
 
-	_adlib = 0;
+	_adlPlayer = 0;
+	_mdyPlayer = 0;
 	_infogrames = 0;
 	_protracker = 0;
 	_cdrom = 0;
 	_bgatmos = 0;
 
-	if (!_vm->_noMusic && _vm->hasAdlib())
-		_adlib = new AdLib(*_vm->_mixer);
+	_hasAdLib = (!_vm->_noMusic && _vm->hasAdlib());
+
 	if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) {
 		_infogrames = new Infogrames(*_vm->_mixer);
 		_protracker = new Protracker(*_vm->_mixer);
@@ -69,7 +70,8 @@
 Sound::~Sound() {
 	delete _pcspeaker;
 	delete _blaster;
-	delete _adlib;
+	delete _adlPlayer;
+	delete _mdyPlayer;
 	delete _infogrames;
 	delete _protracker;
 	delete _cdrom;
@@ -137,9 +139,14 @@
 
 	if (sndDesc->getType() == SOUND_ADL) {
 
-		if (_adlib && noteAdlib)
-			if ((index == -1) || (_adlib->getIndex() == index))
-				_adlib->stopPlay();
+		if (noteAdlib) {
+			if (_adlPlayer)
+				if ((index == -1) || (_adlPlayer->getIndex() == index))
+					_adlPlayer->stopPlay();
+			if (_mdyPlayer)
+				if ((index == -1) || (_mdyPlayer->getIndex() == index))
+					_mdyPlayer->stopPlay();
+		}
 
 	} else {
 
@@ -230,68 +237,90 @@
 	_infogrames->stop();
 }
 
-bool Sound::adlibLoad(const char *fileName) {
-	if (!_adlib)
+bool Sound::adlibLoadADL(const char *fileName) {
+	if (!_hasAdLib)
 		return false;
 
-	debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName);
+	if (!_adlPlayer)
+		_adlPlayer = new ADLPlayer(*_vm->_mixer);
 
-	return _adlib->load(fileName);
+	debugC(1, kDebugSound, "Adlib: Loading ADL data (\"%s\")", fileName);
+
+	return _adlPlayer->load(fileName);
 }
 
-bool Sound::adlibLoad(byte *data, uint32 size, int index) {
-	if (!_adlib)
+bool Sound::adlibLoadADL(byte *data, uint32 size, int index) {
+	if (!_hasAdLib)
 		return false;
 
-	debugC(1, kDebugSound, "Adlib: Loading data (%d)", index);
+	if (!_adlPlayer)
+		_adlPlayer = new ADLPlayer(*_vm->_mixer);
 
-	return _adlib->load(data, size, index);
+	debugC(1, kDebugSound, "Adlib: Loading ADL data (%d)", index);
+
+	return _adlPlayer->load(data, size, index);
 }
 
 void Sound::adlibUnload() {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return;
 
 	debugC(1, kDebugSound, "Adlib: Unloading data");
 
-	_adlib->unload();
+	if (_adlPlayer)
+		_adlPlayer->unload();
+	if (_mdyPlayer)
+		_mdyPlayer->unload();
 }
 
-bool Sound::adlibLoadMdy(const char *fileName) {
-	if (!_adlib)
+bool Sound::adlibLoadMDY(const char *fileName) {
+	if (!_hasAdLib)
 		return false;
 
-	debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName);
+	if (!_mdyPlayer)
+		_mdyPlayer = new MDYPlayer(*_vm->_mixer);
 
-	return _adlib->loadMdy(fileName);
+	debugC(1, kDebugSound, "Adlib: Loading MDY data (\"%s\")", fileName);
+
+	return _mdyPlayer->loadMDY(fileName);
 }
 
-bool Sound::adlibLoadTbr(const char *fileName) {
-	if (!_adlib)
+bool Sound::adlibLoadTBR(const char *fileName) {
+	if (!_hasAdLib)
 		return false;
 
-	debugC(1, kDebugSound, "Adlib: Loading instruments (\"%s\")", fileName);
+	if (!_mdyPlayer)
+		_mdyPlayer = new MDYPlayer(*_vm->_mixer);
 
-	return _adlib->loadTbr(fileName);
+	debugC(1, kDebugSound, "Adlib: Loading MDY instruments (\"%s\")", fileName);
+
+	return _mdyPlayer->loadTBR(fileName);
 }
 
 void Sound::adlibPlayTrack(const char *trackname) {
-	if (!_adlib || _adlib->isPlaying())
+	if (!_hasAdLib)
 		return;
 
-	debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname);
+	if (!_adlPlayer)
+		_adlPlayer = new ADLPlayer(*_vm->_mixer);
 
-	_adlib->unload();
-	_adlib->load(trackname);
-	_adlib->startPlay();
+	if (_adlPlayer->isPlaying())
+		return;
+
+	debugC(1, kDebugSound, "Adlib: Playing ADL track \"%s\"", trackname);
+
+	_adlPlayer->unload();
+	_adlPlayer->load(trackname);
+	_adlPlayer->startPlay();
 }
 
 void Sound::adlibPlayBgMusic() {
-	int track;
-
-	if (!_adlib)
+	if (!_hasAdLib)
 		return;
 
+	if (!_adlPlayer)
+		_adlPlayer = new ADLPlayer(*_vm->_mixer);
+
 	static const char *tracksMac[] = {
 //		"musmac1.adl", // TODO: This track isn't played correctly at all yet
 		"musmac2.adl",
@@ -310,58 +339,82 @@
 	};
 
 	if (_vm->getPlatform() == Common::kPlatformWindows) {
-		track = _vm->_util->getRandom(ARRAYSIZE(tracksWin));
+		int track = _vm->_util->getRandom(ARRAYSIZE(tracksWin));
 		adlibPlayTrack(tracksWin[track]);
 	} else {
-		track = _vm->_util->getRandom(ARRAYSIZE(tracksMac));
+		int track = _vm->_util->getRandom(ARRAYSIZE(tracksMac));
 		adlibPlayTrack(tracksMac[track]);
 	}
 }
 
 void Sound::adlibPlay() {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return;
 
 	debugC(1, kDebugSound, "Adlib: Starting playback");
 
-	_adlib->startPlay();
+	if (_adlPlayer)
+		_adlPlayer->startPlay();
+	if (_mdyPlayer)
+		_mdyPlayer->startPlay();
 }
 
 void Sound::adlibStop() {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return;
 
 	debugC(1, kDebugSound, "Adlib: Stopping playback");
 
-	_adlib->stopPlay();
+	if (_adlPlayer)
+		_adlPlayer->stopPlay();
+	if (_mdyPlayer)
+		_mdyPlayer->stopPlay();
 }
 
 bool Sound::adlibIsPlaying() const {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return false;
 
-	return _adlib->isPlaying();
+	if (_adlPlayer && _adlPlayer->isPlaying())
+		return true;
+	if (_mdyPlayer && _mdyPlayer->isPlaying())
+		return true;
+
+	return false;
 }
 
 int Sound::adlibGetIndex() const {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return -1;
 
-	return _adlib->getIndex();
+	if (_adlPlayer)
+		return _adlPlayer->getIndex();
+	if (_mdyPlayer)
+		return _mdyPlayer->getIndex();
+
+	return -1;
 }
 
 bool Sound::adlibGetRepeating() const {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return false;
 
-	return _adlib->getRepeating();
+	if (_adlPlayer)
+		return _adlPlayer->getRepeating();
+	if (_mdyPlayer)
+		return _mdyPlayer->getRepeating();
+
+	return false;
 }
 
 void Sound::adlibSetRepeating(int32 repCount) {
-	if (!_adlib)
+	if (!_hasAdLib)
 		return;
 
-	_adlib->setRepeating(repCount);
+	if (_adlPlayer)
+		_adlPlayer->setRepeating(repCount);
+	if (_mdyPlayer)
+		_mdyPlayer->setRepeating(repCount);
 }
 
 void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount,

Modified: scummvm/trunk/engines/gob/sound/sound.h
===================================================================
--- scummvm/trunk/engines/gob/sound/sound.h	2009-06-18 13:27:14 UTC (rev 41632)
+++ scummvm/trunk/engines/gob/sound/sound.h	2009-06-18 13:27:35 UTC (rev 41633)
@@ -34,7 +34,8 @@
 class GobEngine;
 class PCSpeaker;
 class SoundBlaster;
-class AdLib;
+class ADLPlayer;
+class MDYPlayer;
 class Infogrames;
 class Protracker;
 class CDROM;
@@ -79,10 +80,10 @@
 
 
 	// AdLib
-	bool adlibLoad(const char *fileName);
-	bool adlibLoad(byte *data, uint32 size, int index = -1);
-	bool adlibLoadMdy(const char *fileName);
-	bool adlibLoadTbr(const char *fileName);
+	bool adlibLoadADL(const char *fileName);
+	bool adlibLoadADL(byte *data, uint32 size, int index = -1);
+	bool adlibLoadMDY(const char *fileName);
+	bool adlibLoadTBR(const char *fileName);
 	void adlibUnload();
 
 	void adlibPlayTrack(const char *trackname);
@@ -143,11 +144,14 @@
 private:
 	GobEngine *_vm;
 
+	bool _hasAdLib;
+
 	SoundDesc _sounds[kSoundsCount];
 
 	PCSpeaker *_pcspeaker;
 	SoundBlaster *_blaster;
-	AdLib *_adlib;
+	ADLPlayer *_adlPlayer;
+	MDYPlayer *_mdyPlayer;
 	Infogrames *_infogrames;
 	Protracker *_protracker;
 	CDROM *_cdrom;


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