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

sluicebox noreply at scummvm.org
Wed Feb 25 23:15:44 UTC 2026


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:
ba8d370f8d AGI: Migrate Apple II and CoCo3 sound code to Audio::PCSpeaker


Commit: ba8d370f8d63b8658106338e03f2f71648be3aea
    https://github.com/scummvm/scummvm/commit/ba8d370f8d63b8658106338e03f2f71648be3aea
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-02-25T16:15:39-07:00

Commit Message:
AGI: Migrate Apple II and CoCo3 sound code to Audio::PCSpeaker

Changed paths:
    engines/agi/sound_a2.cpp
    engines/agi/sound_a2.h
    engines/agi/sound_coco3.cpp
    engines/agi/sound_coco3.h


diff --git a/engines/agi/sound_a2.cpp b/engines/agi/sound_a2.cpp
index fec01afa23e..a6b72aebda9 100644
--- a/engines/agi/sound_a2.cpp
+++ b/engines/agi/sound_a2.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "audio/mixer.h"
+#include "common/timer.h"
 
 #include "agi/agi.h"
 #include "agi/sound_a2.h"
@@ -36,8 +37,6 @@ namespace Agi {
 // consumed by AGI's play-note routine and the speed of the CPU. Playback was
 // driven by the engine's own inner loops instead of a timer, so games are
 // blocked until a sound is completed or interrupted by a key press.
-//
-// TODO: Migrate to Audio::PCSpeaker
 
 static void calculateNote(uint16 clickCount, uint16 delayCount, float &freq, uint32 &duration_usec);
 static uint32 calculateDelayCycles(uint16 delayCount);
@@ -46,17 +45,16 @@ static uint32 calculateTotalCycles(uint32 delayCycles, uint16 delayCount, uint16
 SoundGenA2::SoundGenA2(AgiBase *vm, Audio::Mixer *pMixer) :
 	_isPlaying(false),
 	SoundGen(vm, pMixer) {
-	
-	_mixer->playStream(Audio::Mixer::kMusicSoundType, _soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker.init();
+	g_system->getTimerManager()->installTimerProc(timerProc, 10000, this, "SoundGenA2");
 }
 
 SoundGenA2::~SoundGenA2() {
-	_mixer->stopHandle(*_soundHandle);
+	g_system->getTimerManager()->removeTimerProc(timerProc);
+	_speaker.quit();
 }
 
 void SoundGenA2::play(int resnum) {
-	Common::StackLock lock(_mutex);
-
 	if (_vm->_game.sounds[resnum] == nullptr ||
 		_vm->_game.sounds[resnum]->type() != AGI_SOUND_APPLE2) {
 		error("Apple II sound %d not loaded", resnum);
@@ -90,30 +88,20 @@ void SoundGenA2::play(int resnum) {
 }
 
 void SoundGenA2::stop() {
-	Common::StackLock lock(_mutex);
-
 	_speaker.stop();
 	_isPlaying = false;
 }
 
-int SoundGenA2::readBuffer(int16 *buffer, const int numSamples) {
-	Common::StackLock lock(_mutex);
-
-	// if not playing then there are no samples
-	if (!_isPlaying) {
-		return 0;
-	}
-
-	// fill the buffer with PCSpeaker samples
-	int result = _speaker.readBuffer(buffer, numSamples);
-
+void SoundGenA2::onTimer() {
 	// if PCSpeaker is no longer playing then sound is finished
-	if (!_speaker.isPlaying()) {
+	if (_isPlaying && !_speaker.isPlaying()) {
 		_isPlaying = false;
 		_vm->_sound->soundIsFinished();
 	}
+}
 
-	return result;
+void SoundGenA2::timerProc(void *refCon) {
+	static_cast<SoundGenA2 *>(refCon)->onTimer();
 }
 
 // Apple II note calculations
diff --git a/engines/agi/sound_a2.h b/engines/agi/sound_a2.h
index 1f1fdd5dccb..525cf627e46 100644
--- a/engines/agi/sound_a2.h
+++ b/engines/agi/sound_a2.h
@@ -27,7 +27,7 @@
 
 namespace Agi {
 
-class SoundGenA2 : public SoundGen, public Audio::AudioStream {
+class SoundGenA2 : public SoundGen {
 public:
 	SoundGenA2(AgiBase *vm, Audio::Mixer *pMixer);
 	~SoundGenA2() override;
@@ -35,24 +35,13 @@ public:
 	void play(int resnum) override;
 	void stop() override;
 
-	int readBuffer(int16 *buffer, const int numSamples) override;
-
-	bool isStereo() const override {
-		return false;
-	}
-
-	bool endOfData() const override {
-		return false;
-	}
-
-	int getRate() const override {
-		return _speaker.getRate();
-	}
-
 private:
-	Common::Mutex _mutex;
 	bool _isPlaying;
-	Audio::PCSpeakerStream _speaker;
+	Audio::PCSpeaker _speaker;
+
+	void onTimer();
+
+	static void timerProc(void *refCon);
 };
 
 } // End of namespace Agi
diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp
index 6f7ac495c00..b275fbcbf19 100644
--- a/engines/agi/sound_coco3.cpp
+++ b/engines/agi/sound_coco3.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "audio/mixer.h"
+#include "common/timer.h"
 
 #include "agi/agi.h"
 #include "agi/sound_coco3.h"
@@ -38,8 +39,6 @@ namespace Agi {
 //
 // Thanks to Guillaume Major for documenting the sound format in their
 // conversion program, cc3snd.c.
-//
-// TODO: Migrate to Audio::PCSpeaker
 
 static const uint16 cocoFrequencies[] = {
 	 130,  138,  146,  155,  164,  174,  184,  195,  207,  220,  233,  246,
@@ -52,17 +51,16 @@ static const uint16 cocoFrequencies[] = {
 SoundGenCoCo3::SoundGenCoCo3(AgiBase *vm, Audio::Mixer *pMixer) :
 	_isPlaying(false),
 	SoundGen(vm, pMixer) {
-
-	_mixer->playStream(Audio::Mixer::kMusicSoundType, _soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	_speaker.init();
+	g_system->getTimerManager()->installTimerProc(timerProc, 10000, this, "SoundGenCoCo3");
 }
 
 SoundGenCoCo3::~SoundGenCoCo3() {
-	_mixer->stopHandle(*_soundHandle);
+	g_system->getTimerManager()->removeTimerProc(timerProc);
+	_speaker.quit();
 }
 
 void SoundGenCoCo3::play(int resnum) {
-	Common::StackLock lock(_mutex);
-
 	if (_vm->_game.sounds[resnum] == nullptr ||
 		_vm->_game.sounds[resnum]->type() != AGI_SOUND_COCO3) {
 		error("CoCo3 sound %d not loaded", resnum);
@@ -113,30 +111,20 @@ void SoundGenCoCo3::play(int resnum) {
 }
 
 void SoundGenCoCo3::stop() {
-	Common::StackLock lock(_mutex);
-
 	_speaker.stop();
 	_isPlaying = false;
 }
 
-int SoundGenCoCo3::readBuffer(int16 *buffer, const int numSamples) {
-	Common::StackLock lock(_mutex);
-
-	// if not playing then there are no samples
-	if (!_isPlaying) {
-		return 0;
-	}
-
-	// fill the buffer with PCSpeaker samples
-	int result = _speaker.readBuffer(buffer, numSamples);
-
+void SoundGenCoCo3::onTimer() {
 	// if PCSpeaker is no longer playing then sound is finished
-	if (!_speaker.isPlaying()) {
+	if (_isPlaying && !_speaker.isPlaying()) {
 		_isPlaying = false;
 		_vm->_sound->soundIsFinished();
 	}
+}
 
-	return result;
+void SoundGenCoCo3::timerProc(void *refCon) {
+	static_cast<SoundGenCoCo3 *>(refCon)->onTimer();
 }
 
 } // End of namespace Agi
diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h
index df399fa94e2..ab36e595f26 100644
--- a/engines/agi/sound_coco3.h
+++ b/engines/agi/sound_coco3.h
@@ -27,7 +27,7 @@
 
 namespace Agi {
 
-class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream {
+class SoundGenCoCo3 : public SoundGen {
 public:
 	SoundGenCoCo3(AgiBase *vm, Audio::Mixer *pMixer);
 	~SoundGenCoCo3() override;
@@ -35,24 +35,13 @@ public:
 	void play(int resnum) override;
 	void stop() override;
 
-	int readBuffer(int16 *buffer, const int numSamples) override;
-
-	bool isStereo() const override {
-		return false;
-	}
-
-	bool endOfData() const override {
-		return false;
-	}
-
-	int getRate() const override {
-		return _speaker.getRate();
-	}
-
 private:
-	Common::Mutex _mutex;
 	bool _isPlaying;
-	Audio::PCSpeakerStream _speaker;
+	Audio::PCSpeaker _speaker;
+
+	void onTimer();
+
+	static void timerProc(void *refCon);
 };
 
 } // End of namespace Agi




More information about the Scummvm-git-logs mailing list