mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-30 04:50:08 +00:00
Attempts to implement decay and release the right way around and with full precision.
Higher numbers = decay/release more quickly, not more slowly.
This commit is contained in:
parent
95c6b9b55d
commit
e51e2425cc
@ -29,6 +29,8 @@ namespace OPL {
|
|||||||
This code considers application of tremolo to be a function of the envelope generator;
|
This code considers application of tremolo to be a function of the envelope generator;
|
||||||
this is largely for logical conformity with the phase generator that necessarily has to
|
this is largely for logical conformity with the phase generator that necessarily has to
|
||||||
apply vibrato.
|
apply vibrato.
|
||||||
|
|
||||||
|
TODO: use envelope_precision.
|
||||||
*/
|
*/
|
||||||
template <int envelope_precision, int period_precision> class EnvelopeGenerator {
|
template <int envelope_precision, int period_precision> class EnvelopeGenerator {
|
||||||
public:
|
public:
|
||||||
@ -43,7 +45,7 @@ template <int envelope_precision, int period_precision> class EnvelopeGenerator
|
|||||||
const int key_scaling_rate = key_scale_rate_ >> key_scale_rate_shift_;
|
const int key_scaling_rate = key_scale_rate_ >> key_scale_rate_shift_;
|
||||||
switch(phase_) {
|
switch(phase_) {
|
||||||
case Phase::Damp:
|
case Phase::Damp:
|
||||||
update_decay(oscillator, 12);
|
update_decay(oscillator, 12 << 2);
|
||||||
if(attenuation_ == 511) {
|
if(attenuation_ == 511) {
|
||||||
(*will_attack_)();
|
(*will_attack_)();
|
||||||
phase_ = Phase::Attack;
|
phase_ = Phase::Attack;
|
||||||
@ -203,6 +205,13 @@ template <int envelope_precision, int period_precision> class EnvelopeGenerator
|
|||||||
int sustain_level_ = 0;
|
int sustain_level_ = 0;
|
||||||
bool use_sustain_level_ = false;
|
bool use_sustain_level_ = false;
|
||||||
|
|
||||||
|
static constexpr int dithering_patterns[4][8] = {
|
||||||
|
{0, 1, 0, 1, 0, 1, 0, 1},
|
||||||
|
{0, 1, 0, 1, 1, 1, 0, 1},
|
||||||
|
{0, 1, 1, 1, 0, 1, 1, 1},
|
||||||
|
{0, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
};
|
||||||
|
|
||||||
void update_attack(const LowFrequencyOscillator &oscillator, int rate) {
|
void update_attack(const LowFrequencyOscillator &oscillator, int rate) {
|
||||||
// Rules:
|
// Rules:
|
||||||
//
|
//
|
||||||
@ -221,36 +230,23 @@ template <int envelope_precision, int period_precision> class EnvelopeGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_decay(const LowFrequencyOscillator &oscillator, int rate) {
|
void update_decay(const LowFrequencyOscillator &oscillator, int rate) {
|
||||||
// Rules:
|
// Special case: no decay.
|
||||||
//
|
if(rate < 4) {
|
||||||
// (relative to a 511 scale)
|
return;
|
||||||
//
|
|
||||||
// A rate of 0 is no decay at all.
|
|
||||||
// A rate of 1 means increase 4 per cycle.
|
|
||||||
// A rate of 2 means increase 2 per cycle.
|
|
||||||
// A rate of 3 means increase 1 per cycle.
|
|
||||||
// A rate of 4 means increase 1 every other cycle.
|
|
||||||
// A rate of 5 means increase once every fourth cycle.
|
|
||||||
// etc.
|
|
||||||
// eighth, sixteenth, 32nd, 64th, 128th, 256th, 512th, 1024th, 2048th, 4096th, 8192th
|
|
||||||
|
|
||||||
if(rate) {
|
|
||||||
// TODO: don't throw away low two bits of the rate.
|
|
||||||
switch(rate >> 2) {
|
|
||||||
case 1: attenuation_ += 32; break;
|
|
||||||
case 2: attenuation_ += 16; break;
|
|
||||||
default: {
|
|
||||||
const int sample_length = 1 << ((rate >> 2) - 4);
|
|
||||||
if(!(oscillator.counter & (sample_length - 1))) {
|
|
||||||
attenuation_ += 8;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp to the proper range.
|
// Work out the number of cycles between each adjustment tick, and stop now
|
||||||
|
// if not at the next adjustment boundary.
|
||||||
|
const int shift_size = 13 - (std::min(rate, 52) >> 2);
|
||||||
|
if(oscillator.counter & ((1 << shift_size) - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply dithered adjustment and clamp.
|
||||||
|
const int rate_shift = 1 + (rate > 59) + (rate > 55);
|
||||||
|
attenuation_ += dithering_patterns[rate & 3][(oscillator.counter >> shift_size) & 7] * (4 << rate_shift);
|
||||||
attenuation_ = std::min(attenuation_, 511);
|
attenuation_ = std::min(attenuation_, 511);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user