[Scummvm-git-logs] scummvm master -> e6be031b89e43e7a96d55d7ecd0fba1d7fd6f8d8

sev- noreply at scummvm.org
Mon Jul 21 12:14:56 UTC 2025


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
e6be031b89 AUDIO: Create a wrapper around the PCSpeaker emulator that handles the mixer stream


Commit: e6be031b89e43e7a96d55d7ecd0fba1d7fd6f8d8
    https://github.com/scummvm/scummvm/commit/e6be031b89e43e7a96d55d7ecd0fba1d7fd6f8d8
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-07-21T14:14:53+02:00

Commit Message:
AUDIO: Create a wrapper around the PCSpeaker emulator that handles the mixer stream

Changed paths:
    audio/softsynth/pcspk.cpp
    audio/softsynth/pcspk.h
    engines/agi/preagi/preagi.cpp
    engines/agi/preagi/preagi.h
    engines/agi/sound_a2.h
    engines/agi/sound_coco3.h
    engines/avalanche/sound.cpp
    engines/avalanche/sound.h
    engines/chamber/chamber.cpp
    engines/chamber/chamber.h
    engines/chamber/sound.cpp
    engines/director/sound.cpp
    engines/director/sound.h
    engines/efh/efh.h
    engines/efh/init.cpp
    engines/efh/sound.cpp
    engines/freescape/sound.h
    engines/glk/glk.cpp
    engines/glk/pc_speaker.cpp
    engines/glk/pc_speaker.h
    engines/gob/sound/pcspeaker.cpp
    engines/gob/sound/pcspeaker.h
    engines/gob/sound/sound.cpp
    engines/hugo/sound.cpp
    engines/hugo/sound.h
    engines/kyra/sound/drivers/pcspeaker_v2.cpp
    engines/kyra/sound/sound_intern.h
    engines/made/scriptfuncs.cpp
    engines/scumm/imuse/drivers/pcspk.h
    engines/testbed/sound.cpp


