From 30ff3992183e829bd484d13af4faa1d150ac4987 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 15 Apr 2020 21:27:27 -0400 Subject: [PATCH] With some fixes for scale, I think possibly this is close for melodic channels. --- Components/OPL2/OPL2.cpp | 12 ++++++++---- Components/OPL2/OPL2.hpp | 16 +++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Components/OPL2/OPL2.cpp b/Components/OPL2/OPL2.cpp index 4ed8bd237..cb5f1462b 100644 --- a/Components/OPL2/OPL2.cpp +++ b/Components/OPL2/OPL2.cpp @@ -403,10 +403,14 @@ void Operator::update(OperatorState &state, bool key_on, int channel_period, int }; // Update the raw phase. + // TODO: if this is the real formula (i.e. a downward shift for channel_octave), this is a highly + // suboptimal way to do this. Could just keep one accumulator and shift that downward for the result. const int octave_divider = 2048 >> channel_octave; state.divider_ %= octave_divider; - state.divider_ += multipliers[frequency_multiple] * channel_period; - state.raw_phase_ += state.divider_ / octave_divider; + state.divider_ += channel_period; + state.raw_phase_ += multipliers[frequency_multiple] * (state.divider_ / octave_divider); + // TODO: this last step introduces aliasing, but is a quick way to verify whether the multiplier should + // be applied also to the octave. // Hence calculate phase (TODO: by also taking account of vibrato). constexpr int waveforms[4][4] = { @@ -512,9 +516,9 @@ void Operator::update(OperatorState &state, bool key_on, int channel_period, int // Combine the ADSR attenuation and overall channel attenuation, clamping to the permitted range. if(overrides) { - state.attenuation = state.adsr_attenuation_ + (overrides->attenuation << 6); + state.attenuation = state.adsr_attenuation_ + (overrides->attenuation << 4); } else { - state.attenuation = state.adsr_attenuation_ + (attenuation_ << 3); + state.attenuation = state.adsr_attenuation_ + (attenuation_ << 2); } } diff --git a/Components/OPL2/OPL2.hpp b/Components/OPL2/OPL2.hpp index 398eead6d..537b6c486 100644 --- a/Components/OPL2/OPL2.hpp +++ b/Components/OPL2/OPL2.hpp @@ -92,7 +92,7 @@ class Operator { /// Sets this operator's waveform using the low two bits of @c value. void set_waveform(uint8_t value) { -// waveform = Operator::Waveform(value & 3); + waveform = Operator::Waveform(value & 3); } /// From the top nibble of @c value sets the AM, vibrato, hold/sustain level and keyboard sampling rate flags; @@ -204,7 +204,7 @@ class Channel { // TODO: almost everything. This is a quick test. // Specifically: use lookup tables. - const auto modulator_level = 0.0f;//level(modulator_state_, 0.0f) * 0.25f; + const auto modulator_level = level(modulator_state_, 0.0f); // TODO: what's the proper scaling on this? return int(level(carrier_state_, modulator_level) * 20'000.0f); } @@ -218,7 +218,9 @@ class Channel { const float phase = modulator_level + float(state.phase) / 1024.0f; const float phase_attenuation = logf(1.0f + sinf(float(M_PI) * 2.0f * phase)); const float total_attenuation = phase_attenuation + float(state.attenuation) / 1023.0f; - return expf(total_attenuation); + const float result = expf(total_attenuation / 2.0f); + + return result; } /// 'F-Num' in the spec; this plus the current octave determines channel frequency. @@ -334,10 +336,10 @@ struct OPLL: public OPLBase { int level = 0; }; void update_all_chanels() { -// for(int c = 0; c < 6; ++ c) { // Don't do anything with channels that might be percussion for now. -// channels_[c].level = (channels_[c].update() * total_volume_) >> 14; -// } - channels_[0].level = (channels_[0].update() * total_volume_) >> 14; + for(int c = 0; c < 6; ++ c) { // Don't do anything with channels that might be percussion for now. + channels_[c].level = (channels_[c].update() * total_volume_) >> 14; + } + channels_[2].level = (channels_[2].update() * total_volume_) >> 14; } Channel channels_[9];