diff --git a/Components/OPL2/Implementation/Channel.cpp b/Components/OPL2/Implementation/Channel.cpp index 8dcb55f43..d2d84e612 100644 --- a/Components/OPL2/Implementation/Channel.cpp +++ b/Components/OPL2/Implementation/Channel.cpp @@ -33,16 +33,16 @@ void Channel::set_feedback_mode(uint8_t value) { use_fm_synthesis_ = value & 1; } -int Channel::update(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides, OperatorOverrides *carrier_overrides) { +int Channel::update_melodic(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, bool force_key_on, OperatorOverrides *modulator_overrides, OperatorOverrides *carrier_overrides) { if(use_fm_synthesis_) { // Get modulator level, use that as a phase-adjusting input to the carrier and then return the carrier level. - modulator->update(modulator_state_, nullptr, oscillator, key_on_, period_ << frequency_shift_, octave_, modulator_overrides); - carrier->update(carrier_state_, &modulator_state_, oscillator, key_on_, period_ << frequency_shift_, octave_, carrier_overrides); + modulator->update(modulator_state_, nullptr, oscillator, key_on_ || force_key_on, period_ << frequency_shift_, octave_, modulator_overrides); + carrier->update(carrier_state_, &modulator_state_, oscillator, key_on_ || force_key_on, period_ << frequency_shift_, octave_, carrier_overrides); return carrier_state_.level(); } else { // Get modulator and carrier levels separately, return their sum. - modulator->update(modulator_state_, nullptr, oscillator, key_on_, period_ << frequency_shift_, octave_, modulator_overrides); - carrier->update(carrier_state_, nullptr, oscillator, key_on_, period_ << frequency_shift_, octave_, carrier_overrides); + modulator->update(modulator_state_, nullptr, oscillator, key_on_ || force_key_on, period_ << frequency_shift_, octave_, modulator_overrides); + carrier->update(carrier_state_, nullptr, oscillator, key_on_ || force_key_on, period_ << frequency_shift_, octave_, carrier_overrides); return (modulator_state_.level() + carrier_state_.level()); } } diff --git a/Components/OPL2/Implementation/Channel.hpp b/Components/OPL2/Implementation/Channel.hpp index 122b051b6..4f45e7c37 100644 --- a/Components/OPL2/Implementation/Channel.hpp +++ b/Components/OPL2/Implementation/Channel.hpp @@ -39,9 +39,14 @@ class Channel { /// associated with this channel, and whether FM synthesis is in use. void set_feedback_mode(uint8_t value); - /// This should be called at a rate of around 49,716 Hz; it returns the current output level - /// level for this channel. - int update(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides = nullptr, OperatorOverrides *carrier_overrides = nullptr); + /// Updates this channel, using the operators for melodic output. + int update_melodic(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, bool force_key_on = false, OperatorOverrides *modulator_overrides = nullptr, OperatorOverrides *carrier_overrides = nullptr); + + /// Updates this channel, using the carrier to produce a snare drum and the modulator to produce a tom tom. + int update_snare_tom_tom(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides = nullptr, OperatorOverrides *carrier_overrides = nullptr); + + /// Updates this channel, using the carrier to produce a cymbal and the modulator to produce a high-hat. + int update_symbal_high_hat(const LowFrequencyOscillator &oscillator, Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides = nullptr, OperatorOverrides *carrier_overrides = nullptr); /// @returns @c true if this channel is currently producing any audio; @c false otherwise; bool is_audible(Operator *carrier, OperatorOverrides *carrier_overrides = nullptr); diff --git a/Components/OPL2/OPL2.cpp b/Components/OPL2/OPL2.cpp index 710c93b2a..68cecbb00 100644 --- a/Components/OPL2/OPL2.cpp +++ b/Components/OPL2/OPL2.cpp @@ -31,8 +31,8 @@ template class Yamaha::OPL::OPLBase; OPLL::OPLL(Concurrency::DeferringAsyncTaskQueue &task_queue, int audio_divider, bool is_vrc7): OPLBase(task_queue), audio_divider_(audio_divider) { // Due to the way that sound mixing works on the OPLL, the audio divider may not - // be larger than 2. - assert(audio_divider <= 2); + // be larger than 4. + assert(audio_divider <= 4); // Install fixed instruments. const uint8_t *patch_set = is_vrc7 ? vrc7_patch_set : opll_patch_set; @@ -64,12 +64,12 @@ void OPLL::get_samples(std::size_t number_of_samples, std::int16_t *target) { // unlike the OPL2 the OPLL time-divides the output for 'mixing'. const int update_period = 72 / audio_divider_; - const int channel_output_period = 1;//2 / audio_divider_; + const int channel_output_period = 4 / audio_divider_; while(number_of_samples--) { if(!audio_offset_) update_all_chanels(); - *target = int16_t(channels_[(audio_offset_ / channel_output_period) % 9].level); + *target = int16_t(output_levels_[audio_offset_ / channel_output_period]); ++target; audio_offset_ = (audio_offset_ + 1) % update_period; } @@ -192,22 +192,61 @@ void OPLL::update_all_chanels() { // Update the LFO. oscillator_.update(); + int channel_levels[9]; + // Channels that are updated for melodic output regardless; // in rhythm mode the final three channels — 6, 7, and 8 — // are lost as their operators are used for drum noises. for(int c = 0; c < 6; ++ c) { - channels_[c].level = (channels_[c].update(oscillator_) * total_volume_) >> 12; + channel_levels[c] = (channels_[c].update_melodic(oscillator_) * total_volume_) >> 12; } + output_levels_[3] = channel_levels[0]; + output_levels_[4] = channel_levels[1]; + output_levels_[5] = channel_levels[2]; + output_levels_[9] = channel_levels[3]; + output_levels_[10] = channel_levels[4]; + output_levels_[11] = channel_levels[5]; + if(depth_rhythm_control_ & 0x20) { - // Rhythm mode. Somehow? + // Rhythm mode. + output_levels_[8] = output_levels_[12] = 0; + + // Update channel 6 as if melodic, but with the bass instrument. + output_levels_[2] = output_levels_[15] = + (channels_[6].update_bass(oscillator_, &operators_[32], depth_rhythm_control_ & 0x10) * total_volume_) >> 12; + + // TODO: snare. + output_levels_[6] = output_levels_[16] = 0; + + // TODO: tom tom. + output_levels_[1] = output_levels_[14] = 0; + + // TODO: cymbal. + output_levels_[7] = output_levels_[17] = 0; + + // TODO: high hat. + output_levels_[0] = output_levels_[13] = 0; } else { // Not in rhythm mode; channels 7, 8 and 9 are melodic. for(int c = 7; c < 9; ++ c) { - channels_[c].level = (channels_[c].update(oscillator_) * total_volume_) >> 12; + channel_levels[c] = (channels_[c].update_melodic(oscillator_) * total_volume_) >> 12; } + + output_levels_[0] = output_levels_[1] = output_levels_[2] = + output_levels_[6] = output_levels_[7] = output_levels_[8] = + output_levels_[12] = output_levels_[13] = output_levels_[14] = 0; + + output_levels_[15] = channel_levels[3]; + output_levels_[16] = channel_levels[4]; + output_levels_[17] = channel_levels[5]; } + // Test! +// for(int c = 0; c < 18; ++c) { +// if(c != 2 && c != 15) output_levels_[c] = 0; +// } + // channels_[2].level = (channels_[2].update() * total_volume_) >> 14; } diff --git a/Components/OPL2/OPL2.hpp b/Components/OPL2/OPL2.hpp index 8bae530a9..7dbd7d7fd 100644 --- a/Components/OPL2/OPL2.hpp +++ b/Components/OPL2/OPL2.hpp @@ -95,8 +95,12 @@ struct OPLL: public OPLBase { struct Channel: public ::Yamaha::OPL::Channel { - int update(const LowFrequencyOscillator &oscillator) { - return Yamaha::OPL::Channel::update(oscillator, modulator, modulator + 1, nullptr, &overrides); + int update_melodic(const LowFrequencyOscillator &oscillator) { + return Yamaha::OPL::Channel::update_melodic(oscillator, modulator, modulator + 1, false, nullptr, &overrides); + } + + int update_bass(const LowFrequencyOscillator &oscillator, Operator *bass, bool key_on) { + return Yamaha::OPL::Channel::update_melodic(oscillator, bass, bass + 1, key_on, nullptr, &overrides); } bool is_audible() { @@ -105,10 +109,10 @@ struct OPLL: public OPLBase { Operator *modulator; // Implicitly, the carrier is modulator+1. OperatorOverrides overrides; - int level = 0; }; void update_all_chanels(); Channel channels_[9]; + int output_levels_[18]; void setup_fixed_instrument(int number, const uint8_t *data); uint8_t custom_instrument_[8];