diff --git a/audio/softsynth/pcspk.cpp b/audio/softsynth/pcspk.cpp
index 665fea30350..fa689e0a10c 100644
--- a/audio/softsynth/pcspk.cpp
+++ b/audio/softsynth/pcspk.cpp
@@ -27,17 +27,17 @@
 
 namespace Audio {
 
-PCSpeaker::Command::Command(WaveForm aWaveForm, float aFrequency, uint32 aLength) :
+PCSpeakerStream::Command::Command(PCSpeaker::WaveForm aWaveForm, float aFrequency, uint32 aLength) :
 	waveForm(aWaveForm), frequency(aFrequency), length(aLength) { }
 
-const PCSpeaker::generatorFunc PCSpeaker::generateWave[] =
-	{&PCSpeaker::generateSquare, &PCSpeaker::generateSine,
-	 &PCSpeaker::generateSaw,    &PCSpeaker::generateTriangle,
-	 &PCSpeaker::generateSilence};
+const PCSpeakerStream::generatorFunc PCSpeakerStream::generateWave[] =
+	{&PCSpeakerStream::generateSquare, &PCSpeakerStream::generateSine,
+	 &PCSpeakerStream::generateSaw,    &PCSpeakerStream::generateTriangle,
+	 &PCSpeakerStream::generateSilence};
 
-PCSpeaker::PCSpeaker(int rate) {
+PCSpeakerStream::PCSpeakerStream(int rate) {
 	_rate = rate;
-	_wave = kWaveFormSquare;
+	_wave = PCSpeaker::kWaveFormSquare;
 	_playForever = false;
 	_oscLength = 0;
 	_oscSamples = 0;
@@ -48,14 +48,14 @@ PCSpeaker::PCSpeaker(int rate) {
 	_commandActive = false;
 }
 
-PCSpeaker::~PCSpeaker() {
+PCSpeakerStream::~PCSpeakerStream() {
 	delete _commandQueue;
 }
 
-void PCSpeaker::play(WaveForm wave, int freq, int32 length) {
+void PCSpeakerStream::play(PCSpeaker::WaveForm wave, int freq, int32 length) {
 	Common::StackLock lock(_mutex);
 
-	assert((wave >= kWaveFormSquare) && (wave <= kWaveFormTriangle));
+	assert((wave >= PCSpeaker::kWaveFormSquare) && (wave <= PCSpeaker::kWaveFormTriangle));
 
 	if (_commandActive || !_commandQueue->empty())
 		// Currently playing back a queued instruction. Stop playback and clear
@@ -75,7 +75,7 @@ void PCSpeaker::play(WaveForm wave, int freq, int32 length) {
 	_mixedSamples = 0;
 }
 
-void PCSpeaker::playQueue(WaveForm wave, float freq, uint32 lengthus) {
+void PCSpeakerStream::playQueue(PCSpeaker::WaveForm wave, float freq, uint32 lengthus) {
 	Common::StackLock lock(_mutex);
 
 	// Put the new instruction in the queue. This will be picked up by the
@@ -83,7 +83,7 @@ void PCSpeaker::playQueue(WaveForm wave, float freq, uint32 lengthus) {
 	_commandQueue->push(Command(wave, freq, lengthus));
 }
 
-void PCSpeaker::stop(int32 delay) {
+void PCSpeakerStream::stop(int32 delay) {
 	Common::StackLock lock(_mutex);
 
 	_commandQueue->clear();
@@ -96,17 +96,17 @@ void PCSpeaker::stop(int32 delay) {
 	_playForever = false;
 }
 
-void PCSpeaker::setVolume(byte volume) {
+void PCSpeakerStream::setVolume(byte volume) {
 	_volume = volume;
 }
 
-bool PCSpeaker::isPlaying() const {
+bool PCSpeakerStream::isPlaying() const {
 	Common::StackLock lock(_mutex);
 
 	return _remainingSamples != 0 || !_commandQueue->empty();
 }
 
-int PCSpeaker::readBuffer(int16 *buffer, const int numSamples) {
+int PCSpeakerStream::readBuffer(int16 *buffer, const int numSamples) {
 	Common::StackLock lock(_mutex);
 
 	// The total number of samples generated.
@@ -158,11 +158,11 @@ int PCSpeaker::readBuffer(int16 *buffer, const int numSamples) {
 	return numSamples;
 }
 
-int8 PCSpeaker::generateSquare(uint32 x, uint32 oscLength) {
+int8 PCSpeakerStream::generateSquare(uint32 x, uint32 oscLength) {
 	return (x < (oscLength / 2)) ? 127 : -128;
 }
 
-int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
+int8 PCSpeakerStream::generateSine(uint32 x, uint32 oscLength) {
 	if (oscLength == 0)
 		return 0;
 
@@ -170,14 +170,14 @@ int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
 	return CLIP<int16>((int16) (128 * sin(2.0 * M_PI * x / oscLength)), -128, 127);
 }
 
-int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) {
+int8 PCSpeakerStream::generateSaw(uint32 x, uint32 oscLength) {
 	if (oscLength == 0)
 		return 0;
 
 	return ((x * (65536 / oscLength)) >> 8) - 128;
 }
 
-int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) {
+int8 PCSpeakerStream::generateTriangle(uint32 x, uint32 oscLength) {
 	if (oscLength == 0)
 		return 0;
 
@@ -186,10 +186,60 @@ int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) {
 	return (x <= (oscLength / 2)) ? y : (256 - y);
 }
 
-int8 PCSpeaker::generateSilence(uint32 x, uint32 oscLength) {
+int8 PCSpeakerStream::generateSilence(uint32 x, uint32 oscLength) {
 	return 0;
 }
 
+PCSpeaker::PCSpeaker() : _speakerStream(nullptr) {
+}
+
+PCSpeaker::~PCSpeaker() {
+	quit();
+}
+
+bool PCSpeaker::init() {
+	quit();
+
+	Mixer *mixer = g_system->getMixer();
+	if (!mixer || !mixer->isReady())
+		return false;
+
+	_speakerStream = new Audio::PCSpeakerStream(mixer->getOutputRate());
+	mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
+	                  _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	return true;
+}
+
+void PCSpeaker::quit() {
+	Mixer *mixer = g_system->getMixer();
+	if (!mixer)
+		return;
+
+	mixer->stopHandle(_speakerHandle);
+	delete _speakerStream;
+	_speakerStream = nullptr;
+}
+
+void PCSpeaker::play(WaveForm wave, int freq, int32 length) {
+	assert(_speakerStream);
+	_speakerStream->play(wave, freq, length);
+}
+
+void PCSpeaker::playQueue(WaveForm wave, float freq, uint32 lengthus) {
+	assert(_speakerStream);
+	_speakerStream->playQueue(wave, freq, lengthus);
+}
+
+void PCSpeaker::stop(int32 delay) {
+	assert(_speakerStream);
+	_speakerStream->stop(delay);
+}
+
+bool PCSpeaker::isPlaying() const {
+	assert(_speakerStream);
+	return _speakerStream->isPlaying();
+}
+
 } // End of namespace Audio
 
 
diff --git a/audio/softsynth/pcspk.h b/audio/softsynth/pcspk.h
index 95572fc7206..13d2aaf8469 100644
--- a/audio/softsynth/pcspk.h
+++ b/audio/softsynth/pcspk.h
@@ -23,12 +23,15 @@
 #define AUDIO_SOFTSYNTH_PCSPK_H
 
 #include "audio/audiostream.h"
+#include "audio/mixer.h"
 #include "common/mutex.h"
 #include "common/queue.h"
 
 namespace Audio {
 
-class PCSpeaker : public AudioStream {
+class PCSpeakerStream;
+
+class PCSpeaker {
 public:
 	enum WaveForm {
 		kWaveFormSquare = 0,
@@ -38,25 +41,71 @@ public:
 		kWaveFormSilence
 	};
 
+public:
+	PCSpeaker();
+	~PCSpeaker();
+
+	bool init();
+	void quit();
+
+	/** Play a note for length ms.
+	 *
+	 *  If length is negative, play until told to stop.
+	 */
+	void play(WaveForm wave, int freq, int32 length);
+
+	/**
+	 * Queue the specified playback instruction. It will be executed when all
+	 * previously queued instructions have finished. Use this method for
+	 * playback of effects which require timing precision of less than a
+	 * millisecond.
+	 *
+	 * Calling this method will terminate any waveform started with the play
+	 * method. Calling the play method will terminate the active queued
+	 * instruction and clear the instruction queue.
+	 *
+	 * Use isPlaying to check if all queued instructions have finished playing.
+	 * This will return true even if the current instruction is "playing"
+	 * silence.
+	 *
+	 * @param wave The waveform to use. For PC speaker, use square wave or
+	 * silence.
+	 * @param freq The frequency (in Hertz) to play.
+	 * @param lengthus The length in microseconds for which to play the
+	 * waveform.
+	 */
+	void playQueue(WaveForm wave, float freq, uint32 lengthus);
+	/** Stop the currently playing note after delay ms. */
+	void stop(int32 delay = 0);
+
+	bool isPlaying() const;
+
+private:
+	PCSpeakerStream *_speakerStream;
+	SoundHandle _speakerHandle;
+};
+
+
+class PCSpeakerStream : public AudioStream {
 protected:
 	// PC speaker instruction: play this waveform at frequency x for y microseconds.
 	struct Command {
-		WaveForm waveForm;
+		PCSpeaker::WaveForm waveForm;
 		float frequency;
 		uint32 length;
 
-		Command(WaveForm waveForm, float frequency, uint32 length);
+		Command(PCSpeaker::WaveForm waveForm, float frequency, uint32 length);
 	};
 
 public:
-	PCSpeaker(int rate = 44100);
-	~PCSpeaker();
+	PCSpeakerStream(int rate = 44100);
+	~PCSpeakerStream();
 
 	/** Play a note for length ms.
 	 *
 	 *  If length is negative, play until told to stop.
 	 */
-	void play(WaveForm wave, int freq, int32 length);
+	void play(PCSpeaker::WaveForm wave, int freq, int32 length);
 	/**
 	 * Queue the specified playback instruction. It will be executed when all
 	 * previously queued instructions have finished. Use this method for
@@ -77,7 +126,7 @@ public:
 	 * @param lengthus The length in microseconds for which to play the
 	 * waveform.
 	 */
-	void playQueue(WaveForm wave, float freq, uint32 lengthus);
+	void playQueue(PCSpeaker::WaveForm wave, float freq, uint32 lengthus);
 	/** Stop the currently playing note after delay ms. */
 	void stop(int32 delay = 0);
 	/** Adjust the volume. */
@@ -96,7 +145,7 @@ protected:
 	Common::Mutex _mutex;
 
 	int _rate;
-	WaveForm _wave;
+	PCSpeaker::WaveForm _wave;
 	bool _playForever;
 	uint32 _oscLength;
 	uint32 _oscSamples;
diff --git a/engines/agi/preagi/preagi.cpp b/engines/agi/preagi/preagi.cpp
index db05873d1a9..98b88058558 100644
--- a/engines/agi/preagi/preagi.cpp
+++ b/engines/agi/preagi/preagi.cpp
@@ -37,8 +37,6 @@ PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) :
 	syncSoundSettings();
 
 	memset(&_debug, 0, sizeof(struct AgiDebug));
-
-	_speakerHandle = new Audio::SoundHandle();
 }
 
 void PreAgiEngine::initialize() {
@@ -57,9 +55,8 @@ void PreAgiEngine::initialize() {
 
 	_gfx->initVideo();
 
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, _speakerHandle,
-	                   _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 
 	debugC(2, kDebugLevelMain, "Detect game");
 
@@ -73,9 +70,7 @@ void PreAgiEngine::initialize() {
 }
 
 PreAgiEngine::~PreAgiEngine() {
-	_mixer->stopHandle(*_speakerHandle);
-	delete _speakerStream;
-	delete _speakerHandle;
+	delete _speaker;
 
 	delete _gfx;
 	delete _font;
@@ -288,7 +283,7 @@ int PreAgiEngine::getSelection(SelectionTypes type) {
 bool PreAgiEngine::playSpeakerNote(int16 frequency, int32 length, WaitOptions options) {
 	// play note, unless this is a pause
 	if (frequency != 0) {
-		_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
 	}
 
 	// wait for note length
@@ -297,7 +292,7 @@ bool PreAgiEngine::playSpeakerNote(int16 frequency, int32 length, WaitOptions op
 	// stop note if the wait was interrupted
 	if (!completed) {
 		if (frequency != 0) {
-			_speakerStream->stop();
+			_speaker->stop();
 		}
 	}
 
diff --git a/engines/agi/preagi/preagi.h b/engines/agi/preagi/preagi.h
index 3355f999517..6efa6a95ea0 100644
--- a/engines/agi/preagi/preagi.h
+++ b/engines/agi/preagi/preagi.h
@@ -25,7 +25,6 @@
 #include "agi/agi.h"
 
 namespace Audio {
-class SoundHandle;
 class PCSpeaker;
 }
 
@@ -112,8 +111,7 @@ protected:
 private:
 	int _defaultColor;
 
-	Audio::PCSpeaker *_speakerStream;
-	Audio::SoundHandle *_speakerHandle;
+	Audio::PCSpeaker *_speaker;
 };
 
 } // End of namespace Agi
diff --git a/engines/agi/sound_a2.h b/engines/agi/sound_a2.h
index ea31364b75b..1f1fdd5dccb 100644
--- a/engines/agi/sound_a2.h
+++ b/engines/agi/sound_a2.h
@@ -52,7 +52,7 @@ public:
 private:
 	Common::Mutex _mutex;
 	bool _isPlaying;
-	Audio::PCSpeaker _speaker;
+	Audio::PCSpeakerStream _speaker;
 };
 
 } // End of namespace Agi
diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h
index f21b30f5781..df399fa94e2 100644
--- a/engines/agi/sound_coco3.h
+++ b/engines/agi/sound_coco3.h
@@ -52,7 +52,7 @@ public:
 private:
 	Common::Mutex _mutex;
 	bool _isPlaying;
-	Audio::PCSpeaker _speaker;
+	Audio::PCSpeakerStream _speaker;
 };
 
 } // End of namespace Agi
diff --git a/engines/avalanche/sound.cpp b/engines/avalanche/sound.cpp
index 888f7352cc7..13edf49b030 100644
--- a/engines/avalanche/sound.cpp
+++ b/engines/avalanche/sound.cpp
@@ -29,13 +29,12 @@ namespace Avalanche {
 
 SoundHandler::SoundHandler(AvalancheEngine *vm) : _vm(vm) {
 	_soundFl = true;
-	_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
-	_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-						_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 }
 
 SoundHandler::~SoundHandler() {
-	_vm->_mixer->stopHandle(_speakerHandle);
+	delete _speaker;
 }
 
 /**
@@ -70,7 +69,7 @@ void SoundHandler::playNote(int freq, int length) {
 		return;
 
 	// Start a note playing (we will stop it when the timer expires).
-	_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, freq, length);
+	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, freq, length);
 }
 
 void SoundHandler::click() {
diff --git a/engines/avalanche/sound.h b/engines/avalanche/sound.h
index 6dfab8f8628..848beff8b6a 100644
--- a/engines/avalanche/sound.h
+++ b/engines/avalanche/sound.h
@@ -46,8 +46,7 @@ public:
 
 private:
 	AvalancheEngine *_vm;
-	Audio::PCSpeaker *_speakerStream;
-	Audio::SoundHandle _speakerHandle;
+	Audio::PCSpeaker *_speaker;
 };
 
 } // End of namespace Avalanche
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 4cb07272ccb..f4cbc665fca 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -55,11 +55,6 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
 	_videoMode = Common::kRenderCGA;
 	_screenH = _screenW = _screenBits = _screenBPL = _screenPPB = 0;
 	_line_offset = _line_offset2 = _fontHeight = _fontWidth = 0;
-
-
-
-	_speakerHandle = NULL;
-	_speakerStream = NULL;
 }
 
 ChamberEngine::~ChamberEngine() {
diff --git a/engines/chamber/chamber.h b/engines/chamber/chamber.h
index 0c63e5e684d..59f21177d36 100644
--- a/engines/chamber/chamber.h
+++ b/engines/chamber/chamber.h
@@ -85,8 +85,7 @@ public:
 	uint8 _fontWidth; ///< Font height
 
 
-	Audio::PCSpeaker *_speakerStream;
-	Audio::SoundHandle *_speakerHandle;
+	Audio::PCSpeaker *_speaker;
 
 private:
 	const ADGameDescription *_gameDescription;
diff --git a/engines/chamber/sound.cpp b/engines/chamber/sound.cpp
index 17130d4a9ff..38235f5e3b5 100644
--- a/engines/chamber/sound.cpp
+++ b/engines/chamber/sound.cpp
@@ -70,8 +70,8 @@ static void speakerPlay(pcsample_t *sample) {
 		uint32 delayOff = delay1 * 16; // Around 335 ticks per second
 		uint32 delayOn = delay2 * 16;
 
-		g_vm->_speakerStream->playQueue(Audio::PCSpeaker::kWaveFormSilence, frequency, delayOff);
-		g_vm->_speakerStream->playQueue(Audio::PCSpeaker::kWaveFormSquare, frequency, delayOn);
+		g_vm->_speaker->playQueue(Audio::PCSpeaker::kWaveFormSilence, frequency, delayOff);
+		g_vm->_speaker->playQueue(Audio::PCSpeaker::kWaveFormSquare, frequency, delayOn);
 
 		if (sample->delay1sweep & 0xF000)
 			delay1 -= sample->delay1sweep & 0xFFF;
@@ -126,16 +126,12 @@ void ChamberEngine::initSound() {
 	// Setup mixer
 	syncSoundSettings();
 
-	_speakerHandle = new Audio::SoundHandle();
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, _speakerHandle,
-		_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 }
 
 void ChamberEngine::deinitSound() {
-	_mixer->stopHandle(*_speakerHandle);
-	delete g_vm->_speakerHandle;
-	delete g_vm->_speakerStream;
+	delete g_vm->_speaker;
 }
 
 } // End of namespace Chamber
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 75ed5d57e95..8d3772095e9 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -54,8 +54,7 @@ DirectorSound::DirectorSound(Window *window) : _window(window) {
 	_mixer = g_system->getMixer();
 
 	_speaker = new Audio::PCSpeaker();
-	_mixer->playStream(Audio::Mixer::kSFXSoundType,
-		&_pcSpeakerHandle, _speaker, -1, 50, 0, DisposeAfterUse::NO, true);
+	_speaker->init();
 
 	_enable = true;
 }
@@ -546,7 +545,7 @@ void DirectorSound::stopSound() {
 	}
 
 	_mixer->stopHandle(_scriptSound);
-	_mixer->stopHandle(_pcSpeakerHandle);
+	_speaker->quit();
 }
 
 void DirectorSound::systemBeep() {
diff --git a/engines/director/sound.h b/engines/director/sound.h
index 5c83acf65a6..1ef0f8cb78f 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -165,7 +165,6 @@ private:
 	Audio::SoundHandle _scriptSound;
 	Audio::Mixer *_mixer;
 	Audio::PCSpeaker *_speaker;
-	Audio::SoundHandle _pcSpeakerHandle;
 
 	// these two were used in fplay xobj
 	Common::Queue<Common::String> _fplayQueue;
diff --git a/engines/efh/efh.h b/engines/efh/efh.h
index 29e93958256..448d856960f 100644
--- a/engines/efh/efh.h
+++ b/engines/efh/efh.h
@@ -640,8 +640,7 @@ private:
 
 	int16 _regenCounter;
 
-	Audio::PCSpeaker *_speakerStream;
-	Audio::SoundHandle _speakerHandle;
+	Audio::PCSpeaker *_speaker;
 };
 
 } // End of namespace Efh
diff --git a/engines/efh/init.cpp b/engines/efh/init.cpp
index bed2900f5ea..9ef80f076c0 100644
--- a/engines/efh/init.cpp
+++ b/engines/efh/init.cpp
@@ -394,8 +394,6 @@ EfhEngine::EfhEngine(OSystem *syst, const ADGameDescription *gd) : Engine(syst),
 	_loadSaveSlot = -1;
 	_saveAuthorized = false;
 
-	_speakerStream = nullptr;
-
 	if (ConfMan.hasKey("save_slot")) {
 		int saveSlot = ConfMan.getInt("save_slot");
 		if (saveSlot >= 0 && saveSlot <= 999)
diff --git a/engines/efh/sound.cpp b/engines/efh/sound.cpp
index b5feec4e216..e440f48f08b 100644
--- a/engines/efh/sound.cpp
+++ b/engines/efh/sound.cpp
@@ -36,9 +36,9 @@ void EfhEngine::songDelay(int delay) {
 void EfhEngine::playNote(int frequencyIndex, int totalDelay) {
 	debugC(3, kDebugEngine, "playNote %d %d", frequencyIndex, totalDelay);
 	if (frequencyIndex > 0 && frequencyIndex < 72) {
-		_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, 0x1234DD / kSoundFrequency[frequencyIndex], -1);
+		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, 0x1234DD / kSoundFrequency[frequencyIndex], -1);
 		songDelay(totalDelay);
-		_speakerStream->stop();
+		_speaker->stop();
 	} else {
 		warning("playNote - Skip note with frequency index %d", frequencyIndex);
 	}
@@ -47,9 +47,8 @@ void EfhEngine::playNote(int frequencyIndex, int totalDelay) {
 Common::KeyCode EfhEngine::playSong(uint8 *buffer) {
 	debugC(3, kDebugEngine, "playSong");
 
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-					   _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 
 	Common::KeyCode inputChar = Common::KEYCODE_INVALID;
 	int totalDelay = 0;
@@ -92,9 +91,8 @@ Common::KeyCode EfhEngine::playSong(uint8 *buffer) {
 		}
 	} while (stopFl != 0 && !shouldQuit());
 
-	_mixer->stopHandle(_speakerHandle);
-	delete _speakerStream;
-	_speakerStream = nullptr;
+	delete _speaker;
+	_speaker = nullptr;
 
 	return inputChar;
 }
@@ -111,28 +109,25 @@ void EfhEngine::generateSound1(int lowFreq, int highFreq, int duration) {
 	uint16 var2 = 0;
 	duration /= 20;
 
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-					   _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 
-	_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, highFreq, -1);
+	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, highFreq, -1);
 	songDelay(10);
-	_speakerStream->stop();
+	_speaker->stop();
 
 
 	for (int i = 0; i < duration; ++i) {
 		var2 = ROR(var2 + 0x9248, 3);
 		int val = (var2 * (highFreq - lowFreq)) >> 16;
 
-		_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, lowFreq + val, -1);
+		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, lowFreq + val, -1);
 		songDelay(10);
-		_speakerStream->stop();
+		_speaker->stop();
 	}
 
-
-	_mixer->stopHandle(_speakerHandle);
-	delete _speakerStream;
-	_speakerStream = nullptr;
+	delete _speaker;
+	_speaker = nullptr;
 }
 
 void EfhEngine::generateSound2(int startFreq, int endFreq, int speed) {
@@ -151,42 +146,38 @@ void EfhEngine::generateSound2(int startFreq, int endFreq, int speed) {
 	else
 		delta = 50;
 
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-					   _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 
 	int curFreq = startFreq;
 
 	do {
-		_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, curFreq, -1);
+		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, curFreq, -1);
 		// The original is just looping, making the sound improperly timed as the length of a loop is directly related to the speed of the CPU
 		// Dividing by 10 is just a guess based on how it sounds. I suspect it may be still too much
 		songDelay(speed);
-		_speakerStream->stop();
+		_speaker->stop();
 		curFreq += delta;
 	} while (curFreq < endFreq && !shouldQuit());
 
 
-	_mixer->stopHandle(_speakerHandle);
-	delete _speakerStream;
-	_speakerStream = nullptr;
+	delete _speaker;
+	_speaker = nullptr;
 
 }
 
 void EfhEngine::generateSound3() {
 	debugC(3, kDebugEngine, "generateSound3");
-	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-					   _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 
-	_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, 88, -1);
+	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, 88, -1);
 	// The original makes me think the delay is so short it's not possible to hear. So that delay is guessed (and short)
 	songDelay(30);
-	_speakerStream->stop();
+	_speaker->stop();
 
-	_mixer->stopHandle(_speakerHandle);
-	delete _speakerStream;
-	_speakerStream = nullptr;
+	delete _speaker;
+	_speaker = nullptr;
 }
 
 void EfhEngine::generateSound4(int repeat) {
diff --git a/engines/freescape/sound.h b/engines/freescape/sound.h
index e55d44caf66..1f5849ebdc2 100644
--- a/engines/freescape/sound.h
+++ b/engines/freescape/sound.h
@@ -51,11 +51,11 @@ struct soundSpeakerFx {
 	Common::Array<struct soundSpeakerFx *>additionalSteps;
 };
 
-class SizedPCSpeaker : public Audio::PCSpeaker {
+class SizedPCSpeaker : public Audio::PCSpeakerStream {
 public:
 	bool endOfStream() const override { return !isPlaying(); }
 };
 
 } // End of namespace Freescape
 
-#endif // FREESCAPE_SOUND_H
\ No newline at end of file
+#endif // FREESCAPE_SOUND_H
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 8acb805a1b8..56284a7c81d 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -82,7 +82,7 @@ void GlkEngine::initialize() {
 	_screen->initialize();
 	_clipboard = new Clipboard();
 	_events = new Events();
-	_pcSpeaker = new PCSpeaker(_mixer);
+	_pcSpeaker = new PCSpeaker();
 	_pictures = new Pictures();
 	_selection = new Selection();
 	_sounds = new Sounds();
diff --git a/engines/glk/pc_speaker.cpp b/engines/glk/pc_speaker.cpp
index cacec79cc81..91fc00c6199 100644
--- a/engines/glk/pc_speaker.cpp
+++ b/engines/glk/pc_speaker.cpp
@@ -24,28 +24,26 @@
 
 namespace Glk {
 
-PCSpeaker::PCSpeaker(Audio::Mixer *mixer) : _mixer(mixer) {
-	_stream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType,
-			&_handle, _stream, -1, 50, 0, DisposeAfterUse::NO, true);
+PCSpeaker::PCSpeaker() {
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 }
 
 PCSpeaker::~PCSpeaker() {
-	_mixer->stopHandle(_handle);
-	delete _stream;
+	delete _speaker;
 }
 
 void PCSpeaker::speakerOn(int16 frequency, int32 length) {
-	_stream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
 }
 
 void PCSpeaker::speakerOff() {
-	_stream->stop();
+	_speaker->stop();
 }
 
 void PCSpeaker::onUpdate(uint32 millis) {
-	if (_stream->isPlaying())
-		_stream->stop(millis);
+	if (_speaker->isPlaying())
+		_speaker->stop(millis);
 }
 
 } // End of namespace Glk
diff --git a/engines/glk/pc_speaker.h b/engines/glk/pc_speaker.h
index 3db6497a326..136a5aa809a 100644
--- a/engines/glk/pc_speaker.h
+++ b/engines/glk/pc_speaker.h
@@ -22,7 +22,7 @@
 #ifndef GLK_PC_SPEAKER_H
 #define GLK_PC_SPEAKER_H
 
-#include "audio/mixer.h"
+#include "common/scummsys.h"
 
 namespace Audio {
 class PCSpeaker;
@@ -32,11 +32,9 @@ namespace Glk {
 
 class PCSpeaker {
 private:
-	Audio::Mixer *_mixer;
-	Audio::PCSpeaker *_stream;
-	Audio::SoundHandle _handle;
+	Audio::PCSpeaker *_speaker;
 public:
-	PCSpeaker(Audio::Mixer *mixer);
+	PCSpeaker();
 	~PCSpeaker();
 
 	void speakerOn(int16 frequency, int32 length = -1);
diff --git a/engines/gob/sound/pcspeaker.cpp b/engines/gob/sound/pcspeaker.cpp
index a14f920c824..ecf23c0b87b 100644
--- a/engines/gob/sound/pcspeaker.cpp
+++ b/engines/gob/sound/pcspeaker.cpp
@@ -30,29 +30,26 @@
 
 namespace Gob {
 
-PCSpeaker::PCSpeaker(Audio::Mixer &mixer) : _mixer(&mixer) {
-
-	_stream = new Audio::PCSpeaker(_mixer->getOutputRate());
-	_mixer->playStream(Audio::Mixer::kSFXSoundType,
-			&_handle, _stream, -1, 50, 0, DisposeAfterUse::NO, true);
+PCSpeaker::PCSpeaker() {
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 }
 
 PCSpeaker::~PCSpeaker() {
-	_mixer->stopHandle(_handle);
-	delete _stream;
+	delete _speaker;
 }
 
 void PCSpeaker::speakerOn(int16 frequency, int32 length) {
-	_stream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
 }
 
 void PCSpeaker::speakerOff() {
-	_stream->stop();
+	_speaker->stop();
 }
 
 void PCSpeaker::onUpdate(uint32 millis) {
-	if (_stream->isPlaying())
-		_stream->stop(millis);
+	if (_speaker->isPlaying())
+		_speaker->stop(millis);
 }
 
 } // End of namespace Gob
diff --git a/engines/gob/sound/pcspeaker.h b/engines/gob/sound/pcspeaker.h
index 15b65e4c7d2..5bbf7215ffa 100644
--- a/engines/gob/sound/pcspeaker.h
+++ b/engines/gob/sound/pcspeaker.h
@@ -28,7 +28,7 @@
 #ifndef GOB_SOUND_PCSPEAKER_H
 #define GOB_SOUND_PCSPEAKER_H
 
-#include "audio/mixer.h"
+#include "common/scummsys.h"
 
 namespace Audio {
 class PCSpeaker;
@@ -38,7 +38,7 @@ namespace Gob {
 
 class PCSpeaker {
 public:
-	PCSpeaker(Audio::Mixer &mixer);
+	PCSpeaker();
 	~PCSpeaker();
 
 	void speakerOn(int16 frequency, int32 length = -1);
@@ -46,10 +46,7 @@ public:
 	void onUpdate(uint32 millis);
 
 private:
-	Audio::Mixer *_mixer;
-
-	Audio::PCSpeaker *_stream;
-	Audio::SoundHandle _handle;
+	Audio::PCSpeaker *_speaker;
 };
 
 } // End of namespace Gob
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index d4c216dd255..3d3e5bdfe38 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -45,7 +45,7 @@
 namespace Gob {
 
 Sound::Sound(GobEngine *vm) : _vm(vm) {
-	_pcspeaker = new PCSpeaker(*_vm->_mixer);
+	_pcspeaker = new PCSpeaker();
 	_blaster = new SoundBlaster(*_vm->_mixer);
 
 	_adlPlayer = nullptr;
diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp
index 926c66eb049..f8a224a373f 100644
--- a/engines/hugo/sound.cpp
+++ b/engines/hugo/sound.cpp
@@ -120,9 +120,8 @@ void MidiPlayer::sendToChannel(byte channel, uint32 b) {
 
 SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
 	_midiPlayer = new MidiPlayer();
-	_speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
-	_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
-						_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker = new Audio::PCSpeaker();
+	_speaker->init();
 	_DOSSongPtr = nullptr;
 	_curPriority = 0;
 	_pcspkrTimer = 0;
@@ -133,8 +132,7 @@ SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) {
 
 SoundHandler::~SoundHandler() {
 	_vm->getTimerManager()->removeTimerProc(&loopPlayer);
-	_vm->_mixer->stopHandle(_speakerHandle);
-	delete _speakerStream;
+	delete _speaker;
 	delete _midiPlayer;
 }
 
@@ -288,7 +286,7 @@ void SoundHandler::pcspkr_player() {
 	// Check the timer state..
 	if (!_pcspkrTimer) {
 		// A note just finished, stop the sound (if any) and return.
-		_speakerStream->stop();
+		_speaker->stop();
 		return;
 	} else if (_pcspkrTimer > 0) {
 		// A (rest or normal) note is still playing, return.
@@ -367,13 +365,13 @@ void SoundHandler::pcspkr_player() {
 			count *= (1 << (3 - _pcspkrOctave));
 
 		// Start a note playing (we will stop it when the timer expires).
-		_speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, kHugoCNT / count, -1);
+		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, kHugoCNT / count, -1);
 		_pcspkrTimer = _pcspkrNoteDuration;
 		_DOSSongPtr++;
 		break;
 	case '.':
 		// Play a 'rest note' by being silent for a bit.
-		_speakerStream->stop();
+		_speaker->stop();
 		_pcspkrTimer = _pcspkrNoteDuration;
 		_DOSSongPtr++;
 		break;
diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h
index 0f9e2455e66..be6a0da59d2 100644
--- a/engines/hugo/sound.h
+++ b/engines/hugo/sound.h
@@ -94,8 +94,7 @@ private:
 	HugoEngine *_vm;
 	Audio::SoundHandle _soundHandle;
 	MidiPlayer *_midiPlayer;
-	Audio::PCSpeaker *_speakerStream;
-	Audio::SoundHandle _speakerHandle;
+	Audio::PCSpeaker *_speaker;
 
 	void stopSound();
 	void stopMusic();
diff --git a/engines/kyra/sound/drivers/pcspeaker_v2.cpp b/engines/kyra/sound/drivers/pcspeaker_v2.cpp
index afe2a54625b..aca3de87d95 100644
--- a/engines/kyra/sound/drivers/pcspeaker_v2.cpp
+++ b/engines/kyra/sound/drivers/pcspeaker_v2.cpp
@@ -35,7 +35,7 @@ MidiDriver_PCSpeaker::MidiDriver_PCSpeaker(Audio::Mixer *mixer)
 	for (int i = 0; i < 2; ++i)
 		_note[i].hardwareChannel = 0xFF;
 
-	_speaker = new Audio::PCSpeaker(_rate);
+	_speaker = new Audio::PCSpeakerStream(_rate);
 	assert(_speaker);
 	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
 
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index b1b8696d3e0..2da08bcb859 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -37,7 +37,7 @@ class EuphonyPlayer;
 class TownsPC98_AudioDriver;
 
 namespace Audio {
-class PCSpeaker;
+class PCSpeakerStream;
 class MaxTrax;
 } // End of namespace Audio
 
@@ -265,7 +265,7 @@ public:
 	int getRate() const override { return _rate; }
 private:
 	Common::Mutex _mutex;
-	Audio::PCSpeaker *_speaker;
+	Audio::PCSpeakerStream *_speaker;
 	int _rate;
 
 	struct Channel {
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
index bacf1d73db4..981e6bdf9d2 100644
--- a/engines/made/scriptfuncs.cpp
+++ b/engines/made/scriptfuncs.cpp
@@ -39,8 +39,8 @@ ScriptFunctions::ScriptFunctions(MadeEngine *vm) : _vm(vm), _soundStarted(false)
 	// Initialize the two tone generators
 	_pcSpeaker1 = new Audio::PCSpeaker();
 	_pcSpeaker2 = new Audio::PCSpeaker();
-	_vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle1, _pcSpeaker1);
-	_vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_pcSpeakerHandle2, _pcSpeaker2);
+	_pcSpeaker1->init();
+	_pcSpeaker2->init();
 	_soundResource = nullptr;
 }
 
diff --git a/engines/scumm/imuse/drivers/pcspk.h b/engines/scumm/imuse/drivers/pcspk.h
index 7d30bc337eb..b0471ea1efe 100644
--- a/engines/scumm/imuse/drivers/pcspk.h
+++ b/engines/scumm/imuse/drivers/pcspk.h
@@ -47,7 +47,7 @@ protected:
 	void onTimer() override;
 
 private:
-	Audio::PCSpeaker _pcSpk;
+	Audio::PCSpeakerStream _pcSpk;
 	int _effectTimer;
 	uint8 _randBase;
 
diff --git a/engines/testbed/sound.cpp b/engines/testbed/sound.cpp
index 523074959b2..fb69bafce06 100644
--- a/engines/testbed/sound.cpp
+++ b/engines/testbed/sound.cpp
@@ -55,9 +55,9 @@ SoundSubsystemDialog::SoundSubsystemDialog() : TestbedInteractionDialog(80, 60,
 	_mixer = g_system->getMixer();
 
 	// the three streams to be mixed
-	Audio::PCSpeaker *s1 = new Audio::PCSpeaker();
-	Audio::PCSpeaker *s2 = new Audio::PCSpeaker();
-	Audio::PCSpeaker *s3 = new Audio::PCSpeaker();
+	Audio::PCSpeakerStream *s1 = new Audio::PCSpeakerStream();
+	Audio::PCSpeakerStream *s2 = new Audio::PCSpeakerStream();
+	Audio::PCSpeakerStream *s3 = new Audio::PCSpeakerStream();
 
 	s1->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
 	s2->play(Audio::PCSpeaker::kWaveFormSine, 1200, -1);
@@ -125,7 +125,7 @@ TestExitStatus SoundSubsystem::playBeeps() {
 		return kTestSkipped;
 	}
 
-	Audio::PCSpeaker *speaker = new Audio::PCSpeaker();
+	Audio::PCSpeakerStream *speaker = new Audio::PCSpeakerStream();
 	Audio::Mixer *mixer = g_system->getMixer();
 	Audio::SoundHandle handle;
 	mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, speaker);
@@ -306,11 +306,11 @@ TestExitStatus SoundSubsystem::sampleRates() {
 	TestExitStatus passed = kTestPassed;
 	Audio::Mixer *mixer = g_system->getMixer();
 
-	Audio::PCSpeaker *s1 = new Audio::PCSpeaker();
+	Audio::PCSpeakerStream *s1 = new Audio::PCSpeakerStream();
 	// Stream at half sampling rate
-	Audio::PCSpeaker *s2 = new Audio::PCSpeaker(s1->getRate() - 10000);
+	Audio::PCSpeakerStream *s2 = new Audio::PCSpeakerStream(s1->getRate() - 10000);
 	// Stream at twice sampling rate
-	Audio::PCSpeaker *s3 = new Audio::PCSpeaker(s1->getRate() + 10000);
+	Audio::PCSpeakerStream *s3 = new Audio::PCSpeakerStream(s1->getRate() + 10000);
 
 	s1->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
 	s2->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);




More information about the Scummvm-git-logs mailing list