From 72884f37c38d3d69e3e4df8d1b99c390f238f767 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 26 Nov 2020 16:03:28 -0500 Subject: [PATCH] It's still interrupt-deficient, but fills in additional Ensoniq audio generation. --- Machines/Apple/AppleIIgs/Sound.cpp | 33 ++++++++++++++++++++---------- Machines/Apple/AppleIIgs/Sound.hpp | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Machines/Apple/AppleIIgs/Sound.cpp b/Machines/Apple/AppleIIgs/Sound.cpp index 757e7612e..9c50291b5 100644 --- a/Machines/Apple/AppleIIgs/Sound.cpp +++ b/Machines/Apple/AppleIIgs/Sound.cpp @@ -117,7 +117,7 @@ void GLU::run_for(Cycles cycles) { void GLU::get_samples(std::size_t number_of_samples, std::int16_t *target) { // Update remote state, generating audio. - generate_audio(number_of_samples, target, output_range_); + generate_audio(number_of_samples, target); } void GLU::skip_samples(const std::size_t number_of_samples) { @@ -174,12 +174,9 @@ uint8_t GLU::get_address_high() { // MARK: - Update logic. -void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t range) { - (void)number_of_samples; - (void)target; - (void)range; - +void GLU::generate_audio(size_t number_of_samples, std::int16_t *target) { auto next_store = pending_stores_[pending_store_read_].load(std::memory_order::memory_order_acquire); + uint8_t next_amplitude = 255; for(size_t sample = 0; sample < number_of_samples; sample++) { // TODO: there's a bit of a hack here where it is assumed that the input clock has been @@ -206,13 +203,22 @@ void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t if(remote_.oscillators[c].position & remote_.oscillators[c].overflow_mask) { remote_.oscillators[c].position = 0; remote_.oscillators[c].control |= 1; - } else { - output += remote_.oscillators[c].output(remote_.ram_); } break; case 4: // Sync/AM mode. - assert(false); + if(c&1) { + // Oscillator is odd-numbered; it will amplitude-modulate the next voice. + next_amplitude = remote_.oscillators[c].sample(remote_.ram_); + continue; + } else { + // Oscillator is even-numbered; it will 'sync' to the even voice, i.e. any + // time it wraps around, it will reset the next oscillator. + if(remote_.oscillators[c].position & remote_.oscillators[c].overflow_mask) { + remote_.oscillators[c].position &= remote_.oscillators[c].overflow_mask; + remote_.oscillators[c+1].position = 0; + } + } break; case 6: // Swap mode; possibly trigger partner, and update sample. @@ -223,11 +229,16 @@ void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t remote_.oscillators[c].control |= 1; remote_.oscillators[c].position = 0; remote_.oscillators[c^1].control &= ~1; - } else { - output += remote_.oscillators[c].output(remote_.ram_); } break; } + + // Don't add output for newly-halted oscillators. + if(remote_.oscillators[c].control&1) continue; + + // Append new output. + output += (remote_.oscillators[c].output(remote_.ram_) * next_amplitude) / 255; + next_amplitude = 255; } // Maximum total output was 32 channels times a 16-bit range. Map that down. diff --git a/Machines/Apple/AppleIIgs/Sound.hpp b/Machines/Apple/AppleIIgs/Sound.hpp index 8ac92a847..ca3e91c13 100644 --- a/Machines/Apple/AppleIIgs/Sound.hpp +++ b/Machines/Apple/AppleIIgs/Sound.hpp @@ -94,7 +94,7 @@ class GLU: public Outputs::Speaker::SampleSource { // Functions to update an EnsoniqState; these don't belong to the state itself // because they also access the pending stores (inter alia). - void generate_audio(size_t number_of_samples, std::int16_t *target, int16_t range); + void generate_audio(size_t number_of_samples, std::int16_t *target); void skip_audio(EnsoniqState &state, size_t number_of_samples); // Audio-thread state.