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; panChanged = true;
chan[i].panRight = chan[i].std.panR.val & 0xff; 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) if(panChanged)
{ {
@ -242,10 +252,12 @@ void DivPlatformSID3::tick(bool sysTick)
updateFlags(i, false); //gate off TODO: make it properly? updateFlags(i, false); //gate off TODO: make it properly?
updateFlags(i, true); //gate on updateFlags(i, true); //gate on
chan[i].gate = true;
} }
if (chan[i].keyOff) if (chan[i].keyOff)
{ {
updateFlags(i, false); //gate off updateFlags(i, false); //gate off
chan[i].gate = false;
} }
if (chan[i].freq<0) chan[i].freq=0; 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 # define M_PI 3.14159265358979323846
#endif #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_a(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * envspd_factor_a_sr)) * (rate == 0 ? 1 : (rate * envspd_factor_a_sr))))
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0xff0000 / ((256 - rate) * (256 - rate) * envspd_factor * envspd_factor))) #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 //these 4 ones are util only
double square(double x) { 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)]; 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_create()
{ {
SID3* sid3 = (SID3*)malloc(sizeof(SID3)); 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; 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; return sid3;
} }
@ -2319,48 +2364,7 @@ void sid3_reset(SID3* sid3)
//TODO: wavetable chan //TODO: wavetable chan
} }
void sid3_do_release_rate_period(sid3_channel_adsr* adsr) void sid3_gate_bit(SID3* sid3, uint8_t gate, 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)
{ {
// The rate counter is never reset, thus there will be a delay before the // The rate counter is never reset, thus there will be a delay before the
// envelope counter starts counting up (attack) or down (release). // 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. // Gate bit on: Start attack, decay, sustain.
if (gate) 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->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; //adsr->envelope_counter = 0;
// Switching to attack state unlocks the zero freeze. // Switching to attack state unlocks the zero freeze.
adsr->hold_zero = false; adsr->hold_zero = false;
adsr->rate_counter = 0;
adsr->rate_period = 1;
} }
// Gate bit off: Start release. // Gate bit off: Start release.
else 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->state = RELEASE;
adsr->envelope_speed = envspd_adr(adsr->r); //todo: make it properly adsr->envelope_speed = envspd_dr(adsr->r); //todo: make it properly
adsr->rate_counter = 0;
//adsr->rate_period = 1;
sid3_do_release_rate_period(adsr);
} }
if(adsr->envelope_counter > 0xff0000) adsr->envelope_counter = 0xff0000;
} }
void sid3_adsr_clock(sid3_channel_adsr* adsr) 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. // Check whether the envelope counter is frozen at zero.
if (adsr->hold_zero) if (adsr->hold_zero)
{ {
@ -2425,7 +2416,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
if (adsr->envelope_counter >= 0xff0000) if (adsr->envelope_counter >= 0xff0000)
{ {
adsr->state = DECAY; 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 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; 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)) 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; 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->envelope_counter = 0;
adsr->hold_zero = true; adsr->hold_zero = true;
@ -2464,37 +2457,20 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
} }
break; 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) void sid3_set_filter_settings(sid3_filter* filt)
@ -2956,7 +2932,7 @@ void sid3_clock(SID3* sid3)
sid3_adsr_clock(&ch->adsr); 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; 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)) 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 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)) 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; break;
} }
@ -3021,10 +3019,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
sid3->chan[channel].adsr.a = data; 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 else
{ {
sid3->wave_chan.adsr.a = data; 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; break;
} }
@ -3033,10 +3035,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
sid3->chan[channel].adsr.d = data; 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 else
{ {
sid3->wave_chan.adsr.d = data; 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; break;
} }
@ -3045,10 +3051,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
sid3->chan[channel].adsr.s = data; 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 else
{ {
sid3->wave_chan.adsr.s = data; 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; break;
} }
@ -3057,10 +3067,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
sid3->chan[channel].adsr.sr = data; 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 else
{ {
sid3->wave_chan.adsr.sr = data; 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; break;
} }
@ -3069,10 +3083,14 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data)
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
sid3->chan[channel].adsr.r = data; 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 else
{ {
sid3->wave_chan.adsr.r = data; 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; 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_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_SPECIAL_WAVE_LENGTH 16384
#define SID3_EXPONENTIAL_LUT_LENGTH ((0xff0000 >> 8) + 1)
#define SID3_ACC_BITS 30 #define SID3_ACC_BITS 30
#define SID3_ACC_MASK ((1UL << SID3_ACC_BITS) - 1) #define SID3_ACC_MASK ((1UL << SID3_ACC_BITS) - 1)
@ -147,8 +149,6 @@ typedef struct
{ {
uint8_t a, d, s, sr, r, vol, state; uint8_t a, d, s, sr, r, vol, state;
uint32_t rate_counter;
uint32_t rate_period;
uint32_t envelope_counter; uint32_t envelope_counter;
uint32_t envelope_speed; uint32_t envelope_speed;
bool hold_zero; 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 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_channel chan[SID3_NUM_CHANNELS - 1];
sid3_wavetable_chan wave_chan; sid3_wavetable_chan wave_chan;