From fcd267a3f9655d8ba6eb324481dfdf603ed7d1cd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 26 Jun 2021 23:48:53 -0400 Subject: [PATCH] Starts implementing noise. --- Machines/Enterprise/Dave.cpp | 36 ++++++++++++++++++++++++++---------- Machines/Enterprise/Dave.hpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/Machines/Enterprise/Dave.cpp b/Machines/Enterprise/Dave.cpp index 224764c5b..d3bffe7c5 100644 --- a/Machines/Enterprise/Dave.cpp +++ b/Machines/Enterprise/Dave.cpp @@ -26,26 +26,36 @@ void Dave::write(uint16_t address, uint8_t value) { channels_[address >> 1].high_pass = value & 0x40; channels_[address >> 1].ring_modulate = value & 0x80; break; + case 6: + noise_.frequency = Noise::Frequency(value&3); + noise_.polynomial = Noise::Polynomial((value >> 2)&3); + noise_.swap_polynomial = value & 0x10; + noise_.low_pass = value & 0x20; + noise_.high_pass = value & 0x40; + noise_.ring_modulate = value & 0x80; + break; // TODO: // - // 6: noise selection. - // 7: sync bits, optional D/As, interrupt rate (albeit some of that shouldn't be on this thread, or possibly even _here_). - // 11, 14: noise amplitude. + // 7: sync bits, optional D/As. + // + // (will handle interrupt bits elsewhere) case 8: case 9: case 10: channels_[address - 8].amplitude[0] = value & 0x3f; break; - case 11: case 12: case 13: - channels_[address - 11].amplitude[1] = value & 0x3f; + case 12: case 13: case 14: + channels_[address - 12].amplitude[1] = value & 0x3f; break; + case 11: noise_.amplitude[0] = value & 0x3f; break; + case 15: noise_.amplitude[1] = value & 0x3f; break; } }); } void Dave::set_sample_volume_range(int16_t range) { audio_queue_.defer([range, this] { - volume_ = range / (63*3); + volume_ = range / (63*4); }); } @@ -54,9 +64,11 @@ void Dave::get_samples(std::size_t number_of_samples, int16_t *target) { poly_state_[int(Channel::Distortion::FourBit)] = poly4_.next(); poly_state_[int(Channel::Distortion::FiveBit)] = poly5_.next(); poly_state_[int(Channel::Distortion::SevenBit)] = poly7_.next(); + if(noise_.swap_polynomial) { + poly_state_[int(Channel::Distortion::SevenBit)] = poly_state_[int(Channel::Distortion::None)]; + } - // TODO: substitute poly_state_[2] if polynomial substitution is in play. - + // Update tone channels. #define update_channel(x) { \ auto output = channels_[x].output & 1; \ channels_[x].output <<= 1; \ @@ -86,19 +98,23 @@ void Dave::get_samples(std::size_t number_of_samples, int16_t *target) { #undef update_channel + // TODO: update noise channel. + // Dumbest ever first attempt: sum channels. target[(c << 1) + 0] = volume_ * ( channels_[0].amplitude[0] * (channels_[0].output & 1) + channels_[1].amplitude[0] * (channels_[1].output & 1) + - channels_[2].amplitude[0] * (channels_[2].output & 1) + channels_[2].amplitude[0] * (channels_[2].output & 1) + + noise_.amplitude[0] * noise_.output ); target[(c << 1) + 1] = volume_ * ( channels_[0].amplitude[1] * (channels_[0].output & 1) + channels_[1].amplitude[1] * (channels_[1].output & 1) + - channels_[2].amplitude[1] * (channels_[2].output & 1) + channels_[2].amplitude[1] * (channels_[2].output & 1) + + noise_.amplitude[1] * noise_.output ); } } diff --git a/Machines/Enterprise/Dave.hpp b/Machines/Enterprise/Dave.hpp index 3d7c3619b..1f52bb2f6 100644 --- a/Machines/Enterprise/Dave.hpp +++ b/Machines/Enterprise/Dave.hpp @@ -35,6 +35,7 @@ class Dave: public Outputs::Speaker::SampleSource { private: Concurrency::DeferringAsyncTaskQueue &audio_queue_; + // Tone channels. struct Channel { // User-set values. uint16_t reload = 0; @@ -52,6 +53,34 @@ class Dave: public Outputs::Speaker::SampleSource { uint16_t count = 0; int output = 0; } channels_[3]; + + // Noise channel. + struct Noise { + // User-set values. + uint8_t amplitude[2]{}; + enum class Frequency { + DivideByFour, + ToneChannel0, + ToneChannel1, + ToneChannel2, + } frequency = Frequency::DivideByFour; + enum class Polynomial { + SeventeenBit, + FifteenBit, + ElevenBit, + NineBit + } polynomial = Polynomial::SeventeenBit; + bool swap_polynomial = false; + bool low_pass = false; + bool high_pass = false; + bool ring_modulate = false; + + // Current state. + bool output = false; + uint16_t count = 0; + } noise_; + + // Global volume, per SampleSource obligations. int16_t volume_ = 0; // Polynomials that are always running.