From 6ac6e48b9535474dea2cd2d6b0b20187fd0e8e69 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 13 Apr 2024 21:54:50 -0400 Subject: [PATCH] Attempt audio output. --- Machines/Acorn/Archimedes/Archimedes.cpp | 6 ++++ .../Acorn/Archimedes/MemoryController.hpp | 5 +++ Machines/Acorn/Archimedes/Sound.hpp | 31 +++++++++++++++++-- .../xcschemes/Clock Signal.xcscheme | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Machines/Acorn/Archimedes/Archimedes.cpp b/Machines/Acorn/Archimedes/Archimedes.cpp index 5e9016c2d..fb18453b5 100644 --- a/Machines/Acorn/Archimedes/Archimedes.cpp +++ b/Machines/Acorn/Archimedes/Archimedes.cpp @@ -321,6 +321,7 @@ struct HackyDebugger { class ConcreteMachine: public Machine, + public MachineTypes::AudioProducer, public MachineTypes::MappedKeyboardMachine, public MachineTypes::MediaTarget, public MachineTypes::MouseMachine, @@ -480,6 +481,11 @@ class ConcreteMachine: return true; } + // MARK: - AudioProducer + Outputs::Speaker::Speaker *get_speaker() override { + return executor_.bus.speaker(); + } + // MARK: - Activity::Source. void set_activity_observer(Activity::Observer *observer) final { executor_.bus.set_activity_observer(observer); diff --git a/Machines/Acorn/Archimedes/MemoryController.hpp b/Machines/Acorn/Archimedes/MemoryController.hpp index dbb91c511..f76b6c91c 100644 --- a/Machines/Acorn/Archimedes/MemoryController.hpp +++ b/Machines/Acorn/Archimedes/MemoryController.hpp @@ -96,6 +96,7 @@ struct MemoryController { case 0b111: os_mode_ = address & (1 << 12); sound_dma_enable_ = address & (1 << 11); + ioc_.sound().set_dma_enabled(sound_dma_enable_); video_dma_enable_ = address & (1 << 10); switch((address >> 8) & 3) { default: @@ -203,6 +204,10 @@ struct MemoryController { ioc_.set_disk(disk, drive); } + Outputs::Speaker::Speaker *speaker() { + return ioc_.sound().speaker(); + } + auto &sound() { return ioc_.sound(); } const auto &sound() const { return ioc_.sound(); } auto &video() { return ioc_.video(); } diff --git a/Machines/Acorn/Archimedes/Sound.hpp b/Machines/Acorn/Archimedes/Sound.hpp index 29de60267..6864534c4 100644 --- a/Machines/Acorn/Archimedes/Sound.hpp +++ b/Machines/Acorn/Archimedes/Sound.hpp @@ -61,6 +61,9 @@ struct Sound: private SoundLevels { void set_next_start(uint32_t value) { next_.start = value; set_buffer_valid(true); // My guess: this is triggered on next buffer start write. + + // Definitely wrong; testing. +// set_halted(false); } bool interrupt() const { @@ -89,9 +92,20 @@ struct Sound: private SoundLevels { positions_[channel].left = 6 - positions_[channel].right; } + void set_dma_enabled(bool enabled) { + dma_enabled_ = enabled; + } + void tick() { - // Do nothing if not currently outputting. - if(halted_) { + // Write silence if not currently outputting. + if(halted_ || !dma_enabled_) { + samples_[byte_].left = samples_[byte_].right = 0; + ++byte_; + if(byte_ == 16) { + speaker_.push(reinterpret_cast(samples_.data()), 16); + byte_ = 0; + } + return; } @@ -101,11 +115,15 @@ struct Sound: private SoundLevels { divider_ = reload_; // Grab a single byte from the FIFO. - // TODO: and convert to a linear value, apply stereo image, output. + const uint8_t raw = ram_[current_.start + byte_]; + // TODO: volume, pan. + samples_[byte_].left = levels[raw]; + samples_[byte_].right = 0; ++byte_; // If the FIFO is exhausted, consider triggering a DMA request. if(byte_ == 16) { + speaker_.push(reinterpret_cast(samples_.data()), 16); byte_ = 0; current_.start += 16; @@ -119,6 +137,10 @@ struct Sound: private SoundLevels { } } + Outputs::Speaker::Speaker *speaker() { + return &speaker_; + } + private: const uint8_t *ram_ = nullptr; @@ -132,6 +154,7 @@ private: void set_halted(bool halted) { if(halted_ != halted && !halted) { + speaker_.push(reinterpret_cast(samples_.data()), byte_); byte_ = 0; divider_ = reload_; } @@ -140,6 +163,7 @@ private: bool next_buffer_valid_ = false; bool halted_ = true; // This is a bit of a guess. + bool dma_enabled_ = false; struct Buffer { uint32_t start = 0, end = 0; @@ -154,6 +178,7 @@ private: InterruptObserverT &observer_; Outputs::Speaker::PushLowpass speaker_; Concurrency::AsyncTaskQueue queue_; + std::array samples_; }; } diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 474fa352e..19b54b90e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -62,7 +62,7 @@