proper envelope, phase reset macro, prepare for ad-hoc ADSR params change via macros

This commit is contained in:
LTVA1 2024-08-04 21:28:09 +03:00
parent 986b64bbf0
commit 2e321b66c2
3 changed files with 141 additions and 108 deletions

View file

@ -211,6 +211,16 @@ void DivPlatformSID3::tick(bool sysTick)
panChanged = true;
chan[i].panRight = chan[i].std.panR.val & 0xff;
}
if (chan[i].std.phaseReset.had) {
chan[i].phaseReset = chan[i].std.phaseReset.val & 1;
if(chan[i].phaseReset)
{
updateFlags(i, chan[i].gate);
}
chan[i].phaseReset = false;
}
if(panChanged)
{
@ -242,10 +252,12 @@ void DivPlatformSID3::tick(bool sysTick)
updateFlags(i, false); //gate off TODO: make it properly?
updateFlags(i, true); //gate on
chan[i].gate = true;
}
if (chan[i].keyOff)
{
updateFlags(i, false); //gate off
chan[i].gate = false;
}
if (chan[i].freq<0) chan[i].freq=0;

View file

@ -10,10 +10,12 @@ enum State { ATTACK, DECAY, SUSTAIN, RELEASE }; //for envelope
# define M_PI 3.14159265358979323846
#endif
#define envspd_factor 10
#define envspd_factor_a_sr 10
#define envspd_factor_dr 15
#define envspd_adr(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * envspd_factor)) * (rate == 0 ? 1 : (rate * envspd_factor))))
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0xff0000 / ((256 - rate) * (256 - rate) * envspd_factor * envspd_factor)))
#define envspd_a(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * envspd_factor_a_sr)) * (rate == 0 ? 1 : (rate * envspd_factor_a_sr))))
#define envspd_dr(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * envspd_factor_dr)) * (rate == 0 ? 1 : (rate * envspd_factor_dr))))
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0xff0000 / ((256 - rate) * (256 - rate) * envspd_factor_a_sr * envspd_factor_a_sr)))
//these 4 ones are util only
double square(double x) {
@ -2260,6 +2262,16 @@ uint16_t sid3_special_wave(SID3* sid3, uint32_t acc, uint8_t wave)
return sid3->special_waves[wave][acc >> (SID3_ACC_BITS - 14)];
}
#define fill_gap(i, how_far) \
if(i > (how_far - 1)) \
{ \
if(sid3->exponential_output_to_envelope_counter[(i) - (how_far)] != 0) \
{ \
sid3->exponential_output_to_envelope_counter[(i)] = sid3->exponential_output_to_envelope_counter[i - (how_far)]; \
goto next; \
} \
}
SID3* sid3_create()
{
SID3* sid3 = (SID3*)malloc(sizeof(SID3));
@ -2294,6 +2306,39 @@ SID3* sid3_create()
sid3->special_waves[SID3_NUM_UNIQUE_SPECIAL_WAVES * 2 + 1][j] = clipped + 0x7fff;
}
double min_val = exp(-2.0);
double max_val = exp(2.0);
double scale_factor = (double)0xffff / (max_val - min_val);
for(uint32_t i = 0; i < SID3_EXPONENTIAL_LUT_LENGTH; i++)
{
sid3->env_counter_to_exponential_output[i] = (exp(-2.0 + (double)i * 4.0 / (double)SID3_EXPONENTIAL_LUT_LENGTH) - min_val) * scale_factor;
}
for(uint32_t i = 0; i < SID3_EXPONENTIAL_LUT_LENGTH; i++)
{
sid3->exponential_output_to_envelope_counter[(uint64_t)sid3->env_counter_to_exponential_output[i] * (uint64_t)SID3_EXPONENTIAL_LUT_LENGTH / (uint64_t)0xffff] = i << 8;
}
for(uint32_t i = 0; i < SID3_EXPONENTIAL_LUT_LENGTH; i++) //fill the gaps...
{
if(sid3->exponential_output_to_envelope_counter[i] > 0xff0000)
{
sid3->exponential_output_to_envelope_counter[i] = 0xff0000;
}
if(sid3->exponential_output_to_envelope_counter[i] == 0)
{
fill_gap(i, 1)
fill_gap(i, 2)
fill_gap(i, 3)
fill_gap(i, 4)
fill_gap(i, 5)
fill_gap(i, 6)
}
next:;
}
return sid3;
}
@ -2319,48 +2364,7 @@ void sid3_reset(SID3* sid3)
//TODO: wavetable chan
}
void sid3_do_release_rate_period(sid3_channel_adsr* adsr)
{
uint32_t counter = adsr->envelope_counter >> 15;
if(counter >= 0xff)
{
adsr->rate_period = 1;
return;
}
if(counter >= 0x5d)
{
adsr->rate_period = 2;
return;
}
if(counter >= 0x36)
{
adsr->rate_period = 4;
return;
}
if(counter >= 0x1a)
{
adsr->rate_period = 8;
return;
}
if(counter >= 0x0e)
{
adsr->rate_period = 16;
return;
}
if(counter >= 0x06)
{
adsr->rate_period = 32;
return;
}
if(counter >= 0x02)
{
adsr->rate_period = 64;
return;
}
}
void sid3_gate_bit(uint8_t gate, sid3_channel_adsr* adsr)
void sid3_gate_bit(SID3* sid3, uint8_t gate, sid3_channel_adsr* adsr)
{
// The rate counter is never reset, thus there will be a delay before the
// envelope counter starts counting up (attack) or down (release).
@ -2368,48 +2372,35 @@ void sid3_gate_bit(uint8_t gate, sid3_channel_adsr* adsr)
// Gate bit on: Start attack, decay, sustain.
if (gate)
{
if(adsr->state != ATTACK)
{
adsr->envelope_counter = (uint32_t)sid3->env_counter_to_exponential_output[adsr->envelope_counter >> 8] << 8;
}
adsr->state = ATTACK;
adsr->envelope_speed = envspd_adr(adsr->a); //todo: make it properly
adsr->envelope_speed = envspd_a(adsr->a); //todo: make it properly
//adsr->envelope_counter = 0;
// Switching to attack state unlocks the zero freeze.
adsr->hold_zero = false;
adsr->rate_counter = 0;
adsr->rate_period = 1;
}
// Gate bit off: Start release.
else
{
if(adsr->state == ATTACK && !adsr->hold_zero)
{
adsr->envelope_counter = sid3->exponential_output_to_envelope_counter[adsr->envelope_counter >> 8];
}
adsr->state = RELEASE;
adsr->envelope_speed = envspd_adr(adsr->r); //todo: make it properly
adsr->rate_counter = 0;
//adsr->rate_period = 1;
sid3_do_release_rate_period(adsr);
adsr->envelope_speed = envspd_dr(adsr->r); //todo: make it properly
}
if(adsr->envelope_counter > 0xff0000) adsr->envelope_counter = 0xff0000;
}
void sid3_adsr_clock(sid3_channel_adsr* adsr)
{
if(adsr->rate_counter < adsr->rate_period)
{
adsr->rate_counter++;
}
if(adsr->rate_counter > adsr->rate_period)
{
adsr->rate_counter = adsr->rate_period; //so you can do alternating writes (e.g. writing attack 10-11-10-11-... results in the somewhat average envelope speed)
}
if (adsr->rate_counter != adsr->rate_period)
{
return;
}
adsr->rate_counter = 0;
// Check whether the envelope counter is frozen at zero.
if (adsr->hold_zero)
{
@ -2425,7 +2416,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
if (adsr->envelope_counter >= 0xff0000)
{
adsr->state = DECAY;
adsr->envelope_speed = envspd_adr(adsr->d);
adsr->envelope_speed = envspd_dr(adsr->d);
}
return; //do not do exponential approximation of attack
@ -2435,7 +2426,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
{
adsr->envelope_counter -= adsr->envelope_speed;
if(adsr->envelope_counter > 0xff0f00) adsr->envelope_counter = 0xff0000;
if(adsr->envelope_counter > 0xff0000) adsr->envelope_counter = 0xff0000;
if(adsr->envelope_counter <= ((uint32_t)adsr->s << 16))
{
@ -2456,7 +2447,9 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
{
adsr->envelope_counter -= adsr->envelope_speed;
if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0xfff0000)
if(adsr->envelope_counter > 0xff0000) adsr->envelope_counter = 0xff0000;
if(adsr->envelope_counter <= adsr->envelope_speed)
{
adsr->envelope_counter = 0;
adsr->hold_zero = true;
@ -2464,37 +2457,20 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
}
break;
}
// Check for change of exponential counter period.
switch (adsr->envelope_counter >> 16)
{
case 0xff:
adsr->rate_period = 1;
break;
case 0x5d:
adsr->rate_period = 2;
break;
case 0x36:
adsr->rate_period = 4;
break;
case 0x1a:
adsr->rate_period = 8;
break;
case 0x0e:
adsr->rate_period = 16;
break;
case 0x06:
adsr->rate_period = 32;
break;
case 0x02:
adsr->rate_period = 64;
break;
}
}
int32_t sid3_adsr_output(sid3_channel_adsr* adsr, int32_t input)
int32_t sid3_adsr_output(SID3* sid3, sid3_channel_adsr* adsr, int32_t input)
{
return (int32_t)((int64_t)input * (int64_t)adsr->envelope_counter / (int64_t)0xff0000 * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL);
if(adsr->hold_zero) return 0;
if(adsr->state == ATTACK)
{
return (int32_t)((int64_t)input * (int64_t)adsr->envelope_counter / (int64_t)0xff0000 * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL);
}
else
{
return (int32_t)((int64_t)input * (int64_t)sid3->env_counter_to_exponential_output[adsr->envelope_counter >> 8] / (int64_t)0xffff * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL);
}
}
void sid3_set_filter_settings(sid3_filter* filt)
@ -2956,7 +2932,7 @@ void sid3_clock(SID3* sid3)
sid3_adsr_clock(&ch->adsr);
ch->output_before_filter = sid3_adsr_output(&ch->adsr, waveform);
ch->output_before_filter = sid3_adsr_output(sid3, &ch->adsr, waveform);
int32_t output = 0;
@ -3001,8 +2977,28 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if((prev_flags & SID3_CHAN_ENABLE_GATE) != (sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE))
{
sid3_gate_bit(sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE, &sid3->chan[channel].adsr);
sid3_gate_bit(sid3, sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE, &sid3->chan[channel].adsr);
}
if(sid3->chan[channel].flags & SID3_CHAN_ENV_RESET)
{
sid3->chan[channel].adsr.envelope_counter = 0;
sid3->chan[channel].adsr.state = ATTACK;
sid3->chan[channel].adsr.envelope_speed = envspd_a(sid3->chan[channel].adsr.a);
}
if(sid3->chan[channel].flags & SID3_CHAN_PHASE_RESET)
{
sid3->chan[channel].accumulator = 0;
}
if(sid3->chan[channel].flags & SID3_CHAN_NOISE_PHASE_RESET)
{
sid3->chan[channel].noise_accumulator = 0;
sid3->chan[channel].lfsr = 0x1;
}
sid3->chan[channel].flags &= ~(SID3_CHAN_ENV_RESET | SID3_CHAN_NOISE_PHASE_RESET | SID3_CHAN_PHASE_RESET);
}
else
{
@ -3011,8 +3007,10 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if((prev_flags & SID3_CHAN_ENABLE_GATE) != (sid3->wave_chan.flags & SID3_CHAN_ENABLE_GATE))
{
sid3_gate_bit(sid3->wave_chan.flags & SID3_CHAN_ENABLE_GATE, &sid3->wave_chan.adsr);
sid3_gate_bit(sid3, sid3->wave_chan.flags & SID3_CHAN_ENABLE_GATE, &sid3->wave_chan.adsr);
}
sid3->wave_chan.flags &= ~(SID3_CHAN_ENV_RESET | SID3_CHAN_NOISE_PHASE_RESET | SID3_CHAN_PHASE_RESET);
}
break;
}
@ -3021,10 +3019,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].adsr.a = data;
if(sid3->chan[channel].adsr.state == ATTACK) sid3->chan[channel].adsr.envelope_speed = envspd_a(sid3->chan[channel].adsr.a);
}
else
{
sid3->wave_chan.adsr.a = data;
if(sid3->wave_chan.adsr.state == ATTACK) sid3->wave_chan.adsr.envelope_speed = envspd_a(sid3->wave_chan.adsr.a);
}
break;
}
@ -3033,10 +3035,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].adsr.d = data;
if(sid3->chan[channel].adsr.state == DECAY) sid3->chan[channel].adsr.envelope_speed = envspd_dr(sid3->chan[channel].adsr.d);
}
else
{
sid3->wave_chan.adsr.d = data;
if(sid3->wave_chan.adsr.state == DECAY) sid3->wave_chan.adsr.envelope_speed = envspd_dr(sid3->wave_chan.adsr.d);
}
break;
}
@ -3045,10 +3051,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].adsr.s = data;
if(sid3->chan[channel].adsr.state == SUSTAIN) sid3->chan[channel].adsr.envelope_counter = sid3->chan[channel].adsr.s << 16;
}
else
{
sid3->wave_chan.adsr.s = data;
if(sid3->wave_chan.adsr.state == SUSTAIN) sid3->wave_chan.adsr.envelope_counter = sid3->wave_chan.adsr.s << 16;
}
break;
}
@ -3057,10 +3067,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].adsr.sr = data;
if(sid3->chan[channel].adsr.state == SUSTAIN) sid3->chan[channel].adsr.envelope_speed = envspd_sr(sid3->chan[channel].adsr.sr);
}
else
{
sid3->wave_chan.adsr.sr = data;
if(sid3->wave_chan.adsr.state == SUSTAIN) sid3->wave_chan.adsr.envelope_speed = envspd_sr(sid3->wave_chan.adsr.sr);
}
break;
}
@ -3069,10 +3083,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].adsr.r = data;
if(sid3->chan[channel].adsr.state == RELEASE) sid3->chan[channel].adsr.envelope_speed = envspd_dr(sid3->chan[channel].adsr.r);
}
else
{
sid3->wave_chan.adsr.r = data;
if(sid3->wave_chan.adsr.state == RELEASE) sid3->wave_chan.adsr.envelope_speed = envspd_dr(sid3->wave_chan.adsr.r);
}
break;
}

