2010-08-09 13:28:56 +00:00
|
|
|
#ifdef DSP_CPP
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void DSP::envelope_run(voice_t& v) {
|
2010-08-09 13:28:56 +00:00
|
|
|
int env = v.env;
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
if(v.env_mode == env_release) { //60%
|
2010-08-09 13:28:56 +00:00
|
|
|
env -= 0x8;
|
|
|
|
if(env < 0) env = 0;
|
|
|
|
v.env = env;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rate;
|
|
|
|
int env_data = VREG(adsr1);
|
2013-05-05 09:21:30 +00:00
|
|
|
if(state.t_adsr0 & 0x80) { //99% ADSR
|
|
|
|
if(v.env_mode >= env_decay) { //99%
|
2010-08-09 13:28:56 +00:00
|
|
|
env--;
|
|
|
|
env -= env >> 8;
|
|
|
|
rate = env_data & 0x1f;
|
2013-05-05 09:21:30 +00:00
|
|
|
if(v.env_mode == env_decay) { //1%
|
2010-08-09 13:28:56 +00:00
|
|
|
rate = ((state.t_adsr0 >> 3) & 0x0e) + 0x10;
|
|
|
|
}
|
2013-05-05 09:21:30 +00:00
|
|
|
} else { //env_attack
|
2010-08-09 13:28:56 +00:00
|
|
|
rate = ((state.t_adsr0 & 0x0f) << 1) + 1;
|
|
|
|
env += rate < 31 ? 0x20 : 0x400;
|
|
|
|
}
|
2013-05-05 09:21:30 +00:00
|
|
|
} else { //GAIN
|
2010-08-09 13:28:56 +00:00
|
|
|
env_data = VREG(gain);
|
|
|
|
int mode = env_data >> 5;
|
2013-05-05 09:21:30 +00:00
|
|
|
if(mode < 4) { //direct
|
2010-08-09 13:28:56 +00:00
|
|
|
env = env_data << 4;
|
|
|
|
rate = 31;
|
|
|
|
} else {
|
|
|
|
rate = env_data & 0x1f;
|
2013-05-05 09:21:30 +00:00
|
|
|
if(mode == 4) { //4: linear decrease
|
2010-08-09 13:28:56 +00:00
|
|
|
env -= 0x20;
|
2013-05-05 09:21:30 +00:00
|
|
|
} else if(mode < 6) { //5: exponential decrease
|
2010-08-09 13:28:56 +00:00
|
|
|
env--;
|
|
|
|
env -= env >> 8;
|
2013-05-05 09:21:30 +00:00
|
|
|
} else { //6, 7: linear increase
|
2010-08-09 13:28:56 +00:00
|
|
|
env += 0x20;
|
|
|
|
if(mode > 6 && (unsigned)v.hidden_env >= 0x600) {
|
2013-05-05 09:21:30 +00:00
|
|
|
env += 0x8 - 0x20; //7: two-slope linear increase
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//sustain level
|
|
|
|
if((env >> 8) == (env_data >> 5) && v.env_mode == env_decay) v.env_mode = env_sustain;
|
|
|
|
v.hidden_env = env;
|
|
|
|
|
|
|
|
//unsigned cast because linear decrease underflowing also triggers this
|
|
|
|
if((unsigned)env > 0x7ff) {
|
|
|
|
env = (env < 0 ? 0 : 0x7ff);
|
|
|
|
if(v.env_mode == env_attack) v.env_mode = env_decay;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(counter_poll(rate) == true) v.env = env;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|