diff options
| author | Paweł Kołodziejski | 2003-12-26 12:15:23 +0000 | 
|---|---|---|
| committer | Paweł Kołodziejski | 2003-12-26 12:15:23 +0000 | 
| commit | a45e92efed3715b3bb0b1191b718207b191ab1ae (patch) | |
| tree | 79e58723288257ce0e3e68a434b86f17110330d3 /scumm | |
| parent | 908fbe2ac563f41b039da0392baa60207331d64d (diff) | |
| download | scummvm-rg350-a45e92efed3715b3bb0b1191b718207b191ab1ae.tar.gz scummvm-rg350-a45e92efed3715b3bb0b1191b718207b191ab1ae.tar.bz2 scummvm-rg350-a45e92efed3715b3bb0b1191b718207b191ab1ae.zip | |
passthrought v7+ sound voices by imuse digital
svn-id: r11939
Diffstat (limited to 'scumm')
| -rw-r--r-- | scumm/imuse_digi.cpp | 224 | ||||
| -rw-r--r-- | scumm/imuse_digi.h | 11 | ||||
| -rw-r--r-- | scumm/script_v8.cpp | 7 | ||||
| -rw-r--r-- | scumm/sound.cpp | 95 | ||||
| -rw-r--r-- | scumm/string.cpp | 7 | 
5 files changed, 141 insertions, 203 deletions
| diff --git a/scumm/imuse_digi.cpp b/scumm/imuse_digi.cpp index 8db1fb3dd4..53641531a4 100644 --- a/scumm/imuse_digi.cpp +++ b/scumm/imuse_digi.cpp @@ -634,58 +634,6 @@ static const imuse_ft_music_table _ftSeqMusicTable[] = {  };  #endif -static byte *readCreativeVocFile(byte *ptr, int32 &size, int &rate) { -	assert(strncmp((char *)ptr, "Creative Voice File\x1A", 20) == 0); -	int32 offset = READ_LE_UINT16(ptr + 20); -	int16 version = READ_LE_UINT16(ptr + 22); -	int16 code = READ_LE_UINT16(ptr + 24); -	assert(version == 0x010A || version == 0x0114); -	assert(code == ~version + 0x1234); -	bool quit = 0; -	byte *ret_sound = 0; size = 0; -	int loops = 0; -	while (!quit) { -		int len = READ_LE_UINT32(ptr + offset); -		offset += 4; -		code = len & 0xFF; -		len >>= 8; -		switch(code) { -		case 0: quit = 1; break; -		case 1: { -			int time_constant = ptr[offset++]; -			int packing = ptr[offset++]; -			len -= 2; -			rate = getSampleRateFromVOCRate(time_constant); -			debug(9, "VOC Data Bloc : %d, %d, %d", rate, packing, len); -			if (packing == 0) { -				if (size) { -					ret_sound = (byte *)realloc(ret_sound, size + len); -				} else { -					ret_sound = (byte *)malloc(len); -				} -				memcpy(ret_sound + size, ptr + offset, len); -				size += len; -			} else { -				warning("VOC file packing %d unsupported", packing); -			} -			} break; -		case 6:	// begin of loop -			loops = len + 1; -			break; -		case 7:	// end of loop -			break; -		default: -			warning("Invalid code in VOC file : %d", code); -			quit = 1; -			break; -		} -		// FIXME some FT samples (ex. 362) has bad length, 2 bytes too short -		offset += len; -	} -	debug(9, "VOC Data Size : %d", size); -	return ret_sound; -} -  static uint32 decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo) {  	uint32 loop_size = size / 3;  	uint32 s_size = loop_size * 4; @@ -722,6 +670,12 @@ IMuseDigital::IMuseDigital(ScummEngine *scumm)  	: _scumm(scumm) {  	_pause = false; +	_voiceVocData = NULL; +	_voiceVocSize = 0; +	_voiceVocRate = 0; + +	_voiceBundleData = NULL; +  	_nameBundleMusic = "";  	_musicBundleBufFinal = NULL;  	_musicBundleBufOutput = NULL; @@ -802,17 +756,36 @@ void IMuseDigital::callback() {  	}  } +void IMuseDigital::setVocVoice(byte *src, int32 size, int rate) { +	_voiceVocData = src; +	_voiceVocSize = size; +	_voiceVocRate = rate; +} + +void IMuseDigital::setBundleVoice(byte *src) { +	_voiceBundleData = src; +} +  void IMuseDigital::startSound(int sound) {  	debug(5, "IMuseDigital::startSound(%d)", sound);  	int l, r;  	for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {  		if (!_channel[l].used && !_channel[l].handle.isActive()) { -			byte *ptr = _scumm->getResourceAddress(rtSound, sound); -			byte *s_ptr = ptr; -			if (ptr == NULL) { -				warning("IMuseDigital::startSound(%d) NULL resource pointer", sound); -				return; +			byte *ptr, *s_ptr; +			if ((sound == 10000) && (_voiceBundleData)) { +				s_ptr = ptr = _voiceBundleData; +			} else if ((sound == 10000) && (_voiceVocData)) { +				// +			} else if (sound != 10000) { +				ptr = _scumm->getResourceAddress(rtSound, sound); +				s_ptr = ptr; +				if (ptr == NULL) { +					warning("IMuseDigital::startSound(%d) NULL resource pointer", sound); +					return; +				} +			} else { +				error("IMuseDigital::startSound() unknown condition");  			}  			_channel[l].pan = 0;  			_channel[l].vol = 127 * 1000; @@ -832,8 +805,22 @@ void IMuseDigital::startSound(int sound) {  			int32 size = 0;  			int t; -			if (READ_UINT32(ptr) == MKID('Crea')) { -				byte *t_ptr= readCreativeVocFile(ptr, size, _channel[l].freq); +			if ((sound == 10000) && (_voiceVocData)) { +				_channel[l].mixerSize = _voiceVocRate * 2; +				_channel[l].size = _voiceVocSize * 2; +				_channel[l].bits = 8; +				_channel[l].channels = 2; +				_channel[l].mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO | SoundMixer::FLAG_UNSIGNED; +				_channel[l].data = (byte *)malloc(_channel[l].size); + +				for (t = 0; t < _channel[l].size / 2; t++) { +					*(_channel[l].data + t * 2 + 0) = *(_voiceVocData + t); +					*(_channel[l].data + t * 2 + 1) = *(_voiceVocData + t); +				} + +				_voiceVocRate = NULL; +			} else if (READ_UINT32(ptr) == MKID('Crea')) { +				byte *t_ptr= readCreativeVoc(ptr, size, _channel[l].freq);  				_channel[l].mixerSize = _channel[l].freq * 2;  				_channel[l].size = size * 2;  				_channel[l].bits = 8; @@ -897,6 +884,9 @@ void IMuseDigital::startSound(int sound) {  						_channel[l].jump[_channel[l].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;  						_channel[l].numJumps++;  						break; +					case MKID_BE('SYNC'): +						size = READ_BE_UINT32(ptr); ptr += size + 4; +						break;  					case MKID_BE('DATA'):  						size = READ_BE_UINT32(ptr); ptr += 4;  						break; @@ -907,6 +897,16 @@ void IMuseDigital::startSound(int sound) {  						break;  				} +				if ((sound == 10000) && (_voiceBundleData)) { +					if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) { +						Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound"); +						_channel[l].freq = (_channel[l].freq * a->talkFrequency) / 256; + +						// Adjust to fit the mixer's notion of panning. +						_channel[l].pan = (a->talkPan != 64) ? 2 * a->talkPan - 127 : 0; +					} +				} +  				uint32 header_size = ptr - s_ptr;  				_channel[l].offsetStop -= header_size; @@ -938,6 +938,26 @@ void IMuseDigital::startSound(int sound) {  					_channel[l].mixerSize *= 2;  					_channel[l].mixerFlags |= SoundMixer::FLAG_16BITS;  					_channel[l].size = decode12BitsSample(ptr, &_channel[l].data, size, (_channel[l].channels == 2) ? false : true); +				} else if (_channel[l].bits == 16) { +					_channel[l].mixerSize *= 2; +					_channel[l].mixerFlags |= SoundMixer::FLAG_16BITS; +					 +					// FIXME: For some weird reasons, sometimes we get an odd size, even though +					// the data is supposed to be in 16 bit format... that makes no sense... +					size &= ~1; +					 +					if (_channel[l].channels == 1) { +						size *= 2; +						_channel[l].channels = 2; +						_channel[l].data = (byte *)malloc(size); +						for (t = 0; t < size / 4; t++) { +							*(_channel[l].data + t * 4 + 0) = *(ptr + t * 2 + 0); +							*(_channel[l].data + t * 4 + 1) = *(ptr + t * 2 + 1); +							*(_channel[l].data + t * 4 + 2) = *(ptr + t * 2 + 0); +							*(_channel[l].data + t * 4 + 3) = *(ptr + t * 2 + 1); +						} +					} +					_channel[l].size = size;  				} else if (_channel[l].bits == 8) {  					_channel[l].mixerFlags |= SoundMixer::FLAG_UNSIGNED;  					if (_channel[l].channels == 1) { @@ -1408,9 +1428,8 @@ void IMuseDigital::bundleMusicHandler() {  	free(buffer);  } -void IMuseDigital::playBundleSound(const char *sound, PlayingSoundHandle *handle) { +void IMuseDigital::playBundleSound(const char *sound) {  	byte *ptr = 0, *orig_ptr = 0; -	byte *final;  	bool result;  	if (!_scumm->_mixer->isReady()) @@ -1427,7 +1446,7 @@ void IMuseDigital::playBundleSound(const char *sound, PlayingSoundHandle *handle  			result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath()); -			if (result == false)  +			if (result == false)  				result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath());  			_voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);  		} @@ -1439,89 +1458,22 @@ void IMuseDigital::playBundleSound(const char *sound, PlayingSoundHandle *handle  	if (!result)  		return; -	int32 rate = 22050, pan = 0, channels = 0, output_size = 0; -	int32 tag, size = -1, bits = 0; -  	if (_scumm->_gameId == GID_CMI) {  		char name[20];  		strcpy(name, sound);  		if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music...  			strcat(name, ".IMX"); -		output_size = _bundle->decompressVoiceSampleByName(name, &ptr); +		_bundle->decompressVoiceSampleByName(name, &ptr);  	} else { -		output_size = _bundle->decompressVoiceSampleByName(sound, &ptr); -	} - -	orig_ptr = ptr; -	if (output_size == 0 || orig_ptr == 0) { -		goto bail; -	} - -	tag = READ_BE_UINT32(ptr); ptr += 4; -	if (tag != MKID_BE('iMUS')) { -		warning("Decompression of bundle sound failed"); -		goto bail; +		_bundle->decompressVoiceSampleByName(sound, &ptr);  	} -	ptr += 12; -	while (tag != MKID_BE('DATA')) { -		tag = READ_BE_UINT32(ptr); ptr += 4; -		switch(tag) { -		case MKID_BE('FRMT'): -			ptr += 12; -			bits = READ_BE_UINT32(ptr); ptr += 4; -			rate = READ_BE_UINT32(ptr); ptr += 4; -			channels = READ_BE_UINT32(ptr); ptr += 4; -			break; -		case MKID_BE('TEXT'): -		case MKID_BE('REGN'): -		case MKID_BE('STOP'): -		case MKID_BE('JUMP'): -		case MKID_BE('SYNC'): -			size = READ_BE_UINT32(ptr); ptr += size + 4; -			break; -		case MKID_BE('DATA'): -			size = READ_BE_UINT32(ptr); ptr += 4; -			break; -		default: -			error("Unknown sound header '%s'", tag2str(tag)); -		} -	} - -	if (size < 0) { -		warning("Decompression sound failed (no size field)"); -		goto bail; +	if (ptr) { +		stopSound(10000); +		setBundleVoice(ptr); +		startSound(10000); +		free(ptr);  	} - -	final = (byte *)malloc(size); -	memcpy(final, ptr, size); - -	if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) { -		Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound"); -		rate = (rate * a->talkFrequency) / 256; - -		// Adjust to fit the mixer's notion of panning. -		pan = (a->talkPan != 64) ? 2 * a->talkPan - 127 : 0; -	} -	 -	// Stop any sound currently playing on the given handle -	if (handle) -		_scumm->_mixer->stopHandle(*handle); - -	assert(channels == 1); -	if (bits == 8) { -		_scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); -	} else if (bits == 16) { -		// FIXME: For some weird reasons, sometimes we get an odd size, even though -		// the data is supposed to be in 16 bit format... that makes no sense... -		size &= ~1; -		_scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); -	} else { -		warning("IMuseDigital::playBundleSound() to do more options to playRaw..."); -	} -	 -bail: -	free(orig_ptr);  }  } // End of namespace Scumm diff --git a/scumm/imuse_digi.h b/scumm/imuse_digi.h index 913f1e72e7..eb7ade49d2 100644 --- a/scumm/imuse_digi.h +++ b/scumm/imuse_digi.h @@ -128,11 +128,18 @@ private:  public:  	int32 _bundleSongPosInMs;  	Bundle *_bundle;	// FIXME: should be protected but is used by ScummEngine::askForDisk +	byte *_voiceVocData; +	int32 _voiceVocSize; +	int _voiceVocRate; + +	byte *_voiceBundleData;  	void pauseBundleMusic(bool state);  	void stopBundleMusic(); -	void playBundleSound(const char *sound, PlayingSoundHandle *handle); -  +	void playBundleSound(const char *sound); +	void setVocVoice(byte *src, int32 size, int rate); +	void setBundleVoice(byte *src); +  public:  	IMuseDigital(ScummEngine *scumm);  	~IMuseDigital(); diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp index 6d4afc2bff..b4675ce533 100644 --- a/scumm/script_v8.cpp +++ b/scumm/script_v8.cpp @@ -1078,9 +1078,10 @@ void ScummEngine_v8::o8_actorOps() {  		// on the current talk channel handle. (If the handle is 0,  		// setChannelPan() won't do anything.) -		if (_actorToPrintStrFor == a->number) -			_mixer->setChannelPan(_sound->_talkChannelHandle, -				(a->talkPan != 64) ? 2 * a->talkPan - 127 : 0); +		if (_actorToPrintStrFor == a->number) { +			if (_sound->isSoundRunning(10000)) +				_imuseDigital->parseScriptCmds(12, 0x700, 10000, a->talkPan, 0, 0, 0, 0); +		}  		break;  	default: diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 0590a2696f..5523635069 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -39,11 +39,6 @@  namespace Scumm { -enum { -	SOUND_HEADER_SIZE = 26, -	SOUND_HEADER_BIG_SIZE = 26 + 8 -}; -  struct MP3OffsetTable {					/* Compressed Sound (.SO3) */  	int org_offset;  	int new_offset; @@ -411,7 +406,11 @@ void Sound::processSfxQueues() {  	if ((_sfxMode & 2) && _scumm->VAR(_scumm->VAR_TALK_ACTOR)) {  		act = _scumm->VAR(_scumm->VAR_TALK_ACTOR); -		finished = !_talkChannelHandle.isActive(); +		if (_scumm->_imuseDigital) { +			finished = !isSoundRunning(10000); +		} else { +			finished = !_talkChannelHandle.isActive(); +		}  		if (act != 0 && (uint) act < 0x80 && !_scumm->_string[0].no_talk_anim) {  			a = _scumm->derefActor(act, "processSfxQueues"); @@ -486,14 +485,13 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle  			warning("startTalkSound: dig demo: voc file not found");  			return;  		} -  	} else {  		if (!_sfxFile->isOpen()) {  			warning("startTalkSound: SFX file is not open");  			return;  		} -	 +  		// FIXME hack until more is known  		// the size of the data after the sample isn't known  		// 64 is just a guess @@ -506,7 +504,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle  			_scumm->_mixer->playRaw(handle, sound, b - 64, 11025, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);  			return;  		} -	 +  		// Some games frequently assume that starting one sound effect will  		// automatically stop any other that may be playing at that time. So  		// that is what we do here, but we make an exception for speech. @@ -515,24 +513,24 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle  		//  		// HACK: Checking for script 99 in Sam & Max is to keep Conroy's song  		// from being interrupted. -	 +  		if (mode == 1 && (_scumm->_gameId == GID_TENTACLE  			|| (_scumm->_gameId == GID_SAMNMAX && !_scumm->isScriptRunning(99)))) {  			id = 777777;  			_scumm->_mixer->stopID(id);  		} -	 +  		if (b > 8) {  			num = (b - 8) >> 1;  		} -	 +  		if (offset_table != NULL) {  			MP3OffsetTable *result = NULL, key;  			key.org_offset = offset;  			result = (MP3OffsetTable *)bsearch(&key, offset_table, num_sound_effects,  													sizeof(MP3OffsetTable), compareMP3OffsetTable); -	 +  			if (result == NULL) {  				warning("startTalkSound: did not find sound at offset %d !", offset);  				return; @@ -548,10 +546,10 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle  			offset += 8;  			size = -1;  		} -	 +  		_sfxFile->seek(offset, SEEK_SET); -	 -		assert(num+1 < (int)ARRAYSIZE(_mouthSyncTimes)); + +		assert(num + 1 < (int)ARRAYSIZE(_mouthSyncTimes));  		for (i = 0; i < num; i++)  			_mouthSyncTimes[i] = _sfxFile->readUint16BE(); @@ -566,7 +564,11 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle  void Sound::stopTalkSound() {  	if (_sfxMode & 2) { -		_scumm->_mixer->stopHandle(_talkChannelHandle); +		if (_scumm->_imuseDigital) { +			_scumm->_imuseDigital->stopSound(10000); +		} else { +			_scumm->_mixer->stopHandle(_talkChannelHandle); +		}  		_sfxMode &= ~2;  	}  } @@ -797,10 +799,6 @@ void Sound::pauseSounds(bool pause) {  }  void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle, int id) { -	char ident[8]; -	uint size = 0; -	int rate, comp; -	byte *data;  	if (_soundsPaused || !_scumm->_mixer->isReady())  		return; @@ -818,47 +816,17 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle,  		return;  	} -	if (file->read(ident, 8) != 8) -		goto invalid; +	int32 size; +	int rate; +	byte *data = loadVocSample(_sfxFile, size, rate); -	if (!memcmp(ident, "VTLK", 4)) { -		file->seek(SOUND_HEADER_BIG_SIZE - 8, SEEK_CUR); -	} else if (!memcmp(ident, "Creative", 8)) { -		file->seek(SOUND_HEADER_SIZE - 8, SEEK_CUR); +	if (_scumm->_imuseDigital) { +		_scumm->_imuseDigital->setVocVoice(data, size, rate); +		_scumm->_imuseDigital->startSound(10000); +		free(data);  	} else { -	invalid:; -		warning("startSfxSound: invalid header"); -		return; -	} - -	VocBlockHeader voc_block_hdr; - -	file->read(&voc_block_hdr, sizeof(voc_block_hdr)); -	if (voc_block_hdr.blocktype != 1) { -		warning("startSfxSound: Expecting block_type == 1, got %d", voc_block_hdr.blocktype); -		return; -	} - -	size = voc_block_hdr.size[0] + (voc_block_hdr.size[1] << 8) + (voc_block_hdr.size[2] << 16) - 2; -	rate = getSampleRateFromVOCRate(voc_block_hdr.sr); -	comp = voc_block_hdr.pack; - -	if (comp != 0) { -		warning("startSfxSound: Unsupported compression type %d", comp); -		return; -	} - -	data = (byte *)malloc(size); -	if (data == NULL) { -		error("startSfxSound: out of memory"); +		_scumm->_mixer->playRaw(handle, data, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED, id);  	} - -	if (file->read(data, size) != size) { -		/* no need to free the memory since error will shut down */ -		error("startSfxSound: cannot read %d bytes", size); -	} - -	_scumm->_mixer->playRaw(handle, data, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED, id);  }  File *Sound::openSfxFile() { @@ -870,6 +838,15 @@ File *Sound::openSfxFile() {  	 * same directory */  	offset_table = NULL; +	// for now until better streaming will be, ft voice can't not be compressed +	if (_scumm->_imuseDigital) { +		sprintf(buf, "%s.sou", _scumm->getGameName()); +		if (!file->open(buf, _scumm->getGameDataPath())) { +			file->open("monster.sou", _scumm->getGameDataPath()); +		} +		return file; +	} +  #ifdef USE_MAD  	sprintf(buf, "%s.so3", _scumm->getGameName());  	if (!file->open(buf, _scumm->getGameDataPath())) { diff --git a/scumm/string.cpp b/scumm/string.cpp index 69d5ed5e6c..1a15a48255 100644 --- a/scumm/string.cpp +++ b/scumm/string.cpp @@ -163,9 +163,10 @@ void ScummEngine::CHARSET_1() {  	if (_talkDelay)  		return; -	if ((_gameId == GID_CMI || _gameId == GID_DIG) && _sound->_talkChannelHandle.isActive()) { +	if ((_gameId == GID_CMI || _gameId == GID_DIG) && (_imuseDigital) +				&& _sound->isSoundRunning(10000)) {  		// Keep the 'speech' flag in _sound->_sfxMode set as long as the -		// _talkChannelHandle is valid. +		// sound 10000 is playing.  		_sound->_sfxMode |= 2;  	} @@ -900,7 +901,7 @@ const byte *ScummEngine::translateTextAndPlaySpeech(const byte *ptr) {  		pointer[j] = 0;  		// Play speech -		_imuseDigital->playBundleSound(pointer, &_sound->_talkChannelHandle); +		_imuseDigital->playBundleSound(pointer);  		ptr = _transText;  	} | 
