1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Implements feedback.

This commit is contained in:
Thomas Harte 2020-05-08 21:05:23 -04:00
parent 303965fbb8
commit 668f4b77f3
3 changed files with 14 additions and 0 deletions

View File

@ -58,6 +58,15 @@ template <int precision> class PhaseGenerator {
return phase_ >> 1; return phase_ >> 1;
} }
/*!
Applies feedback based on two historic samples of a total output level,
plus the degree of feedback to apply
*/
void apply_feedback(LogSign first, LogSign second, int level) {
constexpr int masks[] = {0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
phase_ += ((second.level(precision) + first.level(precision)) >> (8 - level)) & masks[level];
}
/*! /*!
Sets the multiple for this phase generator, in the same terms as an OPL programmer, Sets the multiple for this phase generator, in the same terms as an OPL programmer,
i.e. a 4-bit number that is used as a lookup into the internal multiples table. i.e. a 4-bit number that is used as a lookup into the internal multiples table.

View File

@ -377,6 +377,10 @@ int OPLL::melodic_output(int channel) {
auto modulation = WaveformGenerator<period_precision>::wave(channels_[channel].modulator_waveform, phase_generators_[channel + 9].phase()); auto modulation = WaveformGenerator<period_precision>::wave(channels_[channel].modulator_waveform, phase_generators_[channel + 9].phase());
modulation += envelope_generators_[channel + 9].attenuation() + (channels_[channel].modulator_attenuation << 5) + key_level_scalers_[channel + 9].attenuation(); modulation += envelope_generators_[channel + 9].attenuation() + (channels_[channel].modulator_attenuation << 5) + key_level_scalers_[channel + 9].attenuation();
// Apply feedback, if any.
phase_generators_[channel + 9].apply_feedback(channels_[channel].modulator_output, modulation, channels_[channel].modulator_feedback);
channels_[channel].modulator_output = modulation;
auto carrier = WaveformGenerator<period_precision>::wave(channels_[channel].carrier_waveform, phase_generators_[channel].scaled_phase(), modulation); auto carrier = WaveformGenerator<period_precision>::wave(channels_[channel].carrier_waveform, phase_generators_[channel].scaled_phase(), modulation);
carrier += envelope_generators_[channel].attenuation() + (channels_[channel].attenuation << 7) + key_level_scalers_[channel].attenuation(); carrier += envelope_generators_[channel].attenuation() + (channels_[channel].attenuation << 7) + key_level_scalers_[channel].attenuation();
return carrier.level(); return carrier.level();

View File

@ -91,6 +91,7 @@ class OPLL: public OPLBase<OPLL> {
int carrier_key_rate_scale_multiplier = 0; int carrier_key_rate_scale_multiplier = 0;
int modulator_key_rate_scale_multiplier = 0; int modulator_key_rate_scale_multiplier = 0;
LogSign modulator_output;
int modulator_feedback = 0; int modulator_feedback = 0;
bool use_sustain = false; bool use_sustain = false;