diff --git a/Components/AudioToggle/AudioToggle.hpp b/Components/AudioToggle/AudioToggle.hpp index e3d29ac30..f00f1304d 100644 --- a/Components/AudioToggle/AudioToggle.hpp +++ b/Components/AudioToggle/AudioToggle.hpp @@ -29,9 +29,12 @@ class Toggle: public Outputs::Speaker::SampleSource { bool get_output(); private: + // Accessed on the calling thread. bool is_enabled_ = false; - int16_t level_ = 0, volume_ = 0; Concurrency::DeferringAsyncTaskQueue &audio_queue_; + + // Accessed on the audio thread. + int16_t level_ = 0, volume_ = 0; }; } diff --git a/Machines/AppleII/AppleII.cpp b/Machines/AppleII/AppleII.cpp index 7095a4aa9..fda5dd81c 100644 --- a/Machines/AppleII/AppleII.cpp +++ b/Machines/AppleII/AppleII.cpp @@ -51,8 +51,9 @@ class ConcreteMachine: void update_video() { video_->run_for(cycles_since_video_update_.flush()); } + static const int audio_divider = 8; void update_audio() { - speaker_.run_for(cycles_since_audio_update_.divide(Cycles(16))); + speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(audio_divider))); } uint8_t ram_[48*1024]; @@ -82,7 +83,7 @@ class ConcreteMachine: // The speaker, however, should think it is clocked at half the master clock, per a general // decision to sample it at seven times the CPU clock (plus stretches). - speaker_.set_input_rate(static_cast(master_clock / (2.0 * 16.0))); + speaker_.set_input_rate(static_cast(master_clock / (2.0 * static_cast(audio_divider)))); // Also, start with randomised memory contents. Memory::Fuzz(ram_, sizeof(ram_)); diff --git a/Outputs/Speaker/Implementation/LowpassSpeaker.hpp b/Outputs/Speaker/Implementation/LowpassSpeaker.hpp index e22a30a72..19655f980 100644 --- a/Outputs/Speaker/Implementation/LowpassSpeaker.hpp +++ b/Outputs/Speaker/Implementation/LowpassSpeaker.hpp @@ -86,6 +86,18 @@ template class LowpassSpeaker: public Speaker { filter_parameters_.parameters_are_dirty = true; } + /*! + Schedules an advancement by the number of cycles specified on the provided queue. + The speaker will advance by obtaining data from the sample source supplied + at construction, filtering it and passing it on to the speaker's delegate if there is one. + */ + void run_for(Concurrency::DeferringAsyncTaskQueue &queue, const Cycles cycles) { + queue.defer([this, cycles] { + run_for(cycles); + }); + } + + private: /*! Advances by the number of cycles specified, obtaining data from the sample source supplied at construction, filtering it and passing it on to the speaker's delegate if there is one. @@ -173,16 +185,6 @@ template class LowpassSpeaker: public Speaker { // TODO: input rate is less than output rate } - /*! - Provides a convenience shortcut for deferring a call to run_for. - */ - void run_for(Concurrency::DeferringAsyncTaskQueue &queue, const Cycles cycles) { - queue.defer([this, cycles] { - run_for(cycles); - }); - } - - private: T &sample_source_; std::size_t output_buffer_pointer_ = 0;