1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-30 22:56:03 +00:00

Preserves fractional part of modulator phase.

This commit is contained in:
Thomas Harte 2020-04-20 23:35:37 -04:00
parent 32fd1897d0
commit 475d75c16a
4 changed files with 12 additions and 12 deletions

View File

@ -36,15 +36,13 @@ void Channel::set_feedback_mode(uint8_t value) {
int Channel::update(Operator *modulator, Operator *carrier, 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_, 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);
modulator->update(modulator_state_, key_on_, period_ << frequency_shift_, octave_, nullptr, modulator_overrides);
carrier->update(carrier_state_, key_on_, period_ << frequency_shift_, octave_, &modulator_state_, carrier_overrides);
return carrier_state_.level();
} else {
// 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);
modulator->update(modulator_state_, key_on_, period_ << frequency_shift_, octave_, nullptr, modulator_overrides);
carrier->update(carrier_state_, key_on_, period_ << frequency_shift_, octave_, nullptr, carrier_overrides);
return (modulator_state_.level() + carrier_state_.level());
}
}

View File

@ -54,7 +54,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, int phase_offset, OperatorOverrides *overrides) {
void Operator::update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorState *phase_offset, OperatorOverrides *overrides) {
// Per the documentation:
//
// Delta phase = ( [desired freq] * 2^19 / [input clock / 72] ) / 2 ^ (b - 1)
@ -77,7 +77,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) + phase_offset;
const int scaled_phase_offset = phase_offset ? power_two(phase_offset->attenuation, 11) : 0;
const int phase = (state.raw_phase_ + scaled_phase_offset) >> 11;
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.

View File

@ -83,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, int phase_offset, OperatorOverrides *overrides = nullptr);
void update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorState *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);

View File

@ -88,9 +88,10 @@ constexpr LogSign negative_log_sin(int x) {
}
/*!
Computes the linear value represented by the log-sign @c ls.
Computes the linear value represented by the log-sign @c ls, shifted left by @c fractional prior
to loss of precision.
*/
constexpr int power_two(LogSign ls) {
constexpr int power_two(LogSign ls, int fractional = 0) {
/// A derivative of the exponent table in a real OPL2; mapped_exp[x] = (source[c ^ 0xff] << 1) | 0x800.
///
/// The ahead-of-time transformation represents fixed work the OPL2 does when reading its table
@ -142,7 +143,7 @@ constexpr int power_two(LogSign ls) {
2088, 2082, 2076, 2070, 2064, 2060, 2054, 2048,
};
return (mapped_exp[ls.log & 0xff] >> (ls.log >> 8)) * ls.sign;
return ((mapped_exp[ls.log & 0xff] << fractional) >> (ls.log >> 8)) * ls.sign;
}
/*