diff --git a/Components/OPL2/Implementation/Channel.cpp b/Components/OPL2/Implementation/Channel.cpp deleted file mode 100644 index 6387b5e00..000000000 --- a/Components/OPL2/Implementation/Channel.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Channel.cpp -// Clock Signal -// -// Created by Thomas Harte on 15/04/2020. -// Copyright © 2020 Thomas Harte. All rights reserved. -// - -#include "Channel.hpp" - -using namespace Yamaha::OPL; - -void Channel::set_frequency_low(uint8_t value) { - period_ = (period_ &~0xff) | value; -} - -void Channel::set_10bit_frequency_octave_key_on(uint8_t value) { - period_ = (period_ & 0xff) | ((value & 3) << 8); - octave_ = (value >> 2) & 0x7; - key_on_ = value & 0x20; - frequency_shift_ = 0; -} - -void Channel::set_9bit_frequency_octave_key_on(uint8_t value) { - period_ = (period_ & 0xff) | ((value & 1) << 8); - octave_ = (value >> 1) & 0x7; - key_on_ = value & 0x10;; - frequency_shift_ = 1; -} - -void Channel::set_feedback_mode(uint8_t value) { - feedback_strength_ = (value >> 1) & 0x7; - use_fm_synthesis_ = value & 1; -} - -void Channel::update(bool modulator, const LowFrequencyOscillator &oscillator, Operator &op, bool force_key_on, OperatorOverrides *overrides) { - op.update(states_[int(modulator)], oscillator, key_on_ || force_key_on, period_ << frequency_shift_, octave_, overrides); -} - -int Channel::melodic_output(const Operator &modulator, const Operator &carrier, const OperatorOverrides *overrides) const { - if(use_fm_synthesis_) { - // Get modulator level, use that as a phase-adjusting input to the carrier and then return the carrier level. - const LogSign modulator_output = modulator.melodic_output(states_[1]); - return carrier.melodic_output(states_[0], &modulator_output, overrides).level(); - } else { - // Get modulator and carrier levels separately, return their sum. - return (carrier.melodic_output(states_[0], nullptr, overrides).level() + modulator.melodic_output(states_[1], nullptr, overrides).level()) >> 1; - } -} - -int Channel::tom_tom_output(const Operator &modulator, const OperatorOverrides *overrides) const { - return modulator.melodic_output(states_[1], nullptr, overrides).level(); -} - -int Channel::snare_output(const Operator &carrier, const OperatorOverrides *overrides) const { - return carrier.snare_output(states_[0], overrides).level(); -} - -int Channel::cymbal_output(const Operator &modulator, const Operator &carrier, const Channel &channel8, const OperatorOverrides *overrides) const { - return carrier.cymbal_output(states_[0], channel8.states_[1], overrides).level(); -} - -int Channel::high_hat_output(const Operator &modulator, const Operator &carrier, const Channel &channel8, const OperatorOverrides *overrides) const { - return carrier.high_hat_output(states_[0], channel8.states_[1], overrides).level(); -} - -bool Channel::is_audible(Operator *carrier, OperatorOverrides *overrides) { - return carrier->is_audible(states_[0], overrides); -} diff --git a/Components/OPL2/Implementation/Channel.hpp b/Components/OPL2/Implementation/Channel.hpp deleted file mode 100644 index 7872c7b5d..000000000 --- a/Components/OPL2/Implementation/Channel.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Channel.hpp -// Clock Signal -// -// Created by Thomas Harte on 15/04/2020. -// Copyright © 2020 Thomas Harte. All rights reserved. -// - -#ifndef Channel_hpp -#define Channel_hpp - -#include "LowFrequencyOscillator.hpp" -#include "Operator.hpp" - -namespace Yamaha { -namespace OPL { - -/*! - Models an L-type two-operator channel. - - Assuming FM synthesis is enabled, the channel modulates the output of the carrier with that of the modulator. - - TODO: make this a template on period counter size in bits? -*/ -class Channel { - public: - /// Sets the low 8 bits of frequency control. - void set_frequency_low(uint8_t value); - - /// Sets the high two bits of a 10-bit frequency control, along with this channel's - /// block/octave, and key on or off. - void set_10bit_frequency_octave_key_on(uint8_t value); - - /// Sets the high two bits of a 9-bit frequency control, along with this channel's - /// block/octave, and key on or off. - void set_9bit_frequency_octave_key_on(uint8_t value); - - /// Sets the amount of feedback provided to the first operator (i.e. the modulator) - /// associated with this channel, and whether FM synthesis is in use. - void set_feedback_mode(uint8_t value); - - /// Updates one of this channel's operators. - void update(bool modulator, const LowFrequencyOscillator &oscillator, Operator &op, bool force_key_on = false, OperatorOverrides *overrides = nullptr); - - /// Gets regular 'melodic' output for this channel, i.e. the output you'd expect from all channels when not in rhythm mode. - int melodic_output(const Operator &modulator, const Operator &carrier, const OperatorOverrides *overrides = nullptr) const; - - /// Generates tom tom output using this channel's modulator. - int tom_tom_output(const Operator &modulator, const OperatorOverrides *overrides = nullptr) const; - - /// Generates snare output, using this channel's carrier. - int snare_output(const Operator &carrier, const OperatorOverrides *overrides = nullptr) const; - - /// Generates cymbal output, using this channel's modulator and @c channel8 's carrier. - int cymbal_output(const Operator &modulator, const Operator &carrier, const Channel &channel8, const OperatorOverrides *overrides = nullptr) const; - - /// Generates cymbal output, using this channel's modulator and @c channel8 's carrier. - int high_hat_output(const Operator &modulator, const Operator &carrier, const Channel &channel8, const OperatorOverrides *overrides = nullptr) const; - - /// @returns @c true if this channel is currently producing any audio; @c false otherwise; - bool is_audible(Operator *carrier, OperatorOverrides *carrier_overrides = nullptr); - - private: - /// 'F-Num' in the spec; this plus the current octave determines channel frequency. - int period_ = 0; - - /// Linked with the frequency, determines the channel frequency. - int octave_ = 0; - - /// Sets sets this channel on or off, as an input to the ADSR envelope, - bool key_on_ = false; - - /// Sets the degree of feedback applied to the modulator. - int feedback_strength_ = 0; - - /// Selects between FM synthesis, using the modulator to modulate the carrier, or simple mixing of the two - /// underlying operators as completely disjoint entities. - bool use_fm_synthesis_ = true; - - /// Used internally to make both the 10-bit OPL2 frequency selection and 9-bit OPLL/VRC7 frequency - /// selections look the same when passed to the operators. - int frequency_shift_ = 0; - - // Operator state is stored distinctly from Operators because - // carrier/modulator may not be unique per channel — - // on the OPLL there's an extra level of indirection. - OperatorState states_[2]; -}; - -} -} - -#endif /* Channel_hpp */ diff --git a/Components/OPL2/Implementation/Operator.cpp b/Components/OPL2/Implementation/Operator.cpp deleted file mode 100644 index 6e14e538b..000000000 --- a/Components/OPL2/Implementation/Operator.cpp +++ /dev/null @@ -1,308 +0,0 @@ -// -// Operator.cpp -// Clock Signal -// -// Created by Thomas Harte on 15/04/2020. -// Copyright © 2020 Thomas Harte. All rights reserved. -// - -#include "Operator.hpp" - -#include -#include - -using namespace Yamaha::OPL; - -// MARK: - Setters - -void Operator::set_attack_decay(uint8_t value) { - attack_rate_ = (value & 0xf0) >> 2; - decay_rate_ = (value & 0x0f) << 2; -} - -void Operator::set_sustain_release(uint8_t value) { - sustain_level_ = (value & 0xf0) >> 4; - release_rate_ = (value & 0x0f) << 2; -} - -void Operator::set_scaling_output(uint8_t value) { - key_level_scaling_ = value >> 6; - attenuation_ = value & 0x3f; -} - -void Operator::set_waveform(uint8_t value) { - waveform_ = Operator::Waveform(value & 3); -} - -void Operator::set_am_vibrato_hold_sustain_ksr_multiple(uint8_t value) { - apply_amplitude_modulation_ = value & 0x80; - apply_vibrato_ = value & 0x40; - use_sustain_level_ = value & 0x20; - key_rate_scaling_shift_ = (value & 0x10) ? 0 : 2; - frequency_multiple_ = value & 0xf; -} - -// MARK: - Getter - -bool Operator::is_audible(OperatorState &state, OperatorOverrides *overrides) { - // TODO: (i) do I actually want to support this functionality? (ii) if so, fix below. - if(state.adsr_phase_ == OperatorState::ADSRPhase::Release) { - if(overrides) { - if(overrides->attenuation == 0xf) return false; - } else { - if(attenuation_ == 0x3f) return false; - } - } - return state.adsr_attenuation_ != 511; -} - -// MARK: - Update logic. - -void Operator::update_adsr( - OperatorState &state, - const LowFrequencyOscillator &oscillator, - bool key_on, - int channel_period, - int channel_octave, - const OperatorOverrides *overrides) { - // 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. - if(!key_on) { - state.adsr_phase_ = OperatorState::ADSRPhase::Release; - } else if(!state.last_key_on_) { - state.adsr_phase_ = OperatorState::ADSRPhase::Attack; - state.attack_time_ = 0; - - // TODO: should this happen only if current ADSR attenuation is 511? - state.raw_phase_ = 0; - } - state.last_key_on_ = key_on; - - // Adjust the ADSR attenuation appropriately; - // cf. http://forums.submarine.org.uk/phpBB/viewtopic.php?f=9&t=16 (primarily) for the source of the maths below. - - // "An attack rate value of 52 (AR = 13) has 32 samples in the attack phase, an attack rate value of 48 (AR = 12) - // has 64 samples in the attack phase, but pairs of samples show the same envelope attenuation. I am however struggling to find a plausible algorithm to match the experimental results. - - const int key_scaling_rate = ((channel_octave << 1) | (channel_period >> 9)) >> key_rate_scaling_shift_; - assert(key_scaling_rate < 16); - assert((channel_period >> 9) < 2); - - switch(state.adsr_phase_) { - case OperatorState::ADSRPhase::Attack: { - const int attack_rate = attack_rate_ + key_scaling_rate; - - // Rules: - // - // An attack rate of '13' has 32 samples in the attack phase; a rate of '12' has the same 32 steps, but spread out over 64 samples, etc. - // An attack rate of '14' uses a divide by four instead of two. - // 15 is instantaneous. - - if(attack_rate >= 56) { - state.adsr_attenuation_ = state.adsr_attenuation_ - (state.adsr_attenuation_ >> 2) - 1; - } else { - const int sample_length = 1 << (14 - (attack_rate >> 2)); // TODO: don't throw away KSR bits. - if(!(state.attack_time_ & (sample_length - 1))) { - state.adsr_attenuation_ = state.adsr_attenuation_ - (state.adsr_attenuation_ >> 3) - 1; - } - } - - // Two possible terminating conditions: (i) the attack rate is 15; (ii) full volume has been reached. - if(attack_rate > 60 || state.adsr_attenuation_ <= 0) { - state.adsr_attenuation_ = 0; - state.adsr_phase_ = OperatorState::ADSRPhase::Decay; - } - } break; - - case OperatorState::ADSRPhase::Release: - case OperatorState::ADSRPhase::Decay: - { - // Rules: - // - // (relative to a 511 scale) - // - // A rate of 0 is no decay at all. - // A rate of 1 means increase 4 per cycle. - // A rate of 2 means increase 2 per cycle. - // A rate of 3 means increase 1 per cycle. - // A rate of 4 means increase 1 every other cycle. - // A rate of 5 means increase once every fourth cycle. - // etc. - // eighth, sixteenth, 32nd, 64th, 128th, 256th, 512th, 1024th, 2048th, 4096th, 8192th - const int decrease_rate = key_scaling_rate + ((state.adsr_phase_ == OperatorState::ADSRPhase::Decay) ? decay_rate_ : release_rate_); - - - if(decrease_rate) { - // TODO: don't throw away KSR bits. - switch(decrease_rate >> 2) { - case 1: state.adsr_attenuation_ += 32; break; - case 2: state.adsr_attenuation_ += 16; break; - default: { - const int sample_length = 1 << ((decrease_rate >> 2) - 4); - if(!(oscillator.counter & (sample_length - 1))) { - state.adsr_attenuation_ += 8; - } - } break; - } - } - - // Clamp to the proper range. - state.adsr_attenuation_ = std::min(state.adsr_attenuation_, 511); - - // Check for the decay exit condition. - if(state.adsr_phase_ == OperatorState::ADSRPhase::Decay && state.adsr_attenuation_ >= (sustain_level_ << 3)) { - state.adsr_attenuation_ = sustain_level_ << 3; - state.adsr_phase_ = ((overrides && overrides->use_sustain_level) || use_sustain_level_) ? OperatorState::ADSRPhase::Sustain : OperatorState::ADSRPhase::Release; - } - } break; - - case OperatorState::ADSRPhase::Sustain: - // Nothing to do. - break; - } - ++state.attack_time_; -} - -void Operator::update_phase(OperatorState &state, const LowFrequencyOscillator &oscillator, int channel_period, int channel_octave) { - // Per the documentation: - // - // Delta phase = ( [desired freq] * 2^19 / [input clock / 72] ) / 2 ^ (b - 1) - // - // After experimentation, I think this gives rate calculation as formulated below. - - // This encodes the MUL -> multiple table given on page 12, - // multiplied by two. - 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 + vibrato) << channel_octave; -} - -int Operator::key_level_scaling(const OperatorState &state, int channel_period, int channel_octave) const { - // Calculate key-level scaling. Table is as per p14 of the YM3812 application manual, - // converted into a fixed-point scheme. Compare with https://www.smspower.org/Development/RE12 - // and apologies for the highly ad hoc indentation. - constexpr int key_level_scale_shifts[4] = {7, 1, 2, 0}; // '7' is just a number large enough to render all the numbers below as 0. - constexpr int key_level_scales[8][16] = { -#define _ 0 - // 6 db attenuations. - {_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}, - {_, _, _, _, _, _, _, _, _, 4, 6, 8, 10, 12, 14, 16}, - {_, _, _, _, _, 6, 10, 14, 16, 20, 22, 24, 26, 28, 30, 32}, - {_, _, _, 10, 16, 22, 26, 30, 32, 36, 38, 40, 42, 44, 46, 48}, - {_, _, 16, 26, 32, 38, 42, 46, 48, 52, 54, 56, 58, 60, 62, 64}, - {_, 16, 32, 42, 48, 54, 58, 62, 64, 68, 70, 72, 74, 76, 78, 80}, - {_, 32, 48, 58, 64, 70, 74, 78, 80, 84, 86, 88, 90, 92, 94, 96}, - {_, 48, 64, 74, 80, 86, 90, 94, 96, 100, 102, 104, 106, 108, 110, 112}, -#undef _ - }; - assert((channel_period >> 6) < 16); - assert(channel_octave < 8); - return (key_level_scales[channel_octave][channel_period >> 6] >> key_level_scale_shifts[key_level_scaling_]) << 7; -} - -int Operator::adsr_tremolo_attenuation(const OperatorState &state, const LowFrequencyOscillator &oscillator) const { - // Add optional tremolo to the current ADSR attenuation. - return (state.adsr_attenuation_ << 3) + (int(apply_amplitude_modulation_) * oscillator.tremolo << 4); -} - -int Operator::fixed_attenuation(const OperatorState &state, const OperatorOverrides *overrides) const { - if(overrides) { - // 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). - return overrides->attenuation << 7; - } else { - // Overrides here represent per-channel volume on an OPLL. The bits are defined to represent - // attenuations of 24db to 0.75db. - return attenuation_ << 5; - } -} - -void Operator::update( - OperatorState &state, - const LowFrequencyOscillator &oscillator, - bool key_on, - int channel_period, - int channel_octave, - const OperatorOverrides *overrides) { - update_adsr(state, oscillator, key_on, channel_period, channel_octave, overrides); - update_phase(state, oscillator, channel_period, channel_octave); - state.key_level_scaling_ = key_level_scaling(state, channel_period, channel_octave); - state.adsr_tremolo_attenuation_ = adsr_tremolo_attenuation(state, oscillator); - state.lfsr_ = oscillator.lfsr; -} - -// TODO: both the tremolo and ADSR envelopes should be half-resolution on an OPLL. - -// MARK: - Output Generators. - -// A heavy debt is owed to https://github.com/andete/ym2413/blob/master/results/rhythm/rhythm.md regarding -// the drum sound generation below. - -LogSign Operator::melodic_output(const OperatorState &state, const LogSign *phase_offset, const OperatorOverrides *overrides) const { - // Calculate raw attenuation level. - 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. - {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 scaled_phase_offset = phase_offset ? phase_offset->level(11) : 0; - const int phase = (state.raw_phase_ + scaled_phase_offset) >> 11; - - LogSign result = negative_log_sin(phase & waveforms[int(waveform_)][(phase >> 8) & 3]); - result += state.key_level_scaling_; - result += state.adsr_tremolo_attenuation_ + fixed_attenuation(state, overrides); - return result; -} - -LogSign Operator::snare_output(const OperatorState &state, const OperatorOverrides *overrides) const { - LogSign result; - - // If noise is 0, output is positive. - // If noise is 1, output is negative. - // If (noise ^ sign) is 0, output is 0. Otherwise it is max. - const int sign = (state.raw_phase_ >> 11) & 0x200; - const int level = ((state.raw_phase_ >> 20) & 1) ^ state.lfsr_; - result = negative_log_sin(sign + (level << 8)); - - result += state.key_level_scaling_; - result += state.adsr_tremolo_attenuation_ + fixed_attenuation(state, overrides); - return result; -} - -LogSign Operator::cymbal_output(const OperatorState &state, const OperatorState &modulator, const OperatorOverrides *overrides) const { - const int output = - ((state.raw_phase_ >> 16) ^ (state.raw_phase_ >> 14)) & - ((modulator.raw_phase_ >> 18) ^ (modulator.raw_phase_ >> 13)) & - ((state.raw_phase_ >> 16) ^ (modulator.raw_phase_ >> 14)); - - constexpr int angles[] = {256, 768}; - LogSign result = negative_log_sin(angles[output & 1]); - - result += state.key_level_scaling_; - result += state.adsr_tremolo_attenuation_ + fixed_attenuation(state, overrides); - return result; -} - -LogSign Operator::high_hat_output(const OperatorState &state, const OperatorState &modulator, const OperatorOverrides *overrides) const { - const int output = - ((state.raw_phase_ >> 16) ^ (state.raw_phase_ >> 14)) & - ((modulator.raw_phase_ >> 18) ^ (modulator.raw_phase_ >> 13)) & - ((state.raw_phase_ >> 16) ^ (modulator.raw_phase_ >> 14)); - - constexpr int angles[] = {0x234, 0xd0, 0x2d0, 0x34}; - LogSign result = negative_log_sin(angles[(output & 1) | (state.lfsr_ << 1)]); - - result += state.key_level_scaling_; - result += state.adsr_tremolo_attenuation_ + fixed_attenuation(state, overrides); - return result; -} diff --git a/Components/OPL2/Implementation/Operator.hpp b/Components/OPL2/Implementation/Operator.hpp deleted file mode 100644 index aa73c5dcb..000000000 --- a/Components/OPL2/Implementation/Operator.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// Operator.hpp -// Clock Signal -// -// Created by Thomas Harte on 15/04/2020. -// Copyright © 2020 Thomas Harte. All rights reserved. -// - -#ifndef Operator_hpp -#define Operator_hpp - -#include -#include "Tables.hpp" -#include "LowFrequencyOscillator.hpp" - -namespace Yamaha { -namespace OPL { - -/*! - Opaquely describes the ephemeral state of an operator. -*/ -struct OperatorState { - private: - friend class Operator; - - int raw_phase_ = 0; - enum class ADSRPhase { - Attack, Decay, Sustain, Release - } adsr_phase_ = ADSRPhase::Attack; - int adsr_attenuation_ = 511; - int attack_time_ = 0; - - int key_level_scaling_; - int adsr_tremolo_attenuation_; - int lfsr_; - - bool last_key_on_ = false; -}; - -/*! - Describes parts of an operator that are genuinely stored per-operator on the OPLL; - these can be provided to the Operator in order to have it ignore its local values - if the host is an OPLL or VRC7. -*/ -struct OperatorOverrides { - int attenuation = 0; - bool use_sustain_level = false; -}; - -/*! - Models an operator. - - In Yamaha FM terms, an operator is a combination of a few things: - - * an oscillator, producing one of a handful of sine-derived waveforms; - * an ADSR output level envelope; and - * a bunch of potential adjustments to those two things: - * optional tremolo and/or vibrato (the rates of which are global); - * the option to skip 'sustain' in ADSR and go straight to release (since no sustain period is supplied, - it otherwise runs for as long as the programmer leaves a channel enabled); - * an attenuation for the output level; and - * a factor by which to speed up the ADSR envelope as a function of frequency. - - Oscillator period isn't set directly, it's a multiple of the owning channel, in which - period is set as a combination of f-num and octave. -*/ -class Operator { - public: - /// Sets this operator's attack rate as the top nibble of @c value, its decay rate as the bottom nibble. - void set_attack_decay(uint8_t value); - - /// Sets this operator's sustain level as the top nibble of @c value, its release rate as the bottom nibble. - void set_sustain_release(uint8_t value); - - /// Sets this operator's key scale level as the top two bits of @c value, its total output level as the low six bits. - void set_scaling_output(uint8_t value); - - /// Sets this operator's waveform using the low two bits of @c value. - void set_waveform(uint8_t value); - - /// From the top nibble of @c value sets the AM, vibrato, hold/sustain level and keyboard sampling rate flags; - /// uses the bottom nibble to set the period multiplier. - 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, - const LowFrequencyOscillator &oscillator, - bool key_on, - int channel_period, - int channel_octave, - const 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); - - /// Provides ordinary melodic output, optionally with modulation. - LogSign melodic_output(const OperatorState &state, const LogSign *phase_offset = nullptr, const OperatorOverrides *overrides = nullptr) const; - - /// Provides snare drum output, which is a function of phase and the captured LFSR level. - LogSign snare_output(const OperatorState &state, const OperatorOverrides *overrides = nullptr) const; - - /// Provides cymbal output, which is a function of the phase given by @c state, ordinarily the carrier of channel 8, - /// and the phase of @c modulator, which is ordinarily the modulator of channel 7. - LogSign cymbal_output(const OperatorState &state, const OperatorState &modulator, const OperatorOverrides *overrides = nullptr) const; - - /// Provides high-hat output, which is a function of the phase given by @c state, ordinarily the carrier of channel 8, - /// and the phase of @c modulator, which is ordinarily the modulator of channel 7. - LogSign high_hat_output(const OperatorState &state, const OperatorState &modulator, const OperatorOverrides *overrides = nullptr) const; - - private: - /// If true then an amplitude modulation of "3.7Hz" is applied, - /// with a depth "determined by the AM-DEPTH of the BD register"? - bool apply_amplitude_modulation_ = false; - - /// If true then a vibrato of '6.4 Hz' is applied, with a depth - /// "determined by VOB_DEPTH of the BD register"? - bool apply_vibrato_ = false; - - /// Selects between an ADSR envelope that holds at the sustain level - /// for as long as this key is on, releasing afterwards, and one that - /// simply switches straight to the release rate once the sustain - /// level is hit, getting back to 0 regardless of an ongoing key-on. - bool use_sustain_level_ = false; - - /// Indexes a lookup table to determine what multiple of the channel's frequency - /// this operator is advancing at. - int frequency_multiple_ = 0; - - /// Sets the current output level of this modulator, as an attenuation. - int attenuation_ = 0; - - /// Provides a potential faster step through the ADSR envelope. Cf. p12. - int key_rate_scaling_shift_ = 0; - - /// Selects attenuation that is applied as a function of interval. Cf. p14. - int key_level_scaling_ = 0; - - /// Sets the ADSR rates. These all provide the top four bits of a six-bit number; - /// the bottom two bits... are 'RL'? - int attack_rate_ = 0; - int decay_rate_ = 0; - int sustain_level_ = 0; - int release_rate_ = 0; - - /// Selects the generated waveform. - enum class Waveform { - Sine, HalfSine, AbsSine, PulseSine - } waveform_ = Waveform::Sine; - - /// Updates the ADSR envelope. - void update_adsr( - OperatorState &state, - const LowFrequencyOscillator &oscillator, - bool key_on, - int channel_period, - int channel_octave, - const OperatorOverrides *overrides); - - /// Updates the phase generator. - void update_phase(OperatorState &state, const LowFrequencyOscillator &oscillator, int channel_period, int channel_octave); - - /// Adds key-level scaling to the current output state. - int key_level_scaling(const OperatorState &state, int channel_period, int channel_octave) const; - - /// Adds ADSR and general channel attenuations to the output state. - int adsr_tremolo_attenuation(const OperatorState &state, const LowFrequencyOscillator &oscillator) const; - - int fixed_attenuation(const OperatorState &state, const OperatorOverrides *overrides) const; - -}; - -} -} - -#endif /* Operator_hpp */ diff --git a/Components/OPL2/OPL2.cpp b/Components/OPL2/OPL2.cpp deleted file mode 100644 index 6fc19ca59..000000000 --- a/Components/OPL2/OPL2.cpp +++ /dev/null @@ -1,398 +0,0 @@ -// -// OPL2.cpp -// Clock Signal -// -// Created by Thomas Harte on 02/04/2020. -// Copyright © 2020 Thomas Harte. all rights reserved. -// - -#include "OPL2.hpp" - -#include -#include - -#include "Implementation/PhaseGenerator.hpp" -#include "Implementation/EnvelopeGenerator.hpp" -#include "Implementation/KeyLevelScaler.hpp" -#include "Implementation/WaveformGenerator.hpp" - -using namespace Yamaha::OPL; - -/* - -template -OPLBase::OPLBase(Concurrency::DeferringAsyncTaskQueue &task_queue) : task_queue_(task_queue) {} - -template -void OPLBase::write(uint16_t address, uint8_t value) { - if(address & 1) { - static_cast(this)->write_register(selected_register_, value); - } else { - selected_register_ = value; - } -} - -template class Yamaha::OPL::OPLBase; -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 4. - assert(audio_divider <= 4); - - // Install fixed instruments. - const uint8_t *patch_set = is_vrc7 ? vrc7_patch_set : opll_patch_set; - for(int c = 0; c < 15; ++c) { - setup_fixed_instrument(c+1, patch_set); - patch_set += 8; - } - - // Install rhythm patches. - for(int c = 0; c < 3; ++c) { - setup_fixed_instrument(c+16, &percussion_patch_set[c * 8]); - } - - // Set default modulators. - for(int c = 0; c < 9; ++c) { - channels_[c].modulator = &operators_[0]; - } -} - -bool OPLL::is_zero_level() { -// for(int c = 0; c < 9; ++c) { -// if(channels_[c].is_audible()) return false; -// } - return false; -} - -void OPLL::get_samples(std::size_t number_of_samples, std::int16_t *target) { - // Both the OPLL and the OPL2 divide the input clock by 72 to get the base tick frequency; - // unlike the OPL2 the OPLL time-divides the output for 'mixing'. - - const int update_period = 72 / audio_divider_; - const int channel_output_period = 4 / audio_divider_; - - while(number_of_samples--) { - if(!audio_offset_) update_all_chanels(); - - *target = int16_t(output_levels_[audio_offset_ / channel_output_period]); - ++target; - audio_offset_ = (audio_offset_ + 1) % update_period; - } - -// // Fill in any leftover from the previous session. -// if(audio_offset_) { -// while(audio_offset_ < update_period && number_of_samples) { -// *target = int16_t(channels_[audio_offset_ / channel_output_period].level); -// ++target; -// ++audio_offset_; -// --number_of_samples; -// } -// audio_offset_ = 0; -// } -// -// // End now if that provided everything that was asked for. -// if(!number_of_samples) return; -// -// int total_updates = int(number_of_samples) / update_period; -// number_of_samples %= size_t(update_period); -// audio_offset_ = int(number_of_samples); -// -// while(total_updates--) { -// update_all_chanels(); -// -// for(int c = 0; c < update_period; ++c) { -// *target = int16_t(channels_[c / channel_output_period].level); -// ++target; -// } -// } -// -// // If there are any other spots remaining, fill them. -// if(number_of_samples) { -// update_all_chanels(); -// -// for(int c = 0; c < int(number_of_samples); ++c) { -// *target = int16_t(channels_[c / channel_output_period].level); -// ++target; -// } -// } -} - -void OPLL::set_sample_volume_range(std::int16_t range) { - total_volume_ = range; -} - -uint8_t OPLL::read(uint16_t address) { - // I've seen mention of an undocumented two-bit status register. I don't yet know what is in it. - return 0xff; -} - -void OPLL::write_register(uint8_t address, uint8_t value) { - // The OPLL doesn't have timers or other non-audio functions, so all writes - // go to the audio queue. - task_queue_.defer([this, address, value] { - // The first 8 locations are used to define the custom instrument, and have - // exactly the same format as the patch set arrays at the head of this file. - if(address < 8) { - custom_instrument_[address] = value; - - // Update whatever that did to the instrument. - setup_fixed_instrument(0, custom_instrument_); - return; - } - - // Register 0xe is a cut-down version of the OPLL's register 0xbd. - if(address == 0xe) { - depth_rhythm_control_ = value & 0x3f; -// if(depth_rhythm_control_ & 0x08) -// printf("%02x\n", depth_rhythm_control_); - return; - } - - const auto index = address & 0xf; - if(index > 8) return; - - switch(address & 0xf0) { - case 0x30: - // Select an instrument in the top nibble, set a channel volume in the lower. - channels_[index].overrides.attenuation = value & 0xf; - channels_[index].modulator = &operators_[(value >> 4) * 2]; - - // Also crib volume levels for rhythm mode, possibly. - if(index >= 6) { - rhythm_overrides_[(index - 6) * 2 + 0].attenuation = value >> 4; - rhythm_overrides_[(index - 6) * 2 + 1].attenuation = value & 0xf; - } - break; - - case 0x10: channels_[index].set_frequency_low(value); break; - - case 0x20: - // Set sustain on/off, key on/off, octave and a single extra bit of frequency. - // So they're a lot like OPLL registers 0xb0 to 0xb8, but not identical. - channels_[index].set_9bit_frequency_octave_key_on(value); - channels_[index].overrides.use_sustain_level = value & 0x20; - break; - - default: printf("Unknown write to %02x?!?\n", address); break; - } - }); -} - -void OPLL::setup_fixed_instrument(int number, const uint8_t *data) { - auto modulator = &operators_[number * 2]; - auto carrier = &operators_[number * 2 + 1]; - - modulator->set_am_vibrato_hold_sustain_ksr_multiple(data[0]); - carrier->set_am_vibrato_hold_sustain_ksr_multiple(data[1]); - modulator->set_scaling_output(data[2]); - - // Set waveforms — only sine and halfsine are available. - 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 - - // Set ADSR parameters. - modulator->set_attack_decay(data[4]); - carrier->set_attack_decay(data[5]); - modulator->set_sustain_release(data[6]); - carrier->set_sustain_release(data[7]); -} - -void OPLL::update_all_chanels() { - // Update the LFO and then the channels. - oscillator_.update(); - for(int c = 0; c < 6; ++c) { - channels_[c].update(oscillator_); - oscillator_.update_lfsr(); // TODO: should update per slot, not per channel? Or even per cycle? - } - - output_levels_[8] = output_levels_[12] = 0; - -#define VOLUME(x) ((x) * total_volume_) >> 12 - - // 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. - output_levels_[3] = VOLUME(channels_[0].melodic_output()); - output_levels_[4] = VOLUME(channels_[1].melodic_output()); - output_levels_[5] = VOLUME(channels_[2].melodic_output()); - - output_levels_[9] = VOLUME(channels_[3].melodic_output()); - output_levels_[10] = VOLUME(channels_[4].melodic_output()); - output_levels_[11] = VOLUME(channels_[5].melodic_output()); - - if(depth_rhythm_control_ & 0x20) { - // TODO: pervasively, volume. And LFSR updates. - - channels_[6].update(oscillator_, &operators_[32], depth_rhythm_control_ & 0x10); - channels_[7].update(true, oscillator_, operators_[34], bool(depth_rhythm_control_ & 0x01)); - channels_[7].update(false, oscillator_, operators_[35], bool(depth_rhythm_control_ & 0x08)); - channels_[8].update(true, oscillator_, operators_[36], bool(depth_rhythm_control_ & 0x04)); - channels_[8].update(false, oscillator_, operators_[37], bool(depth_rhythm_control_ & 0x02)); - - // Update channel 6 as if melodic, but with the bass instrument. - output_levels_[2] = output_levels_[15] = VOLUME(channels_[6].melodic_output(&rhythm_overrides_[1])); - - // Use the carrier from channel 7 for the snare. - output_levels_[6] = output_levels_[16] = VOLUME(channels_[7].snare_output(operators_[35], &rhythm_overrides_[3])); - - // Use the modulator from channel 8 for the tom tom. - output_levels_[1] = output_levels_[14] = VOLUME(channels_[8].tom_tom_output(operators_[37], &rhythm_overrides_[4])); - - // Use the channel 7 modulator and the channel 8 carrier for a cymbal. - output_levels_[7] = output_levels_[17] = VOLUME(channels_[7].cymbal_output(operators_[36], operators_[35], channels_[8], &rhythm_overrides_[5])); - - // Use the channel 7 modulator and the channel 8 modulator (?) for a high-hat. - output_levels_[0] = output_levels_[13] = VOLUME(channels_[7].high_hat_output(operators_[36], operators_[35], channels_[8], &rhythm_overrides_[2])); - } else { - // Not in rhythm mode; channels 7, 8 and 9 are melodic. - for(int c = 6; c < 9; ++ c) { - channels_[c].update(oscillator_); - oscillator_.update_lfsr(); // TODO: should update per slot, not per channel? Or even per cycle? - } - - output_levels_[0] = output_levels_[1] = output_levels_[2] = - output_levels_[6] = output_levels_[7] = - output_levels_[13] = output_levels_[14] = 0; - - output_levels_[15] = VOLUME(channels_[6].melodic_output()); - output_levels_[16] = VOLUME(channels_[7].melodic_output()); - output_levels_[17] = VOLUME(channels_[8].melodic_output()); - } - - // Test! -// for(int c = 0; c < 18; ++c) { -// if(c != 6 && c != 16) -// output_levels_[c] = 0; -// } - -// channels_[2].level = (channels_[2].update() * total_volume_) >> 14; - -#undef VOLUME -} - - -//template -//void OPL2::get_samples(std::size_t number_of_samples, std::int16_t *target) { - // TODO. - // out = exp(logsin(phase2 + exp(logsin(phase1) + gain1)) + gain2) - -// Melodic channels are: -// -// Channel Operator 1 Operator 2 -// 0 0 3 -// 1 1 4 -// 2 2 5 -// 3 6 9 -// 4 7 10 -// 5 8 11 -// 6 12 15 -// 7 13 16 -// 8 14 17 -// -// In percussion mode, only channels 0–5 are use as melodic, with 6, 7 and 8 being -// replaced by: -// -// Bass drum, using operators 12 and 15; -// Snare, using operator 16; -// Tom tom, using operator 14, -// Cymbal, using operator 17; and -// Symbol, using operator 13. -//} - - - -void OPL2::write_register(uint8_t address, uint8_t value) { - - // Deal with timer changes synchronously. - switch(address) { - case 0x02: timers_[0] = value; return; - case 0x03: timers_[1] = value; return; - case 0x04: timer_control_ = value; return; - // TODO from register 4: - // b7 = IRQ reset; - // b6/b5 = timer 1/2 mask (irq enabling flags, I think?) - // b4/b3 = timer 2/1 start (seemingly the opposite order to b6/b5?) - - default: break; - } - - // Enqueue any changes that affect audio output. - task_queue_.enqueue([this, address, value] { - // - // Modal modifications. - // - - switch(address) { - case 0x01: waveform_enable_ = value & 0x20; break; - case 0x08: - // b7: "composite sine wave mode on/off"? - csm_keyboard_split_ = value; - // b6: "Controls the split point of the keyboard. When 0, the keyboard split is the - // second bit from the bit 8 of the F-Number. When 1, the MSB of the F-Number is used." - break; - case 0xbd: depth_rhythm_control_ = value; break; - - default: break; - } - - - // - // Operator modifications. - // - - if((address >= 0x20 && address < 0xa0) || address >= 0xe0) { - // The 18 operators are spreat out across 22 addresses; each group of - // six is framed within an eight-byte area thusly: - constexpr int operator_by_address[] = { - 0, 1, 2, 3, 4, 5, -1, -1, - 6, 7, 8, 9, 10, 11, -1, -1, - 12, 13, 14, 15, 16, 17, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - }; - - const auto index = operator_by_address[address & 0x1f]; - if(index == -1) return; - - switch(address & 0xe0) { - case 0x20: operators_[index].set_am_vibrato_hold_sustain_ksr_multiple(value); break; - case 0x40: operators_[index].set_scaling_output(value); break; - case 0x60: operators_[index].set_attack_decay(value); break; - case 0x80: operators_[index].set_sustain_release(value); break; - case 0xe0: operators_[index].set_waveform(value); break; - - default: break; - } - } - - - // - // Channel modifications. - // - - const auto index = address & 0xf; - if(index > 8) return; - - switch(address & 0xf0) { - case 0xa0: channels_[index].set_frequency_low(value); break; - case 0xb0: channels_[index].set_10bit_frequency_octave_key_on(value); break; - case 0xc0: channels_[index].set_feedback_mode(value); break; - - default: break; - } - }); -} - -uint8_t OPL2::read(uint16_t address) { - // TODO. There's a status register where: - // b7 = IRQ status (set if interrupt request ongoing) - // b6 = timer 1 flag (set if timer 1 expired) - // b5 = timer 2 flag - return 0xff; -} - -*/ diff --git a/Components/OPL2/OPL2.hpp b/Components/OPL2/OPL2.hpp deleted file mode 100644 index a583c0848..000000000 --- a/Components/OPL2/OPL2.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// OPL2.hpp -// Clock Signal -// -// Created by Thomas Harte on 02/04/2020. -// Copyright © 2020 Thomas Harte. All rights reserved. -// - -#ifndef OPL2_hpp -#define OPL2_hpp - -#include "../../Outputs/Speaker/Implementation/SampleSource.hpp" -#include "../../Concurrency/AsyncTaskQueue.hpp" - -#include "Implementation/Channel.hpp" -#include "Implementation/Operator.hpp" - -#include - -namespace Yamaha { -namespace OPL { - -/* -struct OPL2: public OPLBase { - public: - // Creates a new OPL2. - OPL2(Concurrency::DeferringAsyncTaskQueue &task_queue); - - /// As per ::SampleSource; provides a broadphase test for silence. - bool is_zero_level(); - - /// As per ::SampleSource; provides audio output. - void get_samples(std::size_t number_of_samples, std::int16_t *target); - void set_sample_volume_range(std::int16_t range); - - /// Reads from the OPL. - uint8_t read(uint16_t address); - - private: - friend OPLBase; - - Operator operators_[18]; - Channel channels_[9]; - - // Synchronous properties, valid only on the emulation thread. - uint8_t timers_[2] = {0, 0}; - uint8_t timer_control_ = 0; - - void write_register(uint8_t address, uint8_t value); -}; - -struct OPLL: public OPLBase { - public: - // Creates a new OPLL or VRC7. - OPLL(Concurrency::DeferringAsyncTaskQueue &task_queue, int audio_divider = 1, bool is_vrc7 = false); - - /// As per ::SampleSource; provides a broadphase test for silence. - bool is_zero_level(); - - /// As per ::SampleSource; provides audio output. - void get_samples(std::size_t number_of_samples, std::int16_t *target); - void set_sample_volume_range(std::int16_t range); - - /// Reads from the OPL. - uint8_t read(uint16_t address); - - private: - friend OPLBase; - - Operator operators_[38]; // There's an extra level of indirection with the OPLL; these 38 - // operators are to describe 19 hypothetical channels, being - // one user-configurable channel, 15 hard-coded channels, and - // three channels configured for rhythm generation. - - - struct Channel: public ::Yamaha::OPL::Channel { - void update(const LowFrequencyOscillator &oscillator) { - Yamaha::OPL::Channel::update(true, oscillator, modulator[0]); - Yamaha::OPL::Channel::update(false, oscillator, modulator[1], false, &overrides); - } - - void update(const LowFrequencyOscillator &oscillator, Operator *mod, bool key_on) { - Yamaha::OPL::Channel::update(true, oscillator, mod[0], key_on); - Yamaha::OPL::Channel::update(false, oscillator, mod[1], key_on, &overrides); - } - - using ::Yamaha::OPL::Channel::update; - - int melodic_output() { - return Yamaha::OPL::Channel::melodic_output(modulator[0], modulator[1], &overrides); - } - - int melodic_output(const OperatorOverrides *overrides) { - return Yamaha::OPL::Channel::melodic_output(modulator[0], modulator[1], overrides); - } - - bool is_audible() { - return Yamaha::OPL::Channel::is_audible(modulator + 1, &overrides); - } - - Operator *modulator; // Implicitly, the carrier is modulator+1. - OperatorOverrides overrides; - }; - void update_all_chanels(); - Channel channels_[9]; - int output_levels_[18]; - OperatorOverrides rhythm_overrides_[6]; - - void setup_fixed_instrument(int number, const uint8_t *data); - uint8_t custom_instrument_[8]; - - void write_register(uint8_t address, uint8_t value); - - const int audio_divider_ = 1; - int audio_offset_ = 0; - - std::atomic total_volume_; -};*/ - -} -} - -#endif /* OPL2_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 21e8789d3..a2a2db500 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -781,12 +781,6 @@ 4BBFE83D21015D9C00BF1C40 /* CSJoystickManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFE83C21015D9C00BF1C40 /* CSJoystickManager.m */; }; 4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFFEE51F7B27F1005F3FEB /* TrackSerialiser.cpp */; }; 4BC0CB282446BC7B00A79DBB /* OPLTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB272446BC7B00A79DBB /* OPLTests.mm */; }; - 4BC0CB322447EC7D00A79DBB /* Operator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB302447EC7C00A79DBB /* Operator.cpp */; }; - 4BC0CB332447EC7D00A79DBB /* Operator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB302447EC7C00A79DBB /* Operator.cpp */; }; - 4BC0CB342447EC7D00A79DBB /* Operator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB302447EC7C00A79DBB /* Operator.cpp */; }; - 4BC0CB372447EC9A00A79DBB /* Channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB352447EC9A00A79DBB /* Channel.cpp */; }; - 4BC0CB382447EC9A00A79DBB /* Channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB352447EC9A00A79DBB /* Channel.cpp */; }; - 4BC0CB392447EC9A00A79DBB /* Channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC0CB352447EC9A00A79DBB /* Channel.cpp */; }; 4BC131702346DE5000E4FF3D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC1316F2346DE5000E4FF3D /* StaticAnalyser.cpp */; }; 4BC131712346DE5000E4FF3D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC1316F2346DE5000E4FF3D /* StaticAnalyser.cpp */; }; 4BC131762346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC131752346DE9100E4FF3D /* StaticAnalyser.cpp */; }; @@ -1666,10 +1660,6 @@ 4BBFE83E21015DAE00BF1C40 /* CSJoystickManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSJoystickManager.h; sourceTree = ""; }; 4BBFFEE51F7B27F1005F3FEB /* TrackSerialiser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TrackSerialiser.cpp; sourceTree = ""; }; 4BC0CB272446BC7B00A79DBB /* OPLTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OPLTests.mm; sourceTree = ""; }; - 4BC0CB302447EC7C00A79DBB /* Operator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Operator.cpp; sourceTree = ""; }; - 4BC0CB312447EC7C00A79DBB /* Operator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Operator.hpp; sourceTree = ""; }; - 4BC0CB352447EC9A00A79DBB /* Channel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Channel.cpp; sourceTree = ""; }; - 4BC0CB362447EC9A00A79DBB /* Channel.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Channel.hpp; sourceTree = ""; }; 4BC0CB3A2447ECAE00A79DBB /* Tables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Tables.hpp; sourceTree = ""; }; 4BC1316D2346DE5000E4FF3D /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; 4BC1316E2346DE5000E4FF3D /* Target.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = ""; }; @@ -1684,8 +1674,6 @@ 4BC57CD424342E0600FBC404 /* MachineTypes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MachineTypes.hpp; sourceTree = ""; }; 4BC57CD72436A61300FBC404 /* State.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = State.hpp; sourceTree = ""; }; 4BC57CD82436A62900FBC404 /* State.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = State.cpp; sourceTree = ""; }; - 4BC57CE02436BFE000FBC404 /* OPL2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OPL2.cpp; sourceTree = ""; }; - 4BC57CE12436BFE000FBC404 /* OPL2.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OPL2.hpp; sourceTree = ""; }; 4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000MoveTests.mm; sourceTree = ""; }; 4BC5FC2F20CDDDEE00410AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/AppleIIOptions.xib"; sourceTree = SOURCE_ROOT; }; 4BC751B11D157E61006C31D9 /* 6522Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6522Tests.swift; sourceTree = ""; }; @@ -3529,10 +3517,6 @@ 4BC0CB2F2447EC7C00A79DBB /* Implementation */ = { isa = PBXGroup; children = ( - 4BC0CB302447EC7C00A79DBB /* Operator.cpp */, - 4BC0CB312447EC7C00A79DBB /* Operator.hpp */, - 4BC0CB352447EC9A00A79DBB /* Channel.cpp */, - 4BC0CB362447EC9A00A79DBB /* Channel.hpp */, 4BC0CB3A2447ECAE00A79DBB /* Tables.hpp */, 4B61908F24526E640013F202 /* LowFrequencyOscillator.hpp */, 4B619092245BC1000013F202 /* PhaseGenerator.hpp */, @@ -3576,8 +3560,6 @@ isa = PBXGroup; children = ( 4BC0CB2F2447EC7C00A79DBB /* Implementation */, - 4BC57CE02436BFE000FBC404 /* OPL2.cpp */, - 4BC57CE12436BFE000FBC404 /* OPL2.hpp */, 4B619096245FBEF80013F202 /* OPLBase.hpp */, 4B619097245FBF7B0013F202 /* OPLL.cpp */, 4B619098245FBF7B0013F202 /* OPLL.hpp */, @@ -4387,7 +4369,6 @@ 4B894529201967B4007DE474 /* Disk.cpp in Sources */, 4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */, 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */, - 4BC0CB392447EC9A00A79DBB /* Channel.cpp in Sources */, 4BB0A65E204500A900FB3688 /* StaticAnalyser.cpp in Sources */, 4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */, 4B65086122F4CFE0009C1100 /* Keyboard.cpp in Sources */, @@ -4490,7 +4471,6 @@ 4B0ACC2923775819008902D0 /* DMAController.cpp in Sources */, 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */, 4B055ACE1FAE9B030060FFFF /* Plus3.cpp in Sources */, - 4BC0CB342447EC7D00A79DBB /* Operator.cpp in Sources */, 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */, 4BAD13441FF709C700FD114A /* MSX.cpp in Sources */, 4B055AC41FAE9AE80060FFFF /* Keyboard.cpp in Sources */, @@ -4567,7 +4547,6 @@ 4B89451E201967B4007DE474 /* Tape.cpp in Sources */, 4BAF2B4E2004580C00480230 /* DMK.cpp in Sources */, 4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */, - 4BC0CB322447EC7D00A79DBB /* Operator.cpp in Sources */, 4B0ACC3023775819008902D0 /* TIASound.cpp in Sources */, 4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */, 4B0E04EA1FC9E5DA00F43484 /* CAS.cpp in Sources */, @@ -4726,7 +4705,6 @@ 4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */, 4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */, 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */, - 4BC0CB372447EC9A00A79DBB /* Channel.cpp in Sources */, 4B894524201967B4007DE474 /* Tape.cpp in Sources */, 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */, 4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */, @@ -4795,7 +4773,6 @@ 4B778F4A23A5F1FB0000D260 /* StaticAnalyser.cpp in Sources */, 4BD91D772401C2B8007BDC91 /* PatrikRakTests.swift in Sources */, 4B680CE223A5553100451D43 /* 68000ComparativeTests.mm in Sources */, - 4BC0CB332447EC7D00A79DBB /* Operator.cpp in Sources */, 4B778F3723A5F11C0000D260 /* Parser.cpp in Sources */, 4B778F4523A5F1CD0000D260 /* SegmentParser.cpp in Sources */, 4B90467422C6FADD000E2074 /* 68000BitwiseTests.mm in Sources */, @@ -4883,7 +4860,6 @@ 4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */, 4B778F1223A5EC720000D260 /* CRT.cpp in Sources */, 4B778EF423A5DB3A0000D260 /* C1540.cpp in Sources */, - 4BC0CB382447EC9A00A79DBB /* Channel.cpp in Sources */, 4B778F3C23A5F16F0000D260 /* FIRFilter.cpp in Sources */, 4B778F5423A5F2600000D260 /* UnformattedTrack.cpp in Sources */, 4B778EF823A5EB6E0000D260 /* NIB.cpp in Sources */,