From e02d109864016d06c1a06f994abeb2e4a4c49ab0 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sat, 15 Feb 2020 18:03:12 -0500
Subject: [PATCH] Nudges the LowpassSpeaker towards supporting stereo
 generation.

---
 Components/6560/6560.hpp                                 | 2 +-
 Machines/AmstradCPC/AmstradCPC.cpp                       | 2 +-
 Machines/Apple/AppleII/AppleII.cpp                       | 2 +-
 Machines/Apple/Macintosh/DeferredAudio.hpp               | 2 +-
 Machines/Atari/2600/Bus.hpp                              | 2 +-
 Machines/Atari/ST/AtariST.cpp                            | 2 +-
 Machines/ColecoVision/ColecoVision.cpp                   | 2 +-
 Machines/Electron/Electron.cpp                           | 2 +-
 Machines/MSX/MSX.cpp                                     | 2 +-
 Machines/MasterSystem/MasterSystem.cpp                   | 2 +-
 Machines/Oric/Oric.cpp                                   | 7 ++++---
 Machines/ZX8081/ZX8081.cpp                               | 2 +-
 .../xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme   | 4 ++++
 Outputs/Speaker/Implementation/LowpassSpeaker.hpp        | 9 ++++-----
 14 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp
index e975ef596..f7dc74d4b 100644
--- a/Components/6560/6560.hpp
+++ b/Components/6560/6560.hpp
@@ -433,7 +433,7 @@ template <class BusHandler> class MOS6560 {
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		AudioGenerator audio_generator_;
-		Outputs::Speaker::LowpassSpeaker<AudioGenerator> speaker_;
+		Outputs::Speaker::LowpassSpeaker<AudioGenerator, false> speaker_;
 
 		Cycles cycles_since_speaker_update_;
 		void update_audio() {
diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp
index 1e319eae1..0c0b383f4 100644
--- a/Machines/AmstradCPC/AmstradCPC.cpp
+++ b/Machines/AmstradCPC/AmstradCPC.cpp
@@ -160,7 +160,7 @@ class AYDeferrer {
 	private:
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		GI::AY38910::AY38910 ay_;
-		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
+		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910, false> speaker_;
 		HalfCycles cycles_since_update_;
 };
 
diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp
index 90f53048a..397d24afb 100644
--- a/Machines/Apple/AppleII/AppleII.cpp
+++ b/Machines/Apple/AppleII/AppleII.cpp
@@ -108,7 +108,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		Audio::Toggle audio_toggle_;
-		Outputs::Speaker::LowpassSpeaker<Audio::Toggle> speaker_;
+		Outputs::Speaker::LowpassSpeaker<Audio::Toggle, false> speaker_;
 		Cycles cycles_since_audio_update_;
 
 		// MARK: - Cards
diff --git a/Machines/Apple/Macintosh/DeferredAudio.hpp b/Machines/Apple/Macintosh/DeferredAudio.hpp
index 6fda448fa..50ba7f714 100644
--- a/Machines/Apple/Macintosh/DeferredAudio.hpp
+++ b/Machines/Apple/Macintosh/DeferredAudio.hpp
@@ -18,7 +18,7 @@ namespace Macintosh {
 struct DeferredAudio {
 	Concurrency::DeferringAsyncTaskQueue queue;
 	Audio audio;
-	Outputs::Speaker::LowpassSpeaker<Audio> speaker;
+	Outputs::Speaker::LowpassSpeaker<Audio, false> speaker;
 	HalfCycles time_since_update;
 
 	DeferredAudio() : audio(queue), speaker(audio) {}
diff --git a/Machines/Atari/2600/Bus.hpp b/Machines/Atari/2600/Bus.hpp
index 4b21b4a0b..36c8a16b1 100644
--- a/Machines/Atari/2600/Bus.hpp
+++ b/Machines/Atari/2600/Bus.hpp
@@ -41,7 +41,7 @@ class Bus {
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		TIASound tia_sound_;
-		Outputs::Speaker::LowpassSpeaker<TIASound> speaker_;
+		Outputs::Speaker::LowpassSpeaker<TIASound, false> speaker_;
 
 		// joystick state
 		uint8_t tia_input_value_[2] = {0xff, 0xff};
diff --git a/Machines/Atari/ST/AtariST.cpp b/Machines/Atari/ST/AtariST.cpp
index 9e65aa52c..a4791e412 100644
--- a/Machines/Atari/ST/AtariST.cpp
+++ b/Machines/Atari/ST/AtariST.cpp
@@ -498,7 +498,7 @@ class ConcreteMachine:
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		GI::AY38910::AY38910 ay_;
-		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
+		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910, false> speaker_;
 		HalfCycles cycles_since_audio_update_;
 
 		JustInTimeActor<DMAController> dma_;
diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp
index 1a641d479..3c02ec646 100644
--- a/Machines/ColecoVision/ColecoVision.cpp
+++ b/Machines/ColecoVision/ColecoVision.cpp
@@ -407,7 +407,7 @@ class ConcreteMachine:
 		TI::SN76489 sn76489_;
 		GI::AY38910::AY38910 ay_;
 		Outputs::Speaker::CompoundSource<TI::SN76489, GI::AY38910::AY38910> mixer_;
-		Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<TI::SN76489, GI::AY38910::AY38910>> speaker_;
+		Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<TI::SN76489, GI::AY38910::AY38910>, false> speaker_;
 
 		std::vector<uint8_t> bios_;
 		std::vector<uint8_t> cartridge_;
diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp
index a5c890207..fc89a1f37 100644
--- a/Machines/Electron/Electron.cpp
+++ b/Machines/Electron/Electron.cpp
@@ -592,7 +592,7 @@ class ConcreteMachine:
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		SoundGenerator sound_generator_;
-		Outputs::Speaker::LowpassSpeaker<SoundGenerator> speaker_;
+		Outputs::Speaker::LowpassSpeaker<SoundGenerator, false> speaker_;
 
 		bool speaker_is_enabled_ = false;
 
diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp
index 79f8c532e..fd46acdb9 100644
--- a/Machines/MSX/MSX.cpp
+++ b/Machines/MSX/MSX.cpp
@@ -764,7 +764,7 @@ class ConcreteMachine:
 		Audio::Toggle audio_toggle_;
 		Konami::SCC scc_;
 		Outputs::Speaker::CompoundSource<GI::AY38910::AY38910, Audio::Toggle, Konami::SCC> mixer_;
-		Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910, Audio::Toggle, Konami::SCC>> speaker_;
+		Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910, Audio::Toggle, Konami::SCC>, false> speaker_;
 
 		Storage::Tape::BinaryTapePlayer tape_player_;
 		bool tape_player_is_sleeping_ = false;
diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp
index ce98a0bf8..e7cb76f14 100644
--- a/Machines/MasterSystem/MasterSystem.cpp
+++ b/Machines/MasterSystem/MasterSystem.cpp
@@ -424,7 +424,7 @@ class ConcreteMachine:
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		TI::SN76489 sn76489_;
-		Outputs::Speaker::LowpassSpeaker<TI::SN76489> speaker_;
+		Outputs::Speaker::LowpassSpeaker<TI::SN76489, false> speaker_;
 
 		std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
 		Inputs::Keyboard keyboard_;
diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp
index a7273d20f..043ab14cf 100644
--- a/Machines/Oric/Oric.cpp
+++ b/Machines/Oric/Oric.cpp
@@ -43,6 +43,7 @@
 namespace Oric {
 
 using DiskInterface = Analyser::Static::Oric::Target::DiskInterface;
+using Speaker = Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910, false>;
 
 enum ROM {
 	BASIC10 = 0, BASIC11, Microdisc, Colour
@@ -146,7 +147,7 @@ class TapePlayer: public Storage::Tape::BinaryTapePlayer {
 */
 class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
 	public:
-		VIAPortHandler(Concurrency::DeferringAsyncTaskQueue &audio_queue, GI::AY38910::AY38910 &ay8910, Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> &speaker, TapePlayer &tape_player, Keyboard &keyboard) :
+		VIAPortHandler(Concurrency::DeferringAsyncTaskQueue &audio_queue, GI::AY38910::AY38910 &ay8910, Speaker &speaker, TapePlayer &tape_player, Keyboard &keyboard) :
 			audio_queue_(audio_queue), ay8910_(ay8910), speaker_(speaker), tape_player_(tape_player), keyboard_(keyboard) {}
 
 		/*!
@@ -210,7 +211,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
 
 		Concurrency::DeferringAsyncTaskQueue &audio_queue_;
 		GI::AY38910::AY38910 &ay8910_;
-		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> &speaker_;
+		Speaker &speaker_;
 		TapePlayer &tape_player_;
 		Keyboard &keyboard_;
 };
@@ -692,7 +693,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
 
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		GI::AY38910::AY38910 ay8910_;
-		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
+		Speaker speaker_;
 
 		// Inputs
 		Oric::KeyboardMapper keyboard_mapper_;
diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp
index 8ea7a0781..2ffbdf62d 100644
--- a/Machines/ZX8081/ZX8081.cpp
+++ b/Machines/ZX8081/ZX8081.cpp
@@ -468,7 +468,7 @@ template<bool is_zx81> class ConcreteMachine:
 		// MARK: - Audio
 		Concurrency::DeferringAsyncTaskQueue audio_queue_;
 		GI::AY38910::AY38910 ay_;
-		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910> speaker_;
+		Outputs::Speaker::LowpassSpeaker<GI::AY38910::AY38910, false> speaker_;
 		HalfCycles time_since_ay_update_;
 		inline void ay_set_register(uint8_t value) {
 			update_audio();
diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme
index 1d7e2ee72..271f40201 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme	
@@ -58,6 +58,10 @@
          </CommandLineArgument>
          <CommandLineArgument
             argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Master System/R-Type (NTSC).sms&quot;"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk&quot;"
             isEnabled = "YES">
          </CommandLineArgument>
          <CommandLineArgument
diff --git a/Outputs/Speaker/Implementation/LowpassSpeaker.hpp b/Outputs/Speaker/Implementation/LowpassSpeaker.hpp
index dda9dbabd..bb1162e02 100644
--- a/Outputs/Speaker/Implementation/LowpassSpeaker.hpp
+++ b/Outputs/Speaker/Implementation/LowpassSpeaker.hpp
@@ -28,9 +28,9 @@ namespace Speaker {
 	source of a high-frequency stream of audio which it filters down to a
 	lower-frequency output.
 */
-template <typename T> class LowpassSpeaker: public Speaker {
+template <typename SampleSource, bool is_stereo> class LowpassSpeaker: public Speaker {
 	public:
-		LowpassSpeaker(T &sample_source) : sample_source_(sample_source) {
+		LowpassSpeaker(SampleSource &sample_source) : sample_source_(sample_source) {
 			sample_source.set_sample_volume_range(32767);
 		}
 
@@ -69,9 +69,8 @@ template <typename T> class LowpassSpeaker: public Speaker {
 			output_buffer_.resize(std::size_t(buffer_size));
 		}
 
-		// TODO.
 		bool get_is_stereo() final {
-			return false;
+			return is_stereo;
 		}
 
 		/*!
@@ -179,7 +178,7 @@ template <typename T> class LowpassSpeaker: public Speaker {
 			}
 		}
 
-		T &sample_source_;
+		SampleSource &sample_source_;
 
 		std::size_t output_buffer_pointer_ = 0;
 		std::size_t input_buffer_depth_ = 0;