diff --git a/Components/OPL2/Implementation/LowFrequencyOscillator.cpp b/Components/OPL2/Implementation/LowFrequencyOscillator.cpp index 0a7329213..930904b0d 100644 --- a/Components/OPL2/Implementation/LowFrequencyOscillator.cpp +++ b/Components/OPL2/Implementation/LowFrequencyOscillator.cpp @@ -7,3 +7,22 @@ // #include "LowFrequencyOscillator.hpp" + +using namespace Yamaha::OPL; + +void LowFrequencyOscillator::update() { + ++counter; + + // This produces output of: + // + // four instances of 0, four instances of 1... _three_ instances of 26, + // four instances of 25, four instances of 24... _three_ instances of 0. + // + // ... advancing once every 64th update. + const int tremolo_index = (counter >> 6) % 210; + const int tremolo_levels[2] = {tremolo_index >> 2, 52 - ((tremolo_index+1) >> 2)}; + tremolo = tremolo_levels[tremolo_index / 107]; + + // Vibrato is relatively simple: it's just three bits from the counter. + vibrato = (counter >> 10) & 7; +} diff --git a/Components/OPL2/Implementation/LowFrequencyOscillator.hpp b/Components/OPL2/Implementation/LowFrequencyOscillator.hpp index 92c4ff5fc..d3c71669c 100644 --- a/Components/OPL2/Implementation/LowFrequencyOscillator.hpp +++ b/Components/OPL2/Implementation/LowFrequencyOscillator.hpp @@ -21,31 +21,14 @@ class LowFrequencyOscillator { public: /// Current attenuation due to tremolo / amplitude modulation, between 0 and 26. int tremolo = 0; - /// TODO + /// A number between 0 and 7 indicating the current vibrato offset; this should be combined by operators + /// with their frequency number to get the actual vibrato. int vibrato = 0; /// A counter of the number of operator update cycles (i.e. input clock / 72) since an arbitrary time. int counter = 0; /// Updates the oscillator outputs - void update() { - ++counter; - - // Update tremolo. - ++tremolo_phase_; - - // This produces output of: - // - // four instances of 0, four instances of 1... _three_ instances of 26, - // four instances of 25, four instances of 24... _three_ instances of 0. - // - // ... advancing once every 64th update. - const int tremolo_index = (tremolo_phase_ >> 6) % 210; - const int tremolo_levels[2] = {tremolo_index >> 2, 52 - ((tremolo_index+1) >> 2)}; - tremolo = tremolo_levels[tremolo_index / 107]; - } - - private: - int tremolo_phase_ = 0; + void update(); }; } diff --git a/Components/OPL2/Implementation/Operator.cpp b/Components/OPL2/Implementation/Operator.cpp index 242c723f3..e898218d9 100644 --- a/Components/OPL2/Implementation/Operator.cpp +++ b/Components/OPL2/Implementation/Operator.cpp @@ -81,11 +81,16 @@ void Operator::update( constexpr int multipliers[] = { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 }; + const int top_freq = channel_period >> 7; + assert(top_freq < 8); + constexpr int vibrato_shifts[8] = {3, 1, 0, 1, 3, 1, 0, 1}; + constexpr int vibrato_signs[2] = {1, -1}; + const int vibrato = (top_freq >> vibrato_shifts[oscillator.vibrato]) * vibrato_signs[oscillator.vibrato >> 2] * int(apply_vibrato_); // Update the raw phase. - state.raw_phase_ += multipliers[frequency_multiple_] * channel_period << channel_octave; + state.raw_phase_ += multipliers[frequency_multiple_] * (channel_period + vibrato) << channel_octave; - // Hence calculate phase (TODO: by also taking account of vibrato). + // Hence calculate phase. constexpr int waveforms[4][4] = { {1023, 1023, 1023, 1023}, // Sine: don't mask in any quadrant. {511, 511, 0, 0}, // Half sine: keep the first half intact, lock to 0 in the second half.