diff options
| -rw-r--r-- | engines/gob/inter_fascin.cpp | 28 | ||||
| -rw-r--r-- | engines/gob/inter_v1.cpp | 2 | ||||
| -rw-r--r-- | engines/gob/sound/adlib.cpp | 769 | ||||
| -rw-r--r-- | engines/gob/sound/adlib.h | 81 | ||||
| -rw-r--r-- | engines/gob/sound/sound.cpp | 147 | ||||
| -rw-r--r-- | engines/gob/sound/sound.h | 16 | 
6 files changed, 594 insertions, 449 deletions
diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp index 8f7a53c8f1..d1264021f7 100644 --- a/engines/gob/inter_fascin.cpp +++ b/engines/gob/inter_fascin.cpp @@ -129,8 +129,8 @@ void Inter_Fascination::oFascin_geUnknown1(OpGobParams ¶ms) {  }  void Inter_Fascination::oFascin_geUnknown2(OpGobParams ¶ms) { -	_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 ¶ms) { @@ -146,33 +146,33 @@ void Inter_Fascination::oFascin_geUnknown5(OpGobParams ¶ms) {  }  void Inter_Fascination::oFascin_geUnknown6(OpGobParams ¶ms) { -	_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 ¶ms) { -	_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 ¶ms) { -	_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 ¶ms) { -	_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 ¶ms) { -	_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 ¶ms) { -	_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 ¶ms) { diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 26d6d9b3d9..70a7e12849 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1520,7 +1520,7 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) {  	}  	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 { diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp index b55e9fb0c8..a888b6ee49 100644 --- a/engines/gob/sound/adlib.cpp +++ b/engines/gob/sound/adlib.cpp @@ -39,21 +39,34 @@ const unsigned char AdLib::_volRegNums[] = {  };  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 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {  			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 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {  	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 @@ void AdLib::reset() {  	// 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::setVolume(byte voice, byte volume) {  }  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); - -				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; - -					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 (_data && _freeData) +		delete[] _data; -		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); -	} +	_freeData = false; +} + +bool AdLib::isPlaying() const { +	return _playing; +} + +bool AdLib::getRepeating() const { +	return _repCount != 0; +} + +void AdLib::setRepeating(int32 repCount) { +	_repCount = repCount; +} + +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 AdLib::load(const char *fileName) { +bool ADLPlayer::load(const char *fileName) {  	Common::File song;  	unload(); @@ -581,9 +309,7 @@ bool AdLib::load(const char *fileName) {  	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 @@ bool AdLib::load(const char *fileName) {  	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 @@ bool AdLib::load(byte *data, uint32 size, int index) {  	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 @@ bool AdLib::loadMdy(const char *fileName) {  	if (!song.isOpen())  		return false; -	_needFree = true; -	_mdySong = true; +	_freeData = true;  	song.read(mdyHeader, 70); @@ -652,7 +536,7 @@ bool AdLib::loadMdy(const char *fileName) {  	return true;  } -bool AdLib::loadTbr(const char *fileName) { +bool MDYPlayer::loadTBR(const char *fileName) {  	Common::File timbres;  	unload(); @@ -666,44 +550,203 @@ bool AdLib::loadTbr(const char *fileName) {  	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 diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h index 0a7663bc09..3772b93551 100644 --- a/engines/gob/sound/adlib.h +++ b/engines/gob/sound/adlib.h @@ -38,7 +38,7 @@ class GobEngine;  class AdLib : public Audio::AudioStream {  public:  	AdLib(Audio::Mixer &mixer); -	~AdLib(); +	virtual ~AdLib();  	bool isPlaying() const;  	int getIndex() const; @@ -49,11 +49,7 @@ public:  	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 @@ protected:  	uint32 _rate;  	byte *_data; -	byte *_timbres;  	byte *_playPos;  	uint32 _dataSize; -	uint32 _timbresSize;  	short _freqs[25][12];  	byte _notes[11]; @@ -93,32 +87,83 @@ protected:  	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 diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp index fba9ca3554..d6dd128f42 100644 --- a/engines/gob/sound/sound.cpp +++ b/engines/gob/sound/sound.cpp @@ -44,14 +44,15 @@ Sound::Sound(GobEngine *vm) : _vm(vm) {  	_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(GobEngine *vm) : _vm(vm) {  Sound::~Sound() {  	delete _pcspeaker;  	delete _blaster; -	delete _adlib; +	delete _adlPlayer; +	delete _mdyPlayer;  	delete _infogrames;  	delete _protracker;  	delete _cdrom; @@ -137,9 +139,14 @@ void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) {  	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 @@ void Sound::infogramesStop() {  	_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); + +	debugC(1, kDebugSound, "Adlib: Loading ADL data (%d)", index); -	return _adlib->load(data, size, 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); + +	debugC(1, kDebugSound, "Adlib: Loading MDY instruments (\"%s\")", fileName); -	return _adlib->loadTbr(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); + +	if (_adlPlayer->isPlaying()) +		return; -	_adlib->unload(); -	_adlib->load(trackname); -	_adlib->startPlay(); +	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 @@ void Sound::adlibPlayBgMusic() {  	};  	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, diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h index a48002df4a..6f6c1d0469 100644 --- a/engines/gob/sound/sound.h +++ b/engines/gob/sound/sound.h @@ -34,7 +34,8 @@ namespace Gob {  class GobEngine;  class PCSpeaker;  class SoundBlaster; -class AdLib; +class ADLPlayer; +class MDYPlayer;  class Infogrames;  class Protracker;  class CDROM; @@ -79,10 +80,10 @@ public:  	// 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 @@ public:  private:  	GobEngine *_vm; +	bool _hasAdLib; +  	SoundDesc _sounds[kSoundsCount];  	PCSpeaker *_pcspeaker;  	SoundBlaster *_blaster; -	AdLib *_adlib; +	ADLPlayer *_adlPlayer; +	MDYPlayer *_mdyPlayer;  	Infogrames *_infogrames;  	Protracker *_protracker;  	CDROM *_cdrom;  | 
