1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +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;
}
/*!
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,
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());
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);
carrier += envelope_generators_[channel].attenuation() + (channels_[channel].attenuation << 7) + key_level_scalers_[channel].attenuation();
return carrier.level();

View File

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