diff options
Diffstat (limited to 'engines')
| -rw-r--r-- | engines/adl/adl.cpp | 25 | ||||
| -rw-r--r-- | engines/adl/adl.h | 2 | ||||
| -rw-r--r-- | engines/adl/module.mk | 2 | ||||
| -rw-r--r-- | engines/adl/sound.cpp | 144 | ||||
| -rw-r--r-- | engines/adl/sound.h (renamed from engines/adl/speaker.h) | 43 | ||||
| -rw-r--r-- | engines/adl/speaker.cpp | 94 | 
6 files changed, 195 insertions, 115 deletions
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index c1c3820b10..e92cd690c8 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -39,14 +39,13 @@  #include "adl/display.h"  #include "adl/detection.h"  #include "adl/graphics.h" -#include "adl/speaker.h" +#include "adl/sound.h"  namespace Adl {  AdlEngine::~AdlEngine() {  	delete _display;  	delete _graphics; -	delete _speaker;  	delete _console;  	delete _dumpFile;  } @@ -56,7 +55,6 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :  		_dumpFile(nullptr),  		_display(nullptr),  		_graphics(nullptr), -		_speaker(nullptr),  		_isRestarting(false),  		_isRestoring(false),  		_isQuitting(false), @@ -461,7 +459,25 @@ void AdlEngine::drawPic(byte pic, Common::Point pos) const {  }  void AdlEngine::bell(uint count) const { -	_speaker->bell(count); +	Tones tones; + +	for (uint i = 0; i < count - 1; ++i) { +		tones.push_back(Tone(940.0, 100.0)); +		tones.push_back(Tone(0.0, 12.0)); +	} + +	tones.push_back(Tone(940.0, 100.0)); + +	Audio::SoundHandle handle; +	Audio::AudioStream *stream = new Sound(tones); + +	g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &handle, stream); + +	while (!g_engine->shouldQuit() && g_system->getMixer()->isSoundHandleActive(handle)) { +		Common::Event event; +		pollEvent(event); +		g_system->delayMillis(16); +	}  }  const Region &AdlEngine::getRegion(uint i) const { @@ -644,7 +660,6 @@ Common::Error AdlEngine::run() {  	initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true);  	_console = new Console(this); -	_speaker = new Speaker();  	_display = new Display();  	setupOpcodeTables(); diff --git a/engines/adl/adl.h b/engines/adl/adl.h index 62c5ea1b8e..c9b97237c4 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -53,7 +53,6 @@ namespace Adl {  class Console;  class Display;  class GraphicsMan; -class Speaker;  struct AdlGameDescription;  class ScriptEnv; @@ -347,7 +346,6 @@ protected:  	Display *_display;  	GraphicsMan *_graphics; -	Speaker *_speaker;  	// Opcodes  	typedef Common::Functor1<ScriptEnv &, int> Opcode; diff --git a/engines/adl/module.mk b/engines/adl/module.mk index df9dd2d232..b23ea5b2ef 100644 --- a/engines/adl/module.mk +++ b/engines/adl/module.mk @@ -19,7 +19,7 @@ MODULE_OBJS := \  	hires4.o \  	hires5.o \  	hires6.o \ -	speaker.o +	sound.o  MODULE_DIRS += \  	engines/adl diff --git a/engines/adl/sound.cpp b/engines/adl/sound.cpp new file mode 100644 index 0000000000..17f4955a12 --- /dev/null +++ b/engines/adl/sound.cpp @@ -0,0 +1,144 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/system.h" + +#include "audio/mixer.h" + +#include "adl/sound.h" + +namespace Adl { + +// Generic PC-speaker synth +// This produces more accurate frequencies than Audio::PCSpeaker, but only +// does square waves. +class Speaker { +public: +	Speaker(int sampleRate); + +	void startTone(double freq); +	void stopTone(); +	void generateSamples(int16 *buffer, int numSamples); + +private: +	int _rate; +	frac_t _halfWaveLen, _halfWaveRem; +	int16 _curSample; +}; + +Speaker::Speaker(int sampleRate) : +		_rate(sampleRate), +		_curSample(32767) { + +	stopTone(); +} + +void Speaker::startTone(double freq) { +	_halfWaveLen = _halfWaveRem = doubleToFrac(_rate / freq / 2); + +	if (_halfWaveLen < FRAC_ONE) { +		// Tone out of range at this sample rate +		stopTone(); +	} +} + +void Speaker::stopTone() { +	_halfWaveLen = 0; +	_halfWaveRem = intToFrac(32767); +} + +void Speaker::generateSamples(int16 *buffer, int numSamples) { +	int offset = 0; + +	while (offset < numSamples) { +		if (_halfWaveRem >= 0 && _halfWaveRem < FRAC_ONE) { +			// Rising/falling edge +			// Switch level +			_curSample = ~_curSample; +			// Use transition point fraction for current sample value +			buffer[offset++] = _halfWaveRem ^ _curSample; +			// Compute next transition point +			_halfWaveRem += _halfWaveLen - FRAC_ONE; +		} else { +			// Low/high level (incl. silence) +			// Generate as many samples as we can +			const int samples = MIN(numSamples - offset, (int)fracToInt(_halfWaveRem)); +			Common::fill(buffer + offset, buffer + offset + samples, _curSample); +			offset += samples; + +			// Count down to level transition point, unless we're playing silence +			if (_halfWaveLen > 0) +				_halfWaveRem -= intToFrac(samples); +		} +	} +} + +Sound::Sound(const Tones &tones) : +		_tones(tones), +		_toneIndex(0), +		_samplesRem(0) { + +	_rate = g_system->getMixer()->getOutputRate(); +	_speaker = new Speaker(_rate); +} + +Sound::~Sound() { +	delete _speaker; +} + +bool Sound::endOfData() const { +	return _samplesRem == 0 && _toneIndex == _tones.size(); +} + +int Sound::readBuffer(int16 *buffer, const int numSamples) { +	int offset = 0; + +	while (offset < numSamples) { +		if (_samplesRem == 0) { +			// Set up next tone + +			if (_toneIndex == _tones.size()) { +				// No more tones +				return offset; +			} + +			if (_tones[_toneIndex].freq == 0.0) +				_speaker->stopTone(); +			else +				_speaker->startTone(_tones[_toneIndex].freq); + +			// Compute length of tone +			_samplesRem = _rate * _tones[_toneIndex++].len / 1000; +		} + +		// Generate as many samples as we can +		const int samples = MIN(numSamples - offset, _samplesRem); +		_speaker->generateSamples(buffer + offset, samples); + +		_samplesRem -= samples; +		offset += samples; +	} + +	return numSamples; +} + +} // End of namespace Adl diff --git a/engines/adl/speaker.h b/engines/adl/sound.h index 31aaac32d2..8fbeb805ff 100644 --- a/engines/adl/speaker.h +++ b/engines/adl/sound.h @@ -20,28 +20,45 @@   *   */ -#ifndef ADL_SPEAKER_H -#define ADL_SPEAKER_H +#ifndef ADL_SOUND_H +#define ADL_SOUND_H -#include "common/types.h" +#include "audio/audiostream.h" -#include "audio/mixer.h" - -namespace Audio { -class AudioStream; -} +#include "common/array.h" +#include "common/frac.h"  namespace Adl { -class Speaker { +class Speaker; + +struct Tone { +	double freq; // Hz +	double len; // ms + +	Tone(double frequency, double length) : freq(frequency), len(length) { } +}; + +typedef Common::Array<Tone> Tones; + +class Sound : public Audio::AudioStream {  public: -	Speaker(); -	~Speaker(); +	Sound(const Tones &tones); +	~Sound(); -	void bell(uint count); +	// AudioStream +	int readBuffer(int16 *buffer, const int numSamples); +	bool isStereo() const { return false; } +	bool endOfData() const; +	int getRate() const	{ return _rate; }  private: -	byte *_bell, *_silence; +	const Tones &_tones; + +	Speaker *_speaker; +	int _rate; +	uint _toneIndex; +	int _samplesRem;  };  } // End of namespace Adl diff --git a/engines/adl/speaker.cpp b/engines/adl/speaker.cpp deleted file mode 100644 index 532d361cd9..0000000000 --- a/engines/adl/speaker.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/system.h" -#include "common/events.h" - -#include "engines/engine.h" - -#include "audio/audiostream.h" -#include "audio/decoders/raw.h" - -#include "adl/speaker.h" -#include "adl/adl.h" - -namespace Adl { - -// Number of times to duplicate each sample -#define SAMPLE_DUP 4 -// Bell frequency in Hz -#define BELL_FREQ 1000 -// Sample rate -#define SAMPLE_RATE (BELL_FREQ * SAMPLE_DUP * 2) -// Number of waves per 0.1 seconds (bell length) -#define BELL_WAVE_COUNT (SAMPLE_RATE / 10 / SAMPLE_DUP / 2) -// Length of bell in samples -#define BELL_LEN (BELL_WAVE_COUNT * SAMPLE_DUP * 2) -// Length of silence in samples -#define SILENCE_LEN (SAMPLE_RATE / 80) - -Speaker::~Speaker() { -	delete[] _bell; -	delete[] _silence; -} - -Speaker::Speaker() { -	_bell = new byte[BELL_LEN]; - -	byte *buf = _bell; -	for (uint i = 0; i < BELL_WAVE_COUNT; ++i) { -		for (uint j = 0; j < SAMPLE_DUP; ++j) -			*buf++ = 0x00; -		for (uint j = 0; j < SAMPLE_DUP; ++j) -			*buf++ = 0xff; -	} - -	_silence = new byte[SILENCE_LEN]; - -	buf = _silence; -	for (uint i = 0; i < SILENCE_LEN; ++i) -		*buf++ = 0x80; -} - -void Speaker::bell(uint count) { -	Audio::QueuingAudioStream *stream = Audio::makeQueuingAudioStream(SAMPLE_RATE, false); -	Audio::SoundHandle handle; - -	stream->queueBuffer(_bell, BELL_LEN, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); - -	for (uint i = 1; i < count; ++i) { -		stream->queueBuffer(_silence, SILENCE_LEN, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); -		stream->queueBuffer(_bell, BELL_LEN, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); -	} - -	stream->finish(); - -	g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &handle, stream); - -	while (!g_engine->shouldQuit() && g_system->getMixer()->isSoundHandleActive(handle)) { -		Common::Event event; -		static_cast<AdlEngine *>(g_engine)->pollEvent(event); -		g_system->delayMillis(16); -	} -} - -} // End of namespace Adl  | 
