1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +00:00

Actually, octave probably works this way around? Higher octaves = higher frequencies.

This commit is contained in:
Thomas Harte 2020-04-14 21:39:12 -04:00
parent aa45142728
commit d805e9a8f0
2 changed files with 20 additions and 20 deletions

View File

@ -389,7 +389,7 @@ uint8_t OPL2::read(uint16_t address) {
// MARK: - Operators
void Operator::update(OperatorState &state, bool key_on, int channel_frequency, int channel_octave, OperatorOverrides *overrides) {
void Operator::update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorOverrides *overrides) {
// Per the documentation:
//
// Delta phase = ( [desired freq] * 2^19 / [input clock / 72] ) / 2 ^ (b - 1)
@ -403,9 +403,9 @@ void Operator::update(OperatorState &state, bool key_on, int channel_frequency,
};
// Update the raw phase.
const int octave_divider = 128 << channel_octave;
const int octave_divider = 2048 >> channel_octave;
state.divider_ %= octave_divider;
state.divider_ += multipliers[frequency_multiple] * channel_frequency;
state.divider_ += multipliers[frequency_multiple] * channel_period;
state.raw_phase_ += state.divider_ / octave_divider;
// Hence calculate phase (TODO: by also taking account of vibrato).
@ -512,7 +512,7 @@ void Operator::update(OperatorState &state, bool key_on, int channel_frequency,
// Combine the ADSR attenuation and overall channel attenuation, clamping to the permitted range.
if(overrides) {
state.attenuation = state.adsr_attenuation_ + (overrides->attenuation << 5);
state.attenuation = state.adsr_attenuation_ + (overrides->attenuation << 6);
} else {
state.attenuation = state.adsr_attenuation_ + (attenuation_ << 3);
}

View File

@ -67,8 +67,8 @@ struct OperatorOverrides {
* an attenuation for the output level; and
* a factor by which to speed up the ADSR envelope as a function of frequency.
Oscillator frequency isn't set directly, it's a multiple of the owning channel, in which
frequency is set as a combination of f-num and octave.
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:
@ -92,11 +92,11 @@ class Operator {
/// Sets this operator's waveform using the low two bits of @c value.
void set_waveform(uint8_t value) {
waveform = Operator::Waveform(value & 3);
// waveform = Operator::Waveform(value & 3);
}
/// 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 frequency multiplier.
/// uses the bottom nibble to set the period multiplier.
void set_am_vibrato_hold_sustain_ksr_multiple(uint8_t value) {
apply_amplitude_modulation = value & 0x80;
apply_vibrato = value & 0x40;
@ -105,7 +105,7 @@ class Operator {
frequency_multiple = value & 0xf;
}
void update(OperatorState &state, bool key_on, int channel_frequency, int channel_octave, OperatorOverrides *overrides = nullptr);
void update(OperatorState &state, bool key_on, int channel_period, int channel_octave, OperatorOverrides *overrides = nullptr);
bool is_audible(OperatorState &state, OperatorOverrides *overrides = nullptr) {
if(state.adsr_phase_ == OperatorState::ADSRPhase::Release) {
@ -168,13 +168,13 @@ class Channel {
public:
/// Sets the low 8 bits of frequency control.
void set_frequency_low(uint8_t value) {
frequency = (frequency &~0xff) | value;
period_ = (period_ &~0xff) | 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) {
frequency = (frequency & 0xff) | ((value & 3) << 8);
period_ = (period_ & 0xff) | ((value & 3) << 8);
octave = (value >> 2) & 0x7;
key_on = value & 0x20;
frequency_shift = 0;
@ -183,7 +183,7 @@ class Channel {
/// 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) {
frequency = (frequency & 0xff) | ((value & 1) << 8);
period_ = (period_ & 0xff) | ((value & 1) << 8);
octave = (value >> 1) & 0x7;
key_on = value & 0x10;;
frequency_shift = 1;
@ -199,16 +199,16 @@ class Channel {
/// This should be called at a rate of around 49,716 Hz; it returns the current output level
/// level for this channel.
int update(Operator *modulator, Operator *carrier, OperatorOverrides *modulator_overrides = nullptr, OperatorOverrides *carrier_overrides = nullptr) {
modulator->update(modulator_state_, key_on, frequency << frequency_shift, octave, modulator_overrides);
carrier->update(carrier_state_, key_on, frequency << frequency_shift, octave, carrier_overrides);
modulator->update(modulator_state_, key_on, period_ << frequency_shift, octave, modulator_overrides);
carrier->update(carrier_state_, key_on, period_ << frequency_shift, octave, carrier_overrides);
// TODO: almost everything else. This is a quick test.
// TODO: almost everything. This is a quick test.
// Specifically: use lookup tables.
const float carrier_volume = logf(float(carrier_state_.attenuation + 1)) / logf(1023.0);
const float modulator_volume = logf(float(modulator_state_.attenuation + 1)) / logf(1023.0);
const float modulator_output = 0.0f;//expf(logf(float(M_PI) * sinf(float(modulator_state_.phase) / 512.0f)) + (float(modulator_state_.attenuation) / 1023.0f));
const float carrier_phase = modulator_output + float(carrier_state_.phase) / 1024.0f;
const float carrier_output = expf(logf(sinf(float(M_PI) * 2.0f * carrier_phase)) + (float(carrier_state_.attenuation) / 1023.0f));
const float modulator_output = modulator_volume * sinf(float(modulator_state_.phase) / 1024.0f);
return int(carrier_volume * sinf(modulator_output + (float(carrier_state_.phase) / 1024.0f)) * 20000.0f);
return int(carrier_output * 20'000.0f);
}
/// @returns @c true if this channel is currently producing any audio; @c false otherwise;
@ -218,7 +218,7 @@ class Channel {
private:
/// 'F-Num' in the spec; this plus the current octave determines channel frequency.
int frequency = 0;
int period_ = 0;
/// Linked with the frequency, determines the channel frequency.
int octave = 0;