View file

@ -25,6 +25,8 @@ extern "C" {
#define SID3_NUM_SPECIAL_WAVES (SID3_NUM_UNIQUE_SPECIAL_WAVES * 2 + 2) /* usual and 2x vol clipped + 2x vol clipped tri and saw... */
#define SID3_SPECIAL_WAVE_LENGTH 16384
#define SID3_EXPONENTIAL_LUT_LENGTH ((0xff0000 >> 8) + 1)
#define SID3_ACC_BITS 30
#define SID3_ACC_MASK ((1UL << SID3_ACC_BITS) - 1)
@ -147,8 +149,6 @@ typedef struct
{
uint8_t a, d, s, sr, r, vol, state;
uint32_t rate_counter;
uint32_t rate_period;
uint32_t envelope_counter;
uint32_t envelope_speed;
bool hold_zero;
@ -222,6 +222,9 @@ typedef struct
{
uint16_t special_waves[SID3_NUM_SPECIAL_WAVES][SID3_SPECIAL_WAVE_LENGTH]; //sine wave and OPL3-ish waves + OPZ and YMF825 waves!
uint16_t env_counter_to_exponential_output[SID3_EXPONENTIAL_LUT_LENGTH];
uint32_t exponential_output_to_envelope_counter[SID3_EXPONENTIAL_LUT_LENGTH];
sid3_channel chan[SID3_NUM_CHANNELS - 1];
sid3_wavetable_chan wave_chan;