diff --git a/Components/OPL2/Implementation/Channel.cpp b/Components/OPL2/Implementation/Channel.cpp index c06e1d41a..5a04369bc 100644 --- a/Components/OPL2/Implementation/Channel.cpp +++ b/Components/OPL2/Implementation/Channel.cpp @@ -35,22 +35,21 @@ void Channel::set_feedback_mode(uint8_t value) { } int Channel::update(Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides, OperatorOverrides *carrier_overrides) { - modulator->update(modulator_state_, key_on_, period_ << frequency_shift_, octave_, modulator_overrides); - carrier->update(carrier_state_, key_on_, period_ << frequency_shift_, octave_, carrier_overrides); - - const auto modulator_level = level(modulator_state_); if(use_fm_synthesis_) { - return level(carrier_state_, modulator_level) << 2; + // Get modulator level, use that as a phase-adjusting input to the carrier and then return the carrier level. + modulator->update(modulator_state_, key_on_, period_ << frequency_shift_, octave_, 0, modulator_overrides); + const auto modulator_level = modulator_state_.level(); + + carrier->update(carrier_state_, key_on_, period_ << frequency_shift_, octave_, modulator_level, carrier_overrides); + return carrier_state_.level() << 2; } else { - return (modulator_level + level(carrier_state_)) << 1; + // Get modulator and carrier levels separately, return their sum. + modulator->update(modulator_state_, key_on_, period_ << frequency_shift_, octave_, 0, modulator_overrides); + carrier->update(carrier_state_, key_on_, period_ << frequency_shift_, octave_, 0, carrier_overrides); + return (modulator_state_.level() + carrier_state_.level()) << 1; } } bool Channel::is_audible(Operator *carrier, OperatorOverrides *carrier_overrides) { return carrier->is_audible(carrier_state_, carrier_overrides); } - -int Channel::level(OperatorState &state, int modulator_level) { - const auto log_sin = negative_log_sin(modulator_level + state.phase); - return power_two(log_sin.logsin + state.attenuation) * log_sin.sign; -} diff --git a/Components/OPL2/Implementation/Channel.hpp b/Components/OPL2/Implementation/Channel.hpp index 9ee159d46..a03483d34 100644 --- a/Components/OPL2/Implementation/Channel.hpp +++ b/Components/OPL2/Implementation/Channel.hpp @@ -46,9 +46,6 @@ class Channel { bool is_audible(Operator *carrier, OperatorOverrides *carrier_overrides = nullptr); private: - /// @returns The linear output level for the operator with state @c state and with an [optional] modulation input of @c modulator_level. - int level(OperatorState &state, int modulator_level = 0); - /// 'F-Num' in the spec; this plus the current octave determines channel frequency. int period_ = 0; diff --git a/Components/OPL2/Implementation/Operator.cpp b/Components/OPL2/Implementation/Operator.cpp index ae9d66977..afad9e198 100644 --- a/Components/OPL2/Implementation/Operator.cpp +++ b/Components/OPL2/Implementation/Operator.cpp @@ -9,9 +9,14 @@ #include "Operator.hpp" #include +#include "Tables.h" using namespace Yamaha::OPL; +int OperatorState::level() { + return power_two(attenuation.logsin) * attenuation.sign; +} + void Operator::set_attack_decay(uint8_t value) { attack_rate_ = (value & 0xf0) >> 2; decay_rate_ = (value & 0x0f) << 2; @@ -50,7 +55,7 @@ bool Operator::is_audible(OperatorState &state, OperatorOverrides *overrides) { return state.adsr_attenuation_ != 511; } -void Operator::update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorOverrides *overrides) { +void Operator::update(OperatorState &state, bool key_on, int channel_period, int channel_octave, int phase_offset, OperatorOverrides *overrides) { // Per the documentation: // // Delta phase = ( [desired freq] * 2^19 / [input clock / 72] ) / 2 ^ (b - 1) @@ -73,8 +78,8 @@ void Operator::update(OperatorState &state, bool key_on, int channel_period, int {511, 511, 511, 511}, // AbsSine: endlessly repeat the first half of the sine wave. {255, 0, 255, 0}, // PulseSine: act as if the first quadrant is in the first and third; lock the other two to 0. }; - const int phase = state.raw_phase_ >> 11; - state.phase = phase & waveforms[int(waveform_)][(phase >> 8) & 3]; + const int phase = (state.raw_phase_ >> 12) + phase_offset; + state.attenuation = negative_log_sin(phase & waveforms[int(waveform_)][(phase >> 8) & 3]); // Key-on logic: any time it is false, be in the release state. // On the leading edge of it becoming true, enter the attack state. @@ -169,10 +174,15 @@ void Operator::update(OperatorState &state, bool key_on, int channel_period, int state.time_in_phase_ = 0; } - // Combine the ADSR attenuation and overall channel attenuation, clamping to the permitted range. + // Combine the ADSR attenuation and overall channel attenuation. if(overrides) { - state.attenuation = state.adsr_attenuation_ + (overrides->attenuation << 4); + // Overrides here represent per-channel volume on an OPLL. The bits are defined to represent + // attenuations of 24db to 3db; the main envelope generator is stated to have a resolution of + // 0.325db (which I've assumed is supposed to say 0.375db). + state.attenuation.logsin += state.adsr_attenuation_ + (overrides->attenuation << 4); } else { - state.attenuation = state.adsr_attenuation_ + (attenuation_ << 2); + // Overrides here represent per-channel volume on an OPLL. The bits are defined to represent + // attenuations of 24db to 0.75db. + state.attenuation.logsin += (state.adsr_attenuation_ << 3) + (attenuation_ << 5); } } diff --git a/Components/OPL2/Implementation/Operator.hpp b/Components/OPL2/Implementation/Operator.hpp index 23c36c868..7e16881ae 100644 --- a/Components/OPL2/Implementation/Operator.hpp +++ b/Components/OPL2/Implementation/Operator.hpp @@ -10,6 +10,7 @@ #define Operator_hpp #include +#include "Tables.h" namespace Yamaha { namespace OPL { @@ -19,10 +20,11 @@ namespace OPL { */ struct OperatorState { public: - int phase = 0; // Will be in the range [0, 1023], mapping into a 1024-unit sine curve. - int attenuation = 1023; // Will be in the range [0, 1023]. + /// @returns The linear output level for the operator with this state.. + int level(); private: + LogSin attenuation; int raw_phase_ = 0; enum class ADSRPhase { @@ -81,7 +83,7 @@ class Operator { void set_am_vibrato_hold_sustain_ksr_multiple(uint8_t value); /// Provides one clock tick to the operator, along with the relevant parameters of its channel. - void update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorOverrides *overrides = nullptr); + void update(OperatorState &state, bool key_on, int channel_period, int channel_octave, int phase_offset, OperatorOverrides *overrides = nullptr); /// @returns @c true if this channel currently has a non-zero output; @c false otherwise. bool is_audible(OperatorState &state, OperatorOverrides *overrides = nullptr); diff --git a/Components/OPL2/OPL2.cpp b/Components/OPL2/OPL2.cpp index eb5049dae..be77dbd93 100644 --- a/Components/OPL2/OPL2.cpp +++ b/Components/OPL2/OPL2.cpp @@ -168,8 +168,8 @@ void OPLL::setup_fixed_instrument(int number, const uint8_t *data) { modulator->set_scaling_output(data[2]); // Set waveforms — only sine and halfsine are available. - carrier->set_waveform((data[3] >> 4) & 1); modulator->set_waveform((data[3] >> 3) & 1); + carrier->set_waveform((data[3] >> 4) & 1); // TODO: data[3] b0-b2: modulator feedback level // TODO: data[3] b6, b7: carrier key-scale level