mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Preserves fractional part of modulator phase.
This commit is contained in:
parent
32fd1897d0
commit
475d75c16a
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user