1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

With minor infrastructure fixes, switch Mockingboard to stereo.

This commit is contained in:
Thomas Harte 2024-02-15 09:42:33 -05:00
parent e1fdda928a
commit 51de1892c0
3 changed files with 30 additions and 28 deletions

View File

@ -65,12 +65,12 @@ constexpr float master_clock = 14318180.0;
/// allowing for stretched CPU clock cycles. /// allowing for stretched CPU clock cycles.
struct StretchedAYPair: struct StretchedAYPair:
Apple::II::AYPair, Apple::II::AYPair,
public Outputs::Speaker::BufferSource<StretchedAYPair, false> { public Outputs::Speaker::BufferSource<StretchedAYPair, true> {
using AYPair::AYPair; using AYPair::AYPair;
template <Outputs::Speaker::Action action> template <Outputs::Speaker::Action action>
void apply_samples(std::size_t number_of_samples, Outputs::Speaker::MonoSample *target) { void apply_samples(std::size_t number_of_samples, Outputs::Speaker::StereoSample *target) {
// (1) take 64 windows of 7 input cycles followed by one window of 8 input cycles; // (1) take 64 windows of 7 input cycles followed by one window of 8 input cycles;
// (2) after each four windows, advance the underlying AY. // (2) after each four windows, advance the underlying AY.
@ -168,10 +168,10 @@ template <Analyser::Static::AppleII::Target::Model model, bool has_mockingboard>
Audio::Toggle audio_toggle_; Audio::Toggle audio_toggle_;
StretchedAYPair ays_; StretchedAYPair ays_;
using SourceT = using SourceT =
std::conditional_t<has_mockingboard, Outputs::Speaker::CompoundSource<Audio::Toggle, StretchedAYPair>, Audio::Toggle>; std::conditional_t<has_mockingboard, Outputs::Speaker::CompoundSource<StretchedAYPair, Audio::Toggle>, Audio::Toggle>;
using LowpassT = Outputs::Speaker::PullLowpass<SourceT>; using LowpassT = Outputs::Speaker::PullLowpass<SourceT>;
Outputs::Speaker::CompoundSource<Audio::Toggle, StretchedAYPair> mixer_; Outputs::Speaker::CompoundSource<StretchedAYPair, Audio::Toggle> mixer_;
Outputs::Speaker::PullLowpass<SourceT> speaker_; Outputs::Speaker::PullLowpass<SourceT> speaker_;
Cycles cycles_since_audio_update_; Cycles cycles_since_audio_update_;
@ -570,7 +570,7 @@ template <Analyser::Static::AppleII::Target::Model model, bool has_mockingboard>
video_(video_bus_handler_), video_(video_bus_handler_),
audio_toggle_(audio_queue_), audio_toggle_(audio_queue_),
ays_(audio_queue_), ays_(audio_queue_),
mixer_(audio_toggle_, ays_), mixer_(ays_, audio_toggle_),
speaker_(lowpass_source()), speaker_(lowpass_source()),
language_card_(*this), language_card_(*this),
auxiliary_switches_(*this), auxiliary_switches_(*this),

View File

@ -28,16 +28,19 @@ class AYPair {
} }
void set_sample_volume_range(std::int16_t range) { void set_sample_volume_range(std::int16_t range) {
ays_[0].set_sample_volume_range(range >> 1); ays_[0].set_sample_volume_range(range);
ays_[1].set_sample_volume_range(range >> 1); ays_[1].set_sample_volume_range(range);
} }
bool is_zero_level() const { bool is_zero_level() const {
return ays_[0].is_zero_level() && ays_[1].is_zero_level(); return ays_[0].is_zero_level() && ays_[1].is_zero_level();
} }
Outputs::Speaker::MonoSample level() const { Outputs::Speaker::StereoSample level() const {
return ays_[0].level() + ays_[1].level(); Outputs::Speaker::StereoSample level;
level.left = ays_[0].level();
level.right = ays_[1].level();
return level;
} }
GI::AY38910::AY38910SampleSource<false> &get(int index) { GI::AY38910::AY38910SampleSource<false> &get(int index) {

View File

@ -77,29 +77,28 @@ template <typename... T> class CompoundSource:
// Map up and return. // Map up and return.
for(std::size_t c = 0; c < number_of_samples; c++) { for(std::size_t c = 0; c < number_of_samples; c++) {
Outputs::Speaker::apply<action>(target[c].left, StereoSample(conversion_source_[c])); Outputs::Speaker::apply<action>(target[c], StereoSample(conversion_source_[c]));
} }
return; } else {
} constexpr bool is_final_source = sizeof...(R) == 0;
constexpr bool is_final_source = sizeof...(R) == 0; // Get the rest of the output, if any.
if constexpr (!is_final_source) {
// Get the rest of the output, if any. next_source_.template apply_samples<action, output_stereo>(number_of_samples, target);
if constexpr (!is_final_source) {
next_source_.template apply_samples<action, output_stereo>(number_of_samples, target);
}
if(source_.is_zero_level()) {
// This component is currently outputting silence; therefore don't add anything to the output
// audio. Zero fill only if this is the final source (as everything above will be additive).
if constexpr (is_final_source) {
Outputs::Speaker::fill<action>(target, target + number_of_samples, typename SampleT<output_stereo>::type());
} }
return;
}
// Add in this component's output. if(source_.is_zero_level()) {
source_.template apply_samples<is_final_source ? Action::Store : Action::Mix>(number_of_samples, target); // This component is currently outputting silence; therefore don't add anything to the output
// audio. Zero fill only if this is the final source (as everything above will be additive).
if constexpr (is_final_source) {
Outputs::Speaker::fill<action>(target, target + number_of_samples, typename SampleT<output_stereo>::type());
}
return;
}
// Add in this component's output.
source_.template apply_samples<is_final_source ? Action::Store : Action::Mix>(number_of_samples, target);
}
} }
void set_scaled_volume_range(int16_t range, double *volumes, double scale) { void set_scaled_volume_range(int16_t range, double *volumes, double scale) {