diff options
| author | Sven Hesse | 2007-01-30 22:19:55 +0000 | 
|---|---|---|
| committer | Sven Hesse | 2007-01-30 22:19:55 +0000 | 
| commit | cb8378065d2831fa1512dfce138cc0039eff98fb (patch) | |
| tree | 8a2f720ee83cf583284c2721d6150959b3a8f7f1 | |
| parent | b4bebad6f0c3ab23b6992575c9fee88ace8f49d2 (diff) | |
| download | scummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.tar.gz scummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.tar.bz2 scummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.zip | |
- Changed _soundFlags and implemented "compositions"
- Changed Snd to be a permanent audiostream, to have better control over stopping, looping and compositions
- Some clean-up
svn-id: r25292
| -rw-r--r-- | engines/gob/game.cpp | 7 | ||||
| -rw-r--r-- | engines/gob/game_v1.cpp | 2 | ||||
| -rw-r--r-- | engines/gob/game_v2.cpp | 8 | ||||
| -rw-r--r-- | engines/gob/global.cpp | 3 | ||||
| -rw-r--r-- | engines/gob/global.h | 1 | ||||
| -rw-r--r-- | engines/gob/gob.cpp | 15 | ||||
| -rw-r--r-- | engines/gob/init.cpp | 13 | ||||
| -rw-r--r-- | engines/gob/init_v1.cpp | 15 | ||||
| -rw-r--r-- | engines/gob/init_v2.cpp | 18 | ||||
| -rw-r--r-- | engines/gob/inter_v1.cpp | 2 | ||||
| -rw-r--r-- | engines/gob/inter_v2.cpp | 11 | ||||
| -rw-r--r-- | engines/gob/mult_v2.cpp | 1 | ||||
| -rw-r--r-- | engines/gob/music.cpp | 114 | ||||
| -rw-r--r-- | engines/gob/music.h | 37 | ||||
| -rw-r--r-- | engines/gob/sound.cpp | 163 | ||||
| -rw-r--r-- | engines/gob/sound.h | 41 | 
16 files changed, 245 insertions, 206 deletions
| diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index e239248807..205258d628 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -351,6 +351,13 @@ void Game::freeSoundSlot(int16 slot) {  	if ((slot < 0) || (slot >= 60) || (_soundSamples[slot] == 0))  		return; +	if (slot == _vm->_snd->getCompositionSlot()) { +		if (_vm->_quitRequested) +			_vm->_snd->stopComposition(); +		else +			_vm->_snd->waitEndPlay(); +	} +  	if (_soundADL[slot]) {  		if (_vm->_adlib && (_vm->_adlib->getIndex() == slot))  			_vm->_adlib->stopPlay(); diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index 7c807aef70..47f5475950 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -579,8 +579,6 @@ int16 Game_v1::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId,  			_vm->_draw->animateCursor(-1);  		_vm->_util->delay(10); - -		_vm->_snd->loopSounds();  	}  } diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 1669da9e40..f9aa540308 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -92,18 +92,12 @@ void Game_v2::playTot(int16 skipPlay) {  				_vm->_mult->initAll();  				_vm->_mult->zeroMultData(); -/*				for (i = 0; i < 50; i++) -					_vm->_draw->_spritesArray[i] = 0;*/ -  				_vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface;  				_vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface;  				_vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites;  			} else  				_vm->_inter->initControlVars(0); -			for (i = 0; i < 20; i++) -				_soundSamples[i] = 0; -  			_totTextData = 0;  			_totResourceTable = 0;  			_imFileData = 0; @@ -661,8 +655,6 @@ int16 Game_v2::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId,  			_vm->_draw->animateCursor(-1);  		_vm->_util->delay(10); - -		_vm->_snd->loopSounds();  	}  } diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index d78b3eca29..6b2c54ecdd 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -37,8 +37,7 @@ Global::Global(GobEngine *vm) : _vm(vm) {  	_videoMode = 0;  	/* Sound */ -	_presentSound = 0x8000;	/* undefined values */ -	_soundFlags = 0x8000; +	_soundFlags = 0;  	_blasterPort = 0;  	_disableSoundCfg = 0; diff --git a/engines/gob/global.h b/engines/gob/global.h index 4fd5455201..aa1c6d95ca 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -80,7 +80,6 @@ public:  	int16 _disableVideoCfg; -	uint16 _presentSound;  	uint16 _soundFlags;  	int16 _disableSoundCfg;  	int16 _blasterPort; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 82302b3616..90ca277a9e 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -614,14 +614,10 @@ int GobEngine::init() {  	else  		error("GobEngine::init(): Unknown version of game engine");  	_noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; -	if (!(_features & Gob::GF_AMIGA) && -			(((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) || -			 (_features & Gob::GF_GOB2))) { -		if (_noMusic) -			_adlib = new Adlib_Dummy(this); -		else -			_adlib = new Adlib(this); -	} +	if (!_noMusic && !(_features & Gob::GF_AMIGA) && +	   (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) || +	     (_features & Gob::GF_GOB2))) +		_adlib = new Adlib(this);  	_vm = this;  	_system->beginGFXTransaction(); @@ -642,7 +638,7 @@ int GobEngine::init() {  	_global->_videoMode = 0x13;  	_global->_useMouse = 1; -	_global->_soundFlags = 0; +	_global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG;  	if (ConfMan.hasKey("language"))  		_language = Common::parseLanguage(ConfMan.get("language")); @@ -687,7 +683,6 @@ int GobEngine::init() {  	//        640x480.  	g_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); -  	return 0;  } diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index a026354eb2..c093f80851 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -50,18 +50,7 @@ Init::Init(GobEngine *vm) : _vm(vm) {  void Init::findBestCfg(void) {  	_vm->_global->_videoMode = VIDMODE_VGA;  	_vm->_global->_useMouse = _vm->_global->_mousePresent; -	if (_vm->_global->_presentSound & BLASTER_FLAG) -		_vm->_global->_soundFlags = BLASTER_FLAG | SPEAKER_FLAG | MIDI_FLAG; -	else if (_vm->_global->_presentSound & PROAUDIO_FLAG) -		_vm->_global->_soundFlags = PROAUDIO_FLAG | SPEAKER_FLAG | MIDI_FLAG; -	else if (_vm->_global->_presentSound & ADLIB_FLAG) -		_vm->_global->_soundFlags = ADLIB_FLAG | SPEAKER_FLAG | MIDI_FLAG; -	else if (_vm->_global->_presentSound & INTERSOUND_FLAG) -		_vm->_global->_soundFlags = INTERSOUND_FLAG | SPEAKER_FLAG; -	else if (_vm->_global->_presentSound & SPEAKER_FLAG) -		_vm->_global->_soundFlags = SPEAKER_FLAG; -	else -		_vm->_global->_soundFlags = 0; +	_vm->_global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG;  }  void Init::cleanup(void) { diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp index 73a09dd34b..c6c7481e22 100644 --- a/engines/gob/init_v1.cpp +++ b/engines/gob/init_v1.cpp @@ -41,20 +41,13 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) {  		error("soundVideo: Video mode 0x%x is not supported!",  		    _vm->_global->_videoMode); -	//if ((flag & 4) == 0) -	//	_vm->_video->findVideo(); -  	_vm->_global->_mousePresent = 1;  	_vm->_global->_inVM = 0; -	_vm->_global->_presentSound = 0; // FIXME: sound is not supported yet -  	_vm->_global->_sprAllocated = 0;  	_vm->_gtimer->enableTimer(); -	// _vm->_snd->setResetTimerFlag(debugFlag); // TODO -  	if (_vm->_global->_videoMode == 0x13)  		_vm->_global->_colorCount = 256; @@ -66,14 +59,6 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) {  	if (_vm->_global->_videoMode != 0)  		_vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, PRIMARY_SURFACE); - -	if (_vm->_global->_soundFlags & MIDI_FLAG) { -		_vm->_global->_soundFlags &= _vm->_global->_presentSound; -		if (_vm->_global->_presentSound & ADLIB_FLAG) -			_vm->_global->_soundFlags |= MIDI_FLAG; -	} else { -		_vm->_global->_soundFlags &= _vm->_global->_presentSound; -	}  }  } // End of namespace Gob diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp index 86cc7d7dbb..129f75ebd5 100644 --- a/engines/gob/init_v2.cpp +++ b/engines/gob/init_v2.cpp @@ -45,40 +45,24 @@ void Init_v2::soundVideo(int32 smallHeap, int16 flag) {  	_vm->_draw->_frontSurface = &_vm->_global->_primarySurfDesc;  	_vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200, 0x80); -	//if ((flag & 4) == 0) -	//	_vm->_video->findVideo(); -  	_vm->_global->_mousePresent = 1;  	_vm->_global->_inVM = 0; -	_vm->_global->_presentSound = 0; // FIXME: sound is not supported yet -  	_vm->_global->_sprAllocated = 0;  	_vm->_gtimer->enableTimer(); -	// _vm->_snd->setResetTimerFlag(debugFlag); // TODO - -	if (_vm->_global->_videoMode == 0x13) +	if ((_vm->_global->_videoMode == 0x13) || (_vm->_global->_videoMode == 0x14))  		_vm->_global->_colorCount = 256;  	_vm->_global->_pPaletteDesc = &_vm->_global->_paletteStruct;  	_vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;  	_vm->_global->_pPaletteDesc->unused1 = _vm->_global->_unusedPalette1;  	_vm->_global->_pPaletteDesc->unused2 = _vm->_global->_unusedPalette2; -//	_vm->_global->_pPrimarySurfDesc = &_vm->_global->_primarySurfDesc;  	if (_vm->_global->_videoMode != 0)  		_vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200,  				PRIMARY_SURFACE); - -	if (_vm->_global->_soundFlags & MIDI_FLAG) { -		_vm->_global->_soundFlags &= _vm->_global->_presentSound; -		if (_vm->_global->_presentSound & ADLIB_FLAG) -			_vm->_global->_soundFlags |= MIDI_FLAG; -	} else { -		_vm->_global->_soundFlags &= _vm->_global->_presentSound; -	}  }  } // End of namespace Gob diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 408dcd481c..788f9a0f2a 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1205,7 +1205,7 @@ bool Inter_v1::o1_playComposition(char &cmdCount, int16 &counter, int16 &retFlag  	for (i = 0; i < 50; i++)  		composition[i] = (int16)VAR_OFFSET(dataVar + i * 4); -	_vm->_snd->playComposition(_vm->_game->_soundSamples, composition, freqVal); +	_vm->_snd->playComposition(composition, freqVal);  	return false;  } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index f605b11720..95e13ff43a 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -1401,7 +1401,16 @@ bool Inter_v2::o2_checkData(char &cmdCount, int16 &counter, int16 &retFlag) {  }  bool Inter_v2::o2_stopSound(char &cmdCount, int16 &counter, int16 &retFlag) { -	_vm->_snd->stopSound(_vm->_parse->parseValExpr()); +	int16 expr; + +	expr = _vm->_parse->parseValExpr(); + +	if (expr < 0) { +		if (_vm->_adlib) +			_vm->_adlib->stopPlay(); +	} else +		_vm->_snd->stopSound(expr); +  	_soundEndTimeKey = 0;  	return false;  } diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 2d53f893f2..c082859204 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -522,7 +522,6 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape,  		stop = doFadeAnim(stop);  		stop = doSoundAnim(stop, _frame); -		_vm->_snd->loopSounds();  		if (_frame >= endFrame)  			stopNoClear = 1; diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp index b074a15602..67608bcd67 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/music.cpp @@ -82,7 +82,6 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) {  	_dataSize = 0;  	_rate = _vm->_mixer->getOutputRate();  	_opl = makeAdlibOPL(_rate); -	_vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType);  	_first = true;  	_ended = false;  	_playing = false; @@ -92,74 +91,71 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) {  	for (i = 0; i < 16; i ++)  		_pollNotes[i] = 0; -  	setFreqs(); + +	_vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle, +			this, -1, 255, 0, false, true);  }  Adlib::~Adlib(void) { +	Common::StackLock slock(_mutex); + +	_vm->_mixer->stopHandle(_handle);  	OPLDestroy(_opl);  	if (_data && _needFree)  		delete[] _data; -	_vm->_mixer->setupPremix(0);  } -void Adlib::premixerCall(int16 *buf, uint len) { -	_mutex.lock(); -	if (!_playing) { -		memset(buf, 0, 2 * len * sizeof(int16)); -		_mutex.unlock(); -		return; +int Adlib::readBuffer(int16 *buffer, const int numSamples) { +	Common::StackLock slock(_mutex); +	int samples; +	int render; + +	if (!_playing || (numSamples < 0)) { +		memset(buffer, 0, numSamples * sizeof(int16)); +		return numSamples;  	} -	else { -		if (_first) { -			memset(buf, 0, 2 * len * sizeof(int16)); +	if (_first) { +		memset(buffer, 0, numSamples * sizeof(int16)); +		pollMusic(); +		return numSamples; +	} + +	samples = numSamples; +	while (samples && _playing) { +		if (_samplesTillPoll) { +			render = (samples > _samplesTillPoll) ?  (_samplesTillPoll) : (samples); +			samples -= render; +			_samplesTillPoll -= render; +			YM3812UpdateOne(_opl, buffer, render); +			buffer += render; +		} else {  			pollMusic(); -			_mutex.unlock(); -			return; -		} -		else { -			uint32 render; -			int16 *data = buf; -			uint datalen = len; -			while (datalen && _playing) { -				if (_samplesTillPoll) { -					render = (datalen > _samplesTillPoll) ? -						(_samplesTillPoll) : (datalen); -					datalen -= render; -					_samplesTillPoll -= render; -					YM3812UpdateOne(_opl, data, render); -					data += render; -				} else { -					pollMusic(); -					if (_ended) { -						memset(data, 0, datalen * sizeof(int16)); -						datalen = 0; -					} -				} +			if (_ended) { +				memset(buffer, 0, samples * sizeof(int16)); +				samples = 0;  			}  		} -		if (_ended) { -			_first = true; -			_ended = false; -			_playPos = _data + 3 + (_data[1] + 1) * 0x38; -			_samplesTillPoll = 0; -			if (_repCount == -1) { -				reset(); -				setVoices(); -			} else if (_repCount > 0) { -				_repCount--; -				reset(); -				setVoices(); -			} -			else -				_playing = false; -		} -		// Convert mono data to stereo -		for (int i = (len - 1); i >= 0; i--) { -			buf[2 * i] = buf[2 * i + 1] = buf[i]; +	} + +	if (_ended) { +		_first = true; +		_ended = false; +		_playPos = _data + 3 + (_data[1] + 1) * 0x38; +		_samplesTillPoll = 0; +		if (_repCount == -1) { +			reset(); +			setVoices(); +		} else if (_repCount > 0) { +			_repCount--; +			reset(); +			setVoices();  		} +		else +			_playing = false;  	} -	_mutex.unlock(); + +	return numSamples;  }  void Adlib::writeOPL(byte reg, byte val) { @@ -194,6 +190,7 @@ void Adlib::setFreqs(void) {  }  void Adlib::reset() { +	_first = true;  	OPLResetChip(_opl);  	_samplesTillPoll = 0; @@ -356,21 +353,12 @@ void Adlib::pollMusic(void) {  			setVolume(channel, *(_playPos++));  			setKey(channel, note, true, false);  			break; -		case 0x10: -			warning("GOB2 Stub! ADL command 0x10"); -			break; -		case 0x50: -			warning("GOB2 Stub! ADL command 0x50"); -			break;  		// Note on  		case 0x90:  			note = *(_playPos++);  			_pollNotes[channel] = note;  			setKey(channel, note, true, false);  			break; -		case 0x60: -			warning("GOB2 Stub! ADL command 0x60"); -			break;  		// Last note off  		case 0x80:  			note = _pollNotes[channel]; diff --git a/engines/gob/music.h b/engines/gob/music.h index fdc2e1cbb8..89d3d7acf4 100644 --- a/engines/gob/music.h +++ b/engines/gob/music.h @@ -39,7 +39,7 @@ class GobEngine;  class Adlib : public Audio::AudioStream {  public:  	Adlib(GobEngine *vm); -	virtual ~Adlib(); +	~Adlib();  	void lock() { _mutex.lock(); }  	void unlock() { _mutex.unlock(); } @@ -50,9 +50,8 @@ public:  	virtual void startPlay(void) { if (_data) _playing = true; }  	virtual void stopPlay(void)  	{ -		_mutex.lock(); +		Common::StackLock slock(_mutex);  		_playing = false; -		_mutex.unlock();  	}  	virtual void playTrack(const char *trackname);  	virtual void playBgMusic(void); @@ -61,12 +60,10 @@ public:  	virtual void unload(void);  // AudioStream API -	int readBuffer(int16 *buffer, const int numSamples) { -		premixerCall(buffer, numSamples / 2); -		return numSamples; -	} -	bool isStereo() const { return true; } -	bool endOfData() const { return false; } +	int readBuffer(int16 *buffer, const int numSamples); +	bool isStereo() const { return false; } +	bool endOfData() const { return !_playing; } +	bool endOfStream() const { return false; }  	int getRate() const { return _rate; }  protected: @@ -74,6 +71,7 @@ protected:  	static const char *_trackFiles[];  	static const unsigned char _operators[];  	static const unsigned char _volRegNums []; +	Audio::SoundHandle _handle;  	FM_OPL *_opl;  	int _index;  	byte *_data; @@ -86,7 +84,7 @@ protected:  	byte _notLin[11];  	bool _notOn[11];  	byte _pollNotes[16]; -	uint32 _samplesTillPoll; +	int _samplesTillPoll;  	int32 _repCount;  	bool _playing;  	bool _first; @@ -95,7 +93,6 @@ protected:  	Common::Mutex _mutex;  	GobEngine *_vm; -	void premixerCall(int16 *buf, uint len);  	void writeOPL(byte reg, byte val);  	void setFreqs(void);  	void reset(void); @@ -106,24 +103,6 @@ protected:  	void pollMusic(void);  }; -/** - * A dummy class for the "null" sound driver - */ -class Adlib_Dummy: public Adlib { -public: -	Adlib_Dummy(GobEngine *vm) : Adlib(vm) {} - -	virtual void startPlay(void) {}; -	virtual void stopPlay(void) {}; -	virtual void playTrack(const char *trackname) {}; -	virtual void playBgAdlib(void) {}; -	virtual bool load(const char *filename) { return true; } -	virtual void load(byte *data, int index=-1) {} -	virtual void unload(void) {}; - -	virtual ~Adlib_Dummy() {}; -}; -  } // End of namespace Gob  #endif diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp index aa7724a294..500a2e5295 100644 --- a/engines/gob/sound.cpp +++ b/engines/gob/sound.cpp @@ -61,24 +61,21 @@ int Snd::SquareWaveStream::readBuffer(int16 *buffer, const int numSamples) {  }  Snd::Snd(GobEngine *vm) : _vm(vm) { -	//CleanupFuncPtr cleanupFunc;// = &snd_cleanupFuncCallback();  	_cleanupFunc = 0; -	for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) -		_loopingSounds[i] = NULL;  	_playingSound = 0; -} -void Snd::loopSounds(void) { -	for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { -		SoundDesc *snd = _loopingSounds[i]; -		if (snd && !_vm->_mixer->isSoundHandleActive(snd->handle)) { -			if (snd->repCount-- > 0) { -				_vm->_mixer->playRaw(&snd->handle, snd->data, snd->size, snd->frequency, 0); -			} else { -				_loopingSounds[i] = NULL; -			} -		} -	} +	_rate = _vm->_mixer->getOutputRate(); +	_end = true; +	_data = 0; +	_length = 0; +	_freq = 0; +	_repCount = 0; +	_offset = 0.0; + +	_compositionPos = -1; + +	_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, +			this, -1, 255, 0, false, true);  }  void Snd::setBlasterPort(int16 port) {return;} @@ -94,28 +91,54 @@ void Snd::speakerOff(void) {  	_vm->_mixer->stopHandle(_speakerHandle);  } -void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { -	if (frequency <= 0) -		frequency = sndDesc->frequency; +int8 Snd::getCompositionSlot(void) { +	if (_compositionPos == -1) +		return -1; -	for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) -		_loopingSounds[i] = 0; -	_vm->_mixer->stopHandle(sndDesc->handle); +	return _composition[_compositionPos]; +} -	_vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0); +void Snd::stopSound(int16 arg) +{ +	Common::StackLock slock(_mutex); -	sndDesc->repCount = repCount - 1; -	sndDesc->frequency = frequency; +	_data = 0; +	_end = true; +} + +void Snd::waitEndPlay(void) { +	while (!_end) +		_vm->_util->longDelay(200); +	stopSound(0); +} + +void Snd::stopComposition(void) { +	if (_compositionPos != -1) { +		stopSound(0); +		_compositionPos = -1; +	} +} + +void Snd::nextCompositionPos(void) { +	int8 slot; -	if (repCount > 1) { -		for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { -			if (!_loopingSounds[i]) { -				_loopingSounds[i] = sndDesc; -				return; -			} +	while ((++_compositionPos < 50) && ((slot = _composition[_compositionPos]) != -1)) { +		if ((slot >= 0) && (slot <= 60) && (_vm->_game->_soundSamples[slot] != 0) +				&& !(_vm->_game->_soundTypes[slot] & 8)) { +			setSample(_vm->_game->_soundSamples[slot], 1, 0); +			return;  		} -		warning("Looping sounds list is full");  	} +	_compositionPos = -1; +} + +void Snd::playComposition(int16 *composition, int16 freqVal) { +	waitEndPlay(); +	stopComposition(); + +	for (int i = 0; i < 50; i++) +		_composition[i] = composition[i]; +	nextCompositionPos();  }  void Snd::writeAdlib(int16 port, int16 data) { @@ -133,12 +156,8 @@ Snd::SoundDesc *Snd::loadSoundData(const char *path) {  }  void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) { -	_vm->_mixer->stopHandle(sndDesc->handle); - -	for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { -		if (_loopingSounds[i] == sndDesc) -			_loopingSounds[i] = NULL; -	} +	if (sndDesc == _curSoundDesc) +		stopSound(0);  	if (freedata) {  		delete[] sndDesc->data; @@ -146,7 +165,75 @@ void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) {  	delete sndDesc;  } -}                               // End of namespace Gob +void Snd::setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { +	if (frequency <= 0) +		frequency = sndDesc->frequency; +	_curSoundDesc = sndDesc; +	sndDesc->repCount = repCount - 1; +	sndDesc->frequency = frequency; + +	_data = (int8 *) sndDesc->data; +	_length = sndDesc->size; +	_freq = frequency; +	_ratio = ((double) _freq) / _rate; +	_offset = 0.0; +	_frac = 0; +	_cur = 0; +	_last = 0; +	_repCount = repCount; +	_end = false; +	_playingSound = 0; +} + +void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { +	Common::StackLock slock(_mutex); +	if (!_end) +		return;  + +	setSample(sndDesc, repCount, frequency); +	if (!_vm->_mixer->isSoundHandleActive(_handle)) +		_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, +				this, -1, 255, 0, false, true); +} + +void Snd::checkEndSample(void) { +	if (_compositionPos != -1) +		nextCompositionPos(); +	else if ((_repCount == -1) || (--_repCount > 0)) { +		_offset = 0.0; +		_end = false; +		_playingSound = 0; +	} else { +		_end = true; +		_playingSound = 0; +	} +} + +int Snd::readBuffer(int16 *buffer, const int numSamples) { +	memset(buffer, 0, numSamples); + +	for (int i = 0; i < numSamples; i++) { +		Common::StackLock slock(_mutex); + +		if (!_data) +			return i; +		if (_end || (_offset >= _length)) +			checkEndSample(); +		if (_end) +			return i; + +		*buffer++ = (int) (_last + (_cur - _last) * _frac); +		_frac += _ratio; +		while (_frac > 1) { +			_frac -= 1; +			_last = _cur; +			_cur = _data[(int) _offset] << 8; +		} +		_offset += _ratio; +	} +	return numSamples; +} +} // End of namespace Gob diff --git a/engines/gob/sound.h b/engines/gob/sound.h index 5b32569ac1..dd059b44ee 100644 --- a/engines/gob/sound.h +++ b/engines/gob/sound.h @@ -28,7 +28,7 @@  namespace Gob { -class Snd { +class Snd : public Audio::AudioStream {  public:  	struct SoundDesc {  		Audio::SoundHandle handle; @@ -45,7 +45,6 @@ public:  	typedef void (*CleanupFuncPtr) (int16); -	SoundDesc *_loopingSounds[10]; // Should be enough  	char _playingSound;  	CleanupFuncPtr _cleanupFunc; @@ -53,16 +52,23 @@ public:  	void speakerOn(int16 frequency, int32 length);  	void speakerOff(void);  	SoundDesc *loadSoundData(const char *path); -	void stopSound(int16 arg){return;} -	void loopSounds(void); +	void stopSound(int16 arg);  	void playSample(SoundDesc *sndDesc, int16 repCount, int16 frequency); -	void playComposition(Snd::SoundDesc ** samples, int16 *composit, int16 freqVal) {;} -	void waitEndPlay(void) {;} +	void playComposition(int16 *composition, int16 freqVal); +	void stopComposition(void); +	int8 getCompositionSlot(void); +	void waitEndPlay(void);  	// This deletes sndDesc and stops playing the sample.  	// If freedata is set, it also delete[]s the sample data.  	void freeSoundDesc(SoundDesc *sndDesc, bool freedata=true); +	int readBuffer(int16 *buffer, const int numSamples); +	bool isStereo() const { return false; } +	bool endOfData() const { return _end; } +	bool endOfStream() const { return false; } +	int getRate() const { return _rate; } +  protected:  	// TODO: This is a very primitive square wave generator. The only thing is  	//       has in common with the PC speaker is that it sounds terrible. @@ -91,6 +97,26 @@ protected:  	SquareWaveStream _speakerStream;  	Audio::SoundHandle _speakerHandle; +	Audio::SoundHandle *_activeHandle; +	Audio::SoundHandle _compositionHandle; +	int16 _composition[50]; +	int8 _compositionPos; + +	Audio::SoundHandle _handle; +	Common::Mutex _mutex; +	SoundDesc *_curSoundDesc; +	bool _end; +	int8 *_data; +	uint32 _length; +	uint32 _rate; +	int32 _freq; +	int32 _repCount; +	double _offset; +	double _ratio; +	double _frac; +	int16 _cur; +	int16 _last; +  	GobEngine *_vm;  	void cleanupFuncCallback() {;} @@ -101,6 +127,9 @@ protected:  	void writeAdlib(int16 port, int16 data);  	void setBlasterPort(int16 port);  	void setResetTimerFlag(char flag){return;} +	void setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency); +	void checkEndSample(void); +	void nextCompositionPos(void);  };  }				// End of namespace Gob | 
