fix possible envelope volume clipping

This commit is contained in:
Michaël Banaan Ananas 2013-07-06 09:45:42 +00:00
parent 0c207640cf
commit cb1ad4e10a
2 changed files with 86 additions and 80 deletions

View File

@ -202,67 +202,6 @@ static const int pcm_tab[16] = { 0, 4, 8, -1, 12, 16, 20, -1, 24, 28, 32, -1, 36
/*****************************************************************************/ /*****************************************************************************/
INLINE int GET_KEYSCALED_RATE(int rate, int keycode, int keyscale)
{
int newrate = rate + RKS_Table[keycode][keyscale];
if (newrate > 63)
{
newrate = 63;
}
if (newrate < 0)
{
newrate = 0;
}
return newrate;
}
INLINE int GET_INTERNAL_KEYCODE(int block, int fns)
{
int n43;
if (fns < 0x780)
{
n43 = 0;
}
else if (fns < 0x900)
{
n43 = 1;
}
else if (fns < 0xa80)
{
n43 = 2;
}
else
{
n43 = 3;
}
return ((block & 7) * 4) + n43;
}
INLINE int GET_EXTERNAL_KEYCODE(int block, int fns)
{
int n43;
if (fns < 0x100)
{
n43 = 0;
}
else if (fns < 0x300)
{
n43 = 1;
}
else if (fns < 0x500)
{
n43 = 2;
}
else
{
n43 = 3;
}
return ((block & 7) * 4) + n43;
}
void ymf271_device::calculate_step(YMF271Slot *slot) void ymf271_device::calculate_step(YMF271Slot *slot)
{ {
double st; double st;
@ -295,6 +234,17 @@ void ymf271_device::calculate_step(YMF271Slot *slot)
} }
} }
inline bool ymf271_device::check_envelope_end(YMF271Slot *slot)
{
if (slot->volume <= 0)
{
slot->active = 0;
slot->volume = 0;
return true;
}
return false;
}
void ymf271_device::update_envelope(YMF271Slot *slot) void ymf271_device::update_envelope(YMF271Slot *slot)
{ {
switch (slot->env_state) switch (slot->env_state)
@ -316,7 +266,7 @@ void ymf271_device::update_envelope(YMF271Slot *slot)
int decay_level = 255 - (slot->decay1lvl << 4); int decay_level = 255 - (slot->decay1lvl << 4);
slot->volume -= slot->env_decay1_step; slot->volume -= slot->env_decay1_step;
if ((slot->volume >> ENV_VOLUME_SHIFT) <= decay_level) if (!check_envelope_end(slot) && (slot->volume >> ENV_VOLUME_SHIFT) <= decay_level)
{ {
slot->env_state = ENV_DECAY2; slot->env_state = ENV_DECAY2;
} }
@ -326,29 +276,80 @@ void ymf271_device::update_envelope(YMF271Slot *slot)
case ENV_DECAY2: case ENV_DECAY2:
{ {
slot->volume -= slot->env_decay2_step; slot->volume -= slot->env_decay2_step;
check_envelope_end(slot);
if (slot->volume <= 0)
{
slot->active = 0;
slot->volume = 0;
}
break; break;
} }
case ENV_RELEASE: case ENV_RELEASE:
{ {
slot->volume -= slot->env_release_step; slot->volume -= slot->env_release_step;
check_envelope_end(slot);
if (slot->volume <= 0)
{
slot->active = 0;
slot->volume = 0;
}
break; break;
} }
} }
} }
inline int ymf271_device::get_keyscaled_rate(int rate, int keycode, int keyscale)
{
int newrate = rate + RKS_Table[keycode][keyscale];
if (newrate > 63)
{
newrate = 63;
}
if (newrate < 0)
{
newrate = 0;
}
return newrate;
}
inline int ymf271_device::get_internal_keycode(int block, int fns)
{
int n43;
if (fns < 0x780)
{
n43 = 0;
}
else if (fns < 0x900)
{
n43 = 1;
}
else if (fns < 0xa80)
{
n43 = 2;
}
else
{
n43 = 3;
}
return ((block & 7) * 4) + n43;
}
inline int ymf271_device::get_external_keycode(int block, int fns)
{
int n43;
if (fns < 0x100)
{
n43 = 0;
}
else if (fns < 0x300)
{
n43 = 1;
}
else if (fns < 0x500)
{
n43 = 2;
}
else
{
n43 = 3;
}
return ((block & 7) * 4) + n43;
}
void ymf271_device::init_envelope(YMF271Slot *slot) void ymf271_device::init_envelope(YMF271Slot *slot)
{ {
int keycode, rate; int keycode, rate;
@ -356,28 +357,28 @@ void ymf271_device::init_envelope(YMF271Slot *slot)
if (slot->waveform != 7) if (slot->waveform != 7)
{ {
keycode = GET_INTERNAL_KEYCODE(slot->block, slot->fns); keycode = get_internal_keycode(slot->block, slot->fns);
} }
else else
{ {
keycode = GET_EXTERNAL_KEYCODE(slot->block, slot->fns & 0x7ff); keycode = get_external_keycode(slot->block, slot->fns & 0x7ff);
/* keycode = (keycode + slot->srcb * 4 + slot->srcnote) / 2; */ // not sure /* keycode = (keycode + slot->srcb * 4 + slot->srcnote) / 2; */ // not sure
} }
// init attack state // init attack state
rate = GET_KEYSCALED_RATE(slot->ar * 2, keycode, slot->keyscale); rate = get_keyscaled_rate(slot->ar * 2, keycode, slot->keyscale);
slot->env_attack_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_ar[rate]) * 65536.0); slot->env_attack_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_ar[rate]) * 65536.0);
// init decay1 state // init decay1 state
rate = GET_KEYSCALED_RATE(slot->decay1rate * 2, keycode, slot->keyscale); rate = get_keyscaled_rate(slot->decay1rate * 2, keycode, slot->keyscale);
slot->env_decay1_step = (rate < 4) ? 0 : (int)(((double)(255-decay_level) / m_lut_dc[rate]) * 65536.0); slot->env_decay1_step = (rate < 4) ? 0 : (int)(((double)(255-decay_level) / m_lut_dc[rate]) * 65536.0);
// init decay2 state // init decay2 state
rate = GET_KEYSCALED_RATE(slot->decay2rate * 2, keycode, slot->keyscale); rate = get_keyscaled_rate(slot->decay2rate * 2, keycode, slot->keyscale);
slot->env_decay2_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_dc[rate]) * 65536.0); slot->env_decay2_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_dc[rate]) * 65536.0);
// init release state // init release state
rate = GET_KEYSCALED_RATE(slot->relrate * 4, keycode, slot->keyscale); rate = get_keyscaled_rate(slot->relrate * 4, keycode, slot->keyscale);
slot->env_release_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_ar[rate]) * 65536.0); slot->env_release_step = (rate < 4) ? 0 : (int)(((double)(255-0) / m_lut_ar[rate]) * 65536.0);
slot->volume = (255-160) << ENV_VOLUME_SHIFT; // -60db slot->volume = (255-160) << ENV_VOLUME_SHIFT; // -60db

View File

@ -115,6 +115,11 @@ private:
void ymf271_write_timer(UINT8 address, UINT8 data); void ymf271_write_timer(UINT8 address, UINT8 data);
UINT8 ymf271_read_memory(UINT32 offset); UINT8 ymf271_read_memory(UINT32 offset);
inline int get_keyscaled_rate(int rate, int keycode, int keyscale);
inline int get_internal_keycode(int block, int fns);
inline int get_external_keycode(int block, int fns);
inline bool check_envelope_end(YMF271Slot *slot);
// lookup tables // lookup tables
INT16 *m_lut_waves[8]; INT16 *m_lut_waves[8];
double *m_lut_plfo[4][8]; double *m_lut_plfo[4][8];