mirror of
https://github.com/holub/mame
synced 2025-10-04 08:28:39 +03:00
es5506.cpp : Correct algorithms, Allow signed shifting (#5837)
* es5506.cpp : Correct algorithms, Allow signed shifting * es5506.cpp : Fix envelope
This commit is contained in:
parent
a9d7e55ac2
commit
f9d0e395ba
@ -284,7 +284,7 @@ void es5506_device::device_start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compute the tables */
|
/* compute the tables */
|
||||||
compute_tables(VOLUME_BIT_ES5506, 4, 8, 11); // 4 bit exponent, 8 bit mantissa
|
compute_tables(VOLUME_BIT_ES5506, 4, 8); // 4 bit exponent, 8 bit mantissa
|
||||||
|
|
||||||
/* initialize the rest of the structure */
|
/* initialize the rest of the structure */
|
||||||
m_channels = channels;
|
m_channels = channels;
|
||||||
@ -301,8 +301,8 @@ void es5506_device::device_start()
|
|||||||
{
|
{
|
||||||
m_voice[j].index = j;
|
m_voice[j].index = j;
|
||||||
m_voice[j].control = CONTROL_STOPMASK;
|
m_voice[j].control = CONTROL_STOPMASK;
|
||||||
m_voice[j].lvol = 0xffff << m_volume_shift; // 16 bit volume
|
m_voice[j].lvol = get_shifted_volume(0xffff); // 16 bit volume
|
||||||
m_voice[j].rvol = 0xffff << m_volume_shift;
|
m_voice[j].rvol = get_shifted_volume(0xffff);
|
||||||
m_voice[j].exbank = 0;
|
m_voice[j].exbank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ void es5505_device::device_start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compute the tables */
|
/* compute the tables */
|
||||||
compute_tables(VOLUME_BIT_ES5505, 4, 4, 15); // 4 bit exponent, 4 bit mantissa
|
compute_tables(VOLUME_BIT_ES5505, 4, 4); // 4 bit exponent, 4 bit mantissa
|
||||||
|
|
||||||
/* initialize the rest of the structure */
|
/* initialize the rest of the structure */
|
||||||
m_channels = channels;
|
m_channels = channels;
|
||||||
@ -416,8 +416,8 @@ void es5505_device::device_start()
|
|||||||
{
|
{
|
||||||
m_voice[j].index = j;
|
m_voice[j].index = j;
|
||||||
m_voice[j].control = CONTROL_STOPMASK;
|
m_voice[j].control = CONTROL_STOPMASK;
|
||||||
m_voice[j].lvol = 0xff << m_volume_shift; // 8 bit volume
|
m_voice[j].lvol = get_shifted_volume(0xff); // 8 bit volume
|
||||||
m_voice[j].rvol = 0xff << m_volume_shift;
|
m_voice[j].rvol = get_shifted_volume(0xff);
|
||||||
m_voice[j].exbank = 0;
|
m_voice[j].exbank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +462,7 @@ void es550x_device::update_internal_irq_state()
|
|||||||
|
|
||||||
***********************************************************************************************/
|
***********************************************************************************************/
|
||||||
|
|
||||||
void es550x_device::compute_tables(u32 total_volume_bit, u32 exponent_bit, u32 mantissa_bit, u32 mantissa_shift)
|
void es550x_device::compute_tables(u32 total_volume_bit, u32 exponent_bit, u32 mantissa_bit)
|
||||||
{
|
{
|
||||||
/* allocate ulaw lookup table */
|
/* allocate ulaw lookup table */
|
||||||
m_ulaw_lookup = make_unique_clear<s16[]>(1 << ULAW_MAXBITS);
|
m_ulaw_lookup = make_unique_clear<s16[]>(1 << ULAW_MAXBITS);
|
||||||
@ -491,16 +491,21 @@ void es550x_device::compute_tables(u32 total_volume_bit, u32 exponent_bit, u32 m
|
|||||||
m_volume_lookup = make_unique_clear<u32[]>(volume_len);
|
m_volume_lookup = make_unique_clear<u32[]>(volume_len);
|
||||||
|
|
||||||
/* generate volume lookup table */
|
/* generate volume lookup table */
|
||||||
const u8 exponent_mask = (1 << exponent_bit) - 1;
|
const u32 exponent_shift = 1 << exponent_bit;
|
||||||
|
const u32 exponent_mask = exponent_shift - 1;
|
||||||
|
|
||||||
const u32 mantissa_len = (1 << mantissa_bit);
|
const u32 mantissa_len = (1 << mantissa_bit);
|
||||||
const u32 mantissa_mask = (mantissa_len - 1);
|
const u32 mantissa_mask = (mantissa_len - 1);
|
||||||
|
const u32 mantissa_shift = exponent_shift - mantissa_bit - 1;
|
||||||
|
|
||||||
for (int i = 0; i < volume_len; i++)
|
for (int i = 0; i < volume_len; i++)
|
||||||
{
|
{
|
||||||
const u8 exponent = (i >> mantissa_bit) & exponent_mask;
|
const u32 exponent = (i >> mantissa_bit) & exponent_mask;
|
||||||
const u32 mantissa = (i & mantissa_mask) | mantissa_len;
|
const u32 mantissa = (i & mantissa_mask) | mantissa_len;
|
||||||
|
|
||||||
m_volume_lookup[i] = (mantissa << mantissa_shift) >> ((mantissa_shift + mantissa_bit + 1) - exponent);
|
m_volume_lookup[i] = (mantissa << mantissa_shift) >> (exponent_shift - exponent);
|
||||||
}
|
}
|
||||||
|
m_volume_acc_shift = (16 + exponent_mask) - VOLUME_ACC_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
@ -511,8 +516,10 @@ void es550x_device::compute_tables(u32 total_volume_bit, u32 exponent_bit, u32 m
|
|||||||
|
|
||||||
void es550x_device::get_accum_mask(u32 address_integer, u32 address_frac)
|
void es550x_device::get_accum_mask(u32 address_integer, u32 address_frac)
|
||||||
{
|
{
|
||||||
m_accum_shift = ADDRESS_FRAC_BIT - address_frac;
|
m_address_acc_shift = ADDRESS_FRAC_BIT - address_frac;
|
||||||
m_accum_mask = (((((1 << address_integer) - 1) << address_frac) | ((1 << address_frac) - 1)) << m_accum_shift) | ((1 << m_accum_shift) - 1);
|
m_address_acc_mask = lshift_signed<u64, s8>(((((1 << address_integer) - 1) << address_frac) | ((1 << address_frac) - 1)), m_address_acc_shift);
|
||||||
|
if (m_address_acc_shift > 0)
|
||||||
|
m_address_acc_mask |= ((1 << m_address_acc_shift) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -522,11 +529,11 @@ void es550x_device::get_accum_mask(u32 address_integer, u32 address_frac)
|
|||||||
|
|
||||||
***********************************************************************************************/
|
***********************************************************************************************/
|
||||||
|
|
||||||
inline s32 es550x_device::interpolate(s32 sample1, s32 sample2, u32 accum)
|
inline s32 es550x_device::interpolate(s32 sample1, s32 sample2, u64 accum)
|
||||||
{
|
{
|
||||||
const u32 shifted = 1 << ADDRESS_FRAC_BIT;
|
const u32 shifted = 1 << ADDRESS_FRAC_BIT;
|
||||||
const u32 mask = shifted - 1;
|
const u32 mask = shifted - 1;
|
||||||
accum &= mask & m_accum_mask;
|
accum &= mask & m_address_acc_mask;
|
||||||
return (sample1 * (s32)(shifted - accum) +
|
return (sample1 * (s32)(shifted - accum) +
|
||||||
sample2 * (s32)(accum)) >> ADDRESS_FRAC_BIT;
|
sample2 * (s32)(accum)) >> ADDRESS_FRAC_BIT;
|
||||||
}
|
}
|
||||||
@ -625,23 +632,28 @@ inline void es550x_device::apply_filters(es550x_voice *voice, s32 &sample)
|
|||||||
|
|
||||||
inline void es5506_device::update_envelopes(es550x_voice *voice)
|
inline void es5506_device::update_envelopes(es550x_voice *voice)
|
||||||
{
|
{
|
||||||
|
const u32 volume_max = (1 << VOLUME_BIT_ES5506) - 1;
|
||||||
/* decrement the envelope counter */
|
/* decrement the envelope counter */
|
||||||
voice->ecount--;
|
voice->ecount--;
|
||||||
|
|
||||||
/* ramp left volume */
|
/* ramp left volume */
|
||||||
if (voice->lvramp)
|
if (voice->lvramp)
|
||||||
{
|
{
|
||||||
|
voice->lvol = get_shifted_volume_res(voice->lvol);
|
||||||
voice->lvol += (int8_t)voice->lvramp;
|
voice->lvol += (int8_t)voice->lvramp;
|
||||||
if ((s32)voice->lvol < 0) voice->lvol = 0;
|
if ((s32)voice->lvol < 0) voice->lvol = 0;
|
||||||
else if (voice->lvol > 0xffff) voice->lvol = 0xffff;
|
else if (voice->lvol > volume_max) voice->lvol = volume_max;
|
||||||
|
voice->lvol = get_shifted_volume(voice->lvol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ramp right volume */
|
/* ramp right volume */
|
||||||
if (voice->rvramp)
|
if (voice->rvramp)
|
||||||
{
|
{
|
||||||
|
voice->rvol = get_shifted_volume_res(voice->rvol);
|
||||||
voice->rvol += (int8_t)voice->rvramp;
|
voice->rvol += (int8_t)voice->rvramp;
|
||||||
if ((s32)voice->rvol < 0) voice->rvol = 0;
|
if ((s32)voice->rvol < 0) voice->rvol = 0;
|
||||||
else if (voice->rvol > 0xffff) voice->rvol = 0xffff;
|
else if (voice->rvol > volume_max) voice->rvol = volume_max;
|
||||||
|
voice->rvol = get_shifted_volume(voice->rvol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ramp k1 filter constant */
|
/* ramp k1 filter constant */
|
||||||
@ -679,7 +691,7 @@ inline void es5505_device::update_envelopes(es550x_voice *voice)
|
|||||||
|
|
||||||
***********************************************************************************************/
|
***********************************************************************************************/
|
||||||
|
|
||||||
inline void es5506_device::check_for_end_forward(es550x_voice *voice, u32 &accum)
|
inline void es5506_device::check_for_end_forward(es550x_voice *voice, u64 &accum)
|
||||||
{
|
{
|
||||||
/* are we past the end? */
|
/* are we past the end? */
|
||||||
if (accum > voice->end && !(voice->control & CONTROL_LEI))
|
if (accum > voice->end && !(voice->control & CONTROL_LEI))
|
||||||
@ -698,25 +710,25 @@ inline void es5506_device::check_for_end_forward(es550x_voice *voice, u32 &accum
|
|||||||
|
|
||||||
/* uni-directional looping */
|
/* uni-directional looping */
|
||||||
case CONTROL_LPE:
|
case CONTROL_LPE:
|
||||||
accum = (voice->start + (accum - voice->end)) & m_accum_mask;
|
accum = (voice->start + (accum - voice->end)) & m_address_acc_mask;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* trans-wave looping */
|
/* trans-wave looping */
|
||||||
case CONTROL_BLE:
|
case CONTROL_BLE:
|
||||||
accum = (voice->start + (accum - voice->end)) & m_accum_mask;
|
accum = (voice->start + (accum - voice->end)) & m_address_acc_mask;
|
||||||
voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;
|
voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* bi-directional looping */
|
/* bi-directional looping */
|
||||||
case CONTROL_LPE | CONTROL_BLE:
|
case CONTROL_LPE | CONTROL_BLE:
|
||||||
accum = (voice->end - (accum - voice->end)) & m_accum_mask;
|
accum = (voice->end - (accum - voice->end)) & m_address_acc_mask;
|
||||||
voice->control ^= CONTROL_DIR;
|
voice->control ^= CONTROL_DIR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void es5506_device::check_for_end_reverse(es550x_voice *voice, u32 &accum)
|
inline void es5506_device::check_for_end_reverse(es550x_voice *voice, u64 &accum)
|
||||||
{
|
{
|
||||||
/* are we past the end? */
|
/* are we past the end? */
|
||||||
if (accum < voice->start && !(voice->control & CONTROL_LEI))
|
if (accum < voice->start && !(voice->control & CONTROL_LEI))
|
||||||
@ -735,18 +747,18 @@ inline void es5506_device::check_for_end_reverse(es550x_voice *voice, u32 &accum
|
|||||||
|
|
||||||
/* uni-directional looping */
|
/* uni-directional looping */
|
||||||
case CONTROL_LPE:
|
case CONTROL_LPE:
|
||||||
accum = (voice->end - (voice->start - accum)) & m_accum_mask;
|
accum = (voice->end - (voice->start - accum)) & m_address_acc_mask;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* trans-wave looping */
|
/* trans-wave looping */
|
||||||
case CONTROL_BLE:
|
case CONTROL_BLE:
|
||||||
accum = (voice->end - (voice->start - accum)) & m_accum_mask;
|
accum = (voice->end - (voice->start - accum)) & m_address_acc_mask;
|
||||||
voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;
|
voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* bi-directional looping */
|
/* bi-directional looping */
|
||||||
case CONTROL_LPE | CONTROL_BLE:
|
case CONTROL_LPE | CONTROL_BLE:
|
||||||
accum = (voice->start + (voice->start - accum)) & m_accum_mask;
|
accum = (voice->start + (voice->start - accum)) & m_address_acc_mask;
|
||||||
voice->control ^= CONTROL_DIR;
|
voice->control ^= CONTROL_DIR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -754,7 +766,7 @@ inline void es5506_device::check_for_end_reverse(es550x_voice *voice, u32 &accum
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ES5505 : BLE is ignored when LPE = 0
|
// ES5505 : BLE is ignored when LPE = 0
|
||||||
inline void es5505_device::check_for_end_forward(es550x_voice *voice, u32 &accum)
|
inline void es5505_device::check_for_end_forward(es550x_voice *voice, u64 &accum)
|
||||||
{
|
{
|
||||||
/* are we past the end? */
|
/* are we past the end? */
|
||||||
if (accum > voice->end)
|
if (accum > voice->end)
|
||||||
@ -774,19 +786,19 @@ inline void es5505_device::check_for_end_forward(es550x_voice *voice, u32 &accum
|
|||||||
|
|
||||||
/* uni-directional looping */
|
/* uni-directional looping */
|
||||||
case CONTROL_LPE:
|
case CONTROL_LPE:
|
||||||
accum = (voice->start + (accum - voice->end)) & m_accum_mask;
|
accum = (voice->start + (accum - voice->end)) & m_address_acc_mask;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* bi-directional looping */
|
/* bi-directional looping */
|
||||||
case CONTROL_LPE | CONTROL_BLE:
|
case CONTROL_LPE | CONTROL_BLE:
|
||||||
accum = (voice->end - (accum - voice->end)) & m_accum_mask;
|
accum = (voice->end - (accum - voice->end)) & m_address_acc_mask;
|
||||||
voice->control ^= CONTROL_DIR;
|
voice->control ^= CONTROL_DIR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void es5505_device::check_for_end_reverse(es550x_voice *voice, u32 &accum)
|
inline void es5505_device::check_for_end_reverse(es550x_voice *voice, u64 &accum)
|
||||||
{
|
{
|
||||||
/* are we past the end? */
|
/* are we past the end? */
|
||||||
if (accum < voice->start)
|
if (accum < voice->start)
|
||||||
@ -806,12 +818,12 @@ inline void es5505_device::check_for_end_reverse(es550x_voice *voice, u32 &accum
|
|||||||
|
|
||||||
/* uni-directional looping */
|
/* uni-directional looping */
|
||||||
case CONTROL_LPE:
|
case CONTROL_LPE:
|
||||||
accum = (voice->end - (voice->start - accum)) & m_accum_mask;
|
accum = (voice->end - (voice->start - accum)) & m_address_acc_mask;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* bi-directional looping */
|
/* bi-directional looping */
|
||||||
case CONTROL_LPE | CONTROL_BLE:
|
case CONTROL_LPE | CONTROL_BLE:
|
||||||
accum = (voice->start + (voice->start - accum)) & m_accum_mask;
|
accum = (voice->start + (voice->start - accum)) & m_address_acc_mask;
|
||||||
voice->control ^= CONTROL_DIR;
|
voice->control ^= CONTROL_DIR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -829,7 +841,7 @@ inline void es5505_device::check_for_end_reverse(es550x_voice *voice, u32 &accum
|
|||||||
void es550x_device::generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
void es550x_device::generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
||||||
{
|
{
|
||||||
const u32 freqcount = voice->freqcount;
|
const u32 freqcount = voice->freqcount;
|
||||||
u32 accum = voice->accum & m_accum_mask;
|
u64 accum = voice->accum & m_address_acc_mask;
|
||||||
|
|
||||||
/* outer loop, in case we switch directions */
|
/* outer loop, in case we switch directions */
|
||||||
if (!(voice->control & CONTROL_STOPMASK))
|
if (!(voice->control & CONTROL_STOPMASK))
|
||||||
@ -838,7 +850,7 @@ void es550x_device::generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
if (!(voice->control & CONTROL_DIR))
|
if (!(voice->control & CONTROL_DIR))
|
||||||
{
|
{
|
||||||
/* fetch two samples */
|
/* fetch two samples */
|
||||||
accum = (accum + freqcount) & m_accum_mask;
|
accum = (accum + freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
@ -852,7 +864,7 @@ void es550x_device::generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* fetch two samples */
|
/* fetch two samples */
|
||||||
accum = (accum - freqcount) & m_accum_mask;
|
accum = (accum - freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
@ -882,9 +894,7 @@ void es550x_device::generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
void es550x_device::generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
void es550x_device::generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
||||||
{
|
{
|
||||||
const u32 freqcount = voice->freqcount;
|
const u32 freqcount = voice->freqcount;
|
||||||
u32 accum = voice->accum & m_accum_mask;
|
u64 accum = voice->accum & m_address_acc_mask;
|
||||||
s32 lvol = get_volume(voice->lvol);
|
|
||||||
s32 rvol = get_volume(voice->rvol);
|
|
||||||
|
|
||||||
/* pre-add the bank offset */
|
/* pre-add the bank offset */
|
||||||
base += voice->exbank;
|
base += voice->exbank;
|
||||||
@ -905,22 +915,18 @@ void es550x_device::generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
val1 = interpolate(val1, val2, accum);
|
val1 = interpolate(val1, val2, accum);
|
||||||
accum = (accum + freqcount) & m_accum_mask;
|
accum = (accum + freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* apply filters */
|
/* apply filters */
|
||||||
apply_filters(voice, val1);
|
apply_filters(voice, val1);
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
{
|
|
||||||
update_envelopes(voice);
|
update_envelopes(voice);
|
||||||
lvol = get_volume(voice->lvol);
|
|
||||||
rvol = get_volume(voice->rvol);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* apply volumes and add */
|
/* apply volumes and add */
|
||||||
*lbuffer += (val1 * lvol) >> VOLUME_ACC_SHIFT;
|
*lbuffer += get_sample(val1, voice->lvol);
|
||||||
*rbuffer += (val1 * rvol) >> VOLUME_ACC_SHIFT;
|
*rbuffer += get_sample(val1, voice->rvol);
|
||||||
|
|
||||||
/* check for loop end */
|
/* check for loop end */
|
||||||
check_for_end_forward(voice, accum);
|
check_for_end_forward(voice, accum);
|
||||||
@ -939,22 +945,18 @@ void es550x_device::generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
val1 = interpolate(val1, val2, accum);
|
val1 = interpolate(val1, val2, accum);
|
||||||
accum = (accum - freqcount) & m_accum_mask;
|
accum = (accum - freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* apply filters */
|
/* apply filters */
|
||||||
apply_filters(voice, val1);
|
apply_filters(voice, val1);
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
{
|
|
||||||
update_envelopes(voice);
|
update_envelopes(voice);
|
||||||
lvol = get_volume(voice->lvol);
|
|
||||||
rvol = get_volume(voice->rvol);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* apply volumes and add */
|
/* apply volumes and add */
|
||||||
*lbuffer += (val1 * lvol) >> VOLUME_ACC_SHIFT;
|
*lbuffer += get_sample(val1, voice->lvol);
|
||||||
*rbuffer += (val1 * rvol) >> VOLUME_ACC_SHIFT;
|
*rbuffer += get_sample(val1, voice->rvol);
|
||||||
|
|
||||||
/* check for loop end */
|
/* check for loop end */
|
||||||
check_for_end_reverse(voice, accum);
|
check_for_end_reverse(voice, accum);
|
||||||
@ -981,9 +983,7 @@ void es550x_device::generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer,
|
|||||||
void es550x_device::generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
void es550x_device::generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples)
|
||||||
{
|
{
|
||||||
const u32 freqcount = voice->freqcount;
|
const u32 freqcount = voice->freqcount;
|
||||||
u32 accum = voice->accum & m_accum_mask;
|
u64 accum = voice->accum & m_address_acc_mask;
|
||||||
s32 lvol = get_volume(voice->lvol);
|
|
||||||
s32 rvol = get_volume(voice->rvol);
|
|
||||||
|
|
||||||
/* pre-add the bank offset */
|
/* pre-add the bank offset */
|
||||||
base += voice->exbank;
|
base += voice->exbank;
|
||||||
@ -1000,22 +1000,18 @@ void es550x_device::generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s
|
|||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
val1 = interpolate(val1, val2, accum);
|
val1 = interpolate(val1, val2, accum);
|
||||||
accum = (accum + freqcount) & m_accum_mask;
|
accum = (accum + freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* apply filters */
|
/* apply filters */
|
||||||
apply_filters(voice, val1);
|
apply_filters(voice, val1);
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
{
|
|
||||||
update_envelopes(voice);
|
update_envelopes(voice);
|
||||||
lvol = get_volume(voice->lvol);
|
|
||||||
rvol = get_volume(voice->rvol);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* apply volumes and add */
|
/* apply volumes and add */
|
||||||
*lbuffer += (val1 * lvol) >> VOLUME_ACC_SHIFT;
|
*lbuffer += get_sample(val1, voice->lvol);
|
||||||
*rbuffer += (val1 * rvol) >> VOLUME_ACC_SHIFT;
|
*rbuffer += get_sample(val1, voice->rvol);
|
||||||
|
|
||||||
/* check for loop end */
|
/* check for loop end */
|
||||||
check_for_end_forward(voice, accum);
|
check_for_end_forward(voice, accum);
|
||||||
@ -1030,22 +1026,18 @@ void es550x_device::generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s
|
|||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
val1 = interpolate(val1, val2, accum);
|
val1 = interpolate(val1, val2, accum);
|
||||||
accum = (accum - freqcount) & m_accum_mask;
|
accum = (accum - freqcount) & m_address_acc_mask;
|
||||||
|
|
||||||
/* apply filters */
|
/* apply filters */
|
||||||
apply_filters(voice, val1);
|
apply_filters(voice, val1);
|
||||||
|
|
||||||
/* update filters/volumes */
|
/* update filters/volumes */
|
||||||
if (voice->ecount != 0)
|
if (voice->ecount != 0)
|
||||||
{
|
|
||||||
update_envelopes(voice);
|
update_envelopes(voice);
|
||||||
lvol = get_volume(voice->lvol);
|
|
||||||
rvol = get_volume(voice->rvol);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* apply volumes and add */
|
/* apply volumes and add */
|
||||||
*lbuffer += (val1 * lvol) >> VOLUME_ACC_SHIFT;
|
*lbuffer += get_sample(val1, voice->lvol);
|
||||||
*rbuffer += (val1 * rvol) >> VOLUME_ACC_SHIFT;
|
*rbuffer += get_sample(val1, voice->rvol);
|
||||||
|
|
||||||
/* check for loop end */
|
/* check for loop end */
|
||||||
check_for_end_reverse(voice, accum);
|
check_for_end_reverse(voice, accum);
|
||||||
@ -1221,13 +1213,13 @@ inline void es5506_device::reg_write_low(es550x_voice *voice, offs_t offset, u32
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08/8: /* FC */
|
case 0x08/8: /* FC */
|
||||||
voice->freqcount = get_accum_shifted_val(data & 0x1ffff);
|
voice->freqcount = get_address_acc_shifted_val(data & 0x1ffff);
|
||||||
LOG("voice %d, freq count=%08x\n", m_current_page & 0x1f, get_accum_res(voice->freqcount));
|
LOG("voice %d, freq count=%08x\n", m_current_page & 0x1f, get_address_acc_res(voice->freqcount));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10/8: /* LVOL */
|
case 0x10/8: /* LVOL */
|
||||||
voice->lvol = data & 0xffff; // low 4 bit is used for finer envelope control
|
voice->lvol = get_shifted_volume(data & 0xffff); // low 4 bit is used for finer envelope control
|
||||||
LOG("voice %d, left vol=%04x\n", m_current_page & 0x1f, voice->lvol);
|
LOG("voice %d, left vol=%04x\n", m_current_page & 0x1f, get_shifted_volume_res(voice->lvol));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x18/8: /* LVRAMP */
|
case 0x18/8: /* LVRAMP */
|
||||||
@ -1236,8 +1228,8 @@ inline void es5506_device::reg_write_low(es550x_voice *voice, offs_t offset, u32
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20/8: /* RVOL */
|
case 0x20/8: /* RVOL */
|
||||||
voice->rvol = data & 0xffff; // low 4 bit is used for finer envelope control
|
voice->rvol = get_shifted_volume(data & 0xffff); // low 4 bit is used for finer envelope control
|
||||||
LOG("voice %d, right vol=%04x\n", m_current_page & 0x1f, voice->rvol);
|
LOG("voice %d, right vol=%04x\n", m_current_page & 0x1f, get_shifted_volume_res(voice->rvol));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x28/8: /* RVRAMP */
|
case 0x28/8: /* RVRAMP */
|
||||||
@ -1311,18 +1303,18 @@ inline void es5506_device::reg_write_high(es550x_voice *voice, offs_t offset, u3
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08/8: /* START */
|
case 0x08/8: /* START */
|
||||||
voice->start = get_accum_shifted_val(data & 0xfffff800);
|
voice->start = get_address_acc_shifted_val(data & 0xfffff800);
|
||||||
LOG("voice %d, loop start=%08x\n", m_current_page & 0x1f, get_accum_res(voice->start));
|
LOG("voice %d, loop start=%08x\n", m_current_page & 0x1f, get_address_acc_res(voice->start));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10/8: /* END */
|
case 0x10/8: /* END */
|
||||||
voice->end = get_accum_shifted_val(data & 0xffffff80);
|
voice->end = get_address_acc_shifted_val(data & 0xffffff80);
|
||||||
LOG("voice %d, loop end=%08x\n", m_current_page & 0x1f, get_accum_res(voice->end));
|
LOG("voice %d, loop end=%08x\n", m_current_page & 0x1f, get_address_acc_res(voice->end));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x18/8: /* ACCUM */
|
case 0x18/8: /* ACCUM */
|
||||||
voice->accum = get_accum_shifted_val(data);
|
voice->accum = get_address_acc_shifted_val(data);
|
||||||
LOG("voice %d, accum=%08x\n", m_current_page & 0x1f, get_accum_res(voice->accum));
|
LOG("voice %d, accum=%08x\n", m_current_page & 0x1f, get_address_acc_res(voice->accum));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20/8: /* O4(n-1) */
|
case 0x20/8: /* O4(n-1) */
|
||||||
@ -1489,11 +1481,11 @@ inline u32 es5506_device::reg_read_low(es550x_voice *voice, offs_t offset)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08/8: /* FC */
|
case 0x08/8: /* FC */
|
||||||
result = get_accum_res(voice->freqcount);
|
result = get_address_acc_res(voice->freqcount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10/8: /* LVOL */
|
case 0x10/8: /* LVOL */
|
||||||
result = voice->lvol;
|
result = get_shifted_volume_res(voice->lvol);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x18/8: /* LVRAMP */
|
case 0x18/8: /* LVRAMP */
|
||||||
@ -1501,7 +1493,7 @@ inline u32 es5506_device::reg_read_low(es550x_voice *voice, offs_t offset)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20/8: /* RVOL */
|
case 0x20/8: /* RVOL */
|
||||||
result = voice->rvol;
|
result = get_shifted_volume_res(voice->rvol);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x28/8: /* RVRAMP */
|
case 0x28/8: /* RVRAMP */
|
||||||
@ -1566,15 +1558,15 @@ inline u32 es5506_device::reg_read_high(es550x_voice *voice, offs_t offset)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08/8: /* START */
|
case 0x08/8: /* START */
|
||||||
result = get_accum_res(voice->start);
|
result = get_address_acc_res(voice->start);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10/8: /* END */
|
case 0x10/8: /* END */
|
||||||
result = get_accum_res(voice->end);
|
result = get_address_acc_res(voice->end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x18/8: /* ACCUM */
|
case 0x18/8: /* ACCUM */
|
||||||
result = get_accum_res(voice->accum);
|
result = get_address_acc_res(voice->accum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20/8: /* O4(n-1) */
|
case 0x20/8: /* O4(n-1) */
|
||||||
@ -1717,48 +1709,48 @@ inline void es5505_device::reg_write_low(es550x_voice *voice, offs_t offset, u16
|
|||||||
|
|
||||||
case 0x01: /* FC */
|
case 0x01: /* FC */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->freqcount = (voice->freqcount & ~get_accum_shifted_val(0x00fe, 1)) | (get_accum_shifted_val((data & 0x00fe), 1));
|
voice->freqcount = (voice->freqcount & ~get_address_acc_shifted_val(0x00fe, 1)) | (get_address_acc_shifted_val((data & 0x00fe), 1));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->freqcount = (voice->freqcount & ~get_accum_shifted_val(0xff00, 1)) | (get_accum_shifted_val((data & 0xff00), 1));
|
voice->freqcount = (voice->freqcount & ~get_address_acc_shifted_val(0xff00, 1)) | (get_address_acc_shifted_val((data & 0xff00), 1));
|
||||||
LOG("%s:voice %d, freq count=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->freqcount, 1));
|
LOG("%s:voice %d, freq count=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->freqcount, 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: /* STRT (hi) */
|
case 0x02: /* STRT (hi) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->start = (voice->start & ~get_accum_shifted_val(0x00ff0000)) | (get_accum_shifted_val((data & 0x00ff) << 16));
|
voice->start = (voice->start & ~get_address_acc_shifted_val(0x00ff0000)) | (get_address_acc_shifted_val((data & 0x00ff) << 16));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->start = (voice->start & ~get_accum_shifted_val(0x1f000000)) | (get_accum_shifted_val((data & 0x1f00) << 16));
|
voice->start = (voice->start & ~get_address_acc_shifted_val(0x1f000000)) | (get_address_acc_shifted_val((data & 0x1f00) << 16));
|
||||||
LOG("%s:voice %d, loop start=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->start));
|
LOG("%s:voice %d, loop start=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->start));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: /* STRT (lo) */
|
case 0x03: /* STRT (lo) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->start = (voice->start & ~get_accum_shifted_val(0x000000e0)) | (get_accum_shifted_val(data & 0x00e0));
|
voice->start = (voice->start & ~get_address_acc_shifted_val(0x000000e0)) | (get_address_acc_shifted_val(data & 0x00e0));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->start = (voice->start & ~get_accum_shifted_val(0x0000ff00)) | (get_accum_shifted_val(data & 0xff00));
|
voice->start = (voice->start & ~get_address_acc_shifted_val(0x0000ff00)) | (get_address_acc_shifted_val(data & 0xff00));
|
||||||
LOG("%s:voice %d, loop start=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->start));
|
LOG("%s:voice %d, loop start=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->start));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: /* END (hi) */
|
case 0x04: /* END (hi) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->end = (voice->end & ~get_accum_shifted_val(0x00ff0000)) | (get_accum_shifted_val((data & 0x00ff) << 16));
|
voice->end = (voice->end & ~get_address_acc_shifted_val(0x00ff0000)) | (get_address_acc_shifted_val((data & 0x00ff) << 16));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->end = (voice->end & ~get_accum_shifted_val(0x1f000000)) | (get_accum_shifted_val((data & 0x1f00) << 16));
|
voice->end = (voice->end & ~get_address_acc_shifted_val(0x1f000000)) | (get_address_acc_shifted_val((data & 0x1f00) << 16));
|
||||||
#if RAINE_CHECK
|
#if RAINE_CHECK
|
||||||
voice->control |= CONTROL_STOP0;
|
voice->control |= CONTROL_STOP0;
|
||||||
#endif
|
#endif
|
||||||
LOG("%s:voice %d, loop end=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->end));
|
LOG("%s:voice %d, loop end=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->end));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: /* END (lo) */
|
case 0x05: /* END (lo) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->end = (voice->end & ~get_accum_shifted_val(0x000000e0)) | (get_accum_shifted_val(data & 0x00e0));
|
voice->end = (voice->end & ~get_address_acc_shifted_val(0x000000e0)) | (get_address_acc_shifted_val(data & 0x00e0));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->end = (voice->end & ~get_accum_shifted_val(0x0000ff00)) | (get_accum_shifted_val(data & 0xff00));
|
voice->end = (voice->end & ~get_address_acc_shifted_val(0x0000ff00)) | (get_address_acc_shifted_val(data & 0xff00));
|
||||||
#if RAINE_CHECK
|
#if RAINE_CHECK
|
||||||
voice->control |= CONTROL_STOP0;
|
voice->control |= CONTROL_STOP0;
|
||||||
#endif
|
#endif
|
||||||
LOG("%s:voice %d, loop end=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->end));
|
LOG("%s:voice %d, loop end=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->end));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06: /* K2 */
|
case 0x06: /* K2 */
|
||||||
@ -1780,29 +1772,29 @@ inline void es5505_device::reg_write_low(es550x_voice *voice, offs_t offset, u16
|
|||||||
case 0x08: /* LVOL */
|
case 0x08: /* LVOL */
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->lvol = (voice->lvol & ~0xff00) | (data & 0xff00);
|
voice->lvol = (voice->lvol & ~0xff00) | (data & 0xff00);
|
||||||
LOG("%s:voice %d, left vol=%02x\n", machine().describe_context(), m_current_page & 0x1f, voice->lvol >> m_volume_shift);
|
LOG("%s:voice %d, left vol=%02x\n", machine().describe_context(), m_current_page & 0x1f, get_shifted_volume_res(voice->lvol));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x09: /* RVOL */
|
case 0x09: /* RVOL */
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->rvol = (voice->rvol & ~0xff00) | (data & 0xff00);
|
voice->rvol = (voice->rvol & ~0xff00) | (data & 0xff00);
|
||||||
LOG("%s:voice %d, right vol=%02x\n", machine().describe_context(), m_current_page & 0x1f, voice->rvol >> m_volume_shift);
|
LOG("%s:voice %d, right vol=%02x\n", machine().describe_context(), m_current_page & 0x1f, get_shifted_volume_res(voice->rvol));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0a: /* ACC (hi) */
|
case 0x0a: /* ACC (hi) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->accum = (voice->accum & ~get_accum_shifted_val(0x00ff0000)) | (get_accum_shifted_val((data & 0x00ff) << 16));
|
voice->accum = (voice->accum & ~get_address_acc_shifted_val(0x00ff0000)) | (get_address_acc_shifted_val((data & 0x00ff) << 16));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->accum = (voice->accum & ~get_accum_shifted_val(0x1f000000)) | (get_accum_shifted_val((data & 0x1f00) << 16));
|
voice->accum = (voice->accum & ~get_address_acc_shifted_val(0x1f000000)) | (get_address_acc_shifted_val((data & 0x1f00) << 16));
|
||||||
LOG("%s:voice %d, accum=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->accum));
|
LOG("%s:voice %d, accum=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->accum));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0b: /* ACC (lo) */
|
case 0x0b: /* ACC (lo) */
|
||||||
if (ACCESSING_BITS_0_7)
|
if (ACCESSING_BITS_0_7)
|
||||||
voice->accum = (voice->accum & ~get_accum_shifted_val(0x000000ff)) | (get_accum_shifted_val(data & 0x00ff));
|
voice->accum = (voice->accum & ~get_address_acc_shifted_val(0x000000ff)) | (get_address_acc_shifted_val(data & 0x00ff));
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->accum = (voice->accum & ~get_accum_shifted_val(0x0000ff00)) | (get_accum_shifted_val(data & 0xff00));
|
voice->accum = (voice->accum & ~get_address_acc_shifted_val(0x0000ff00)) | (get_address_acc_shifted_val(data & 0xff00));
|
||||||
LOG("%s:voice %d, accum=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_accum_res(voice->accum));
|
LOG("%s:voice %d, accum=%08x\n", machine().describe_context(), m_current_page & 0x1f, get_address_acc_res(voice->accum));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0c: /* unused */
|
case 0x0c: /* unused */
|
||||||
@ -1891,7 +1883,7 @@ inline void es5505_device::reg_write_high(es550x_voice *voice, offs_t offset, u1
|
|||||||
voice->o1n1 = (voice->o1n1 & ~0x00ff) | (data & 0x00ff);
|
voice->o1n1 = (voice->o1n1 & ~0x00ff) | (data & 0x00ff);
|
||||||
if (ACCESSING_BITS_8_15)
|
if (ACCESSING_BITS_8_15)
|
||||||
voice->o1n1 = (s16)((voice->o1n1 & ~0xff00) | (data & 0xff00));
|
voice->o1n1 = (s16)((voice->o1n1 & ~0xff00) | (data & 0xff00));
|
||||||
LOG("%s:voice %d, O1(n-1)=%04x (accum=%08x)\n", machine().describe_context(), m_current_page & 0x1f, voice->o1n1 & 0xffff, get_accum_res(voice->accum));
|
LOG("%s:voice %d, O1(n-1)=%04x (accum=%08x)\n", machine().describe_context(), m_current_page & 0x1f, voice->o1n1 & 0xffff, get_address_acc_res(voice->accum));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x07:
|
case 0x07:
|
||||||
@ -2012,23 +2004,23 @@ inline u16 es5505_device::reg_read_low(es550x_voice *voice, offs_t offset)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01: /* FC */
|
case 0x01: /* FC */
|
||||||
result = get_accum_res(voice->freqcount, 1);
|
result = get_address_acc_res(voice->freqcount, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: /* STRT (hi) */
|
case 0x02: /* STRT (hi) */
|
||||||
result = get_accum_res(voice->start) >> 16;
|
result = get_address_acc_res(voice->start) >> 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: /* STRT (lo) */
|
case 0x03: /* STRT (lo) */
|
||||||
result = get_accum_res(voice->start);
|
result = get_address_acc_res(voice->start);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: /* END (hi) */
|
case 0x04: /* END (hi) */
|
||||||
result = get_accum_res(voice->end) >> 16;
|
result = get_address_acc_res(voice->end) >> 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: /* END (lo) */
|
case 0x05: /* END (lo) */
|
||||||
result = get_accum_res(voice->end);
|
result = get_address_acc_res(voice->end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06: /* K2 */
|
case 0x06: /* K2 */
|
||||||
@ -2048,11 +2040,11 @@ inline u16 es5505_device::reg_read_low(es550x_voice *voice, offs_t offset)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0a: /* ACC (hi) */
|
case 0x0a: /* ACC (hi) */
|
||||||
result = get_accum_res(voice->accum) >> 16;
|
result = get_address_acc_res(voice->accum) >> 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0b: /* ACC (lo) */
|
case 0x0b: /* ACC (lo) */
|
||||||
result = get_accum_res(voice->accum);
|
result = get_address_acc_res(voice->accum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0c: /* unused */
|
case 0x0c: /* unused */
|
||||||
|
@ -37,7 +37,7 @@ protected:
|
|||||||
// constants for volumes
|
// constants for volumes
|
||||||
const u32 FINE_VOLUME_BIT = 16;
|
const u32 FINE_VOLUME_BIT = 16;
|
||||||
|
|
||||||
const u32 VOLUME_ACC_SHIFT = 11;
|
const u32 VOLUME_ACC_BIT = 20;
|
||||||
|
|
||||||
// constants for address
|
// constants for address
|
||||||
const u32 ADDRESS_FRAC_BIT = 11;
|
const u32 ADDRESS_FRAC_BIT = 11;
|
||||||
@ -88,23 +88,31 @@ protected:
|
|||||||
|
|
||||||
void update_irq_state();
|
void update_irq_state();
|
||||||
void update_internal_irq_state();
|
void update_internal_irq_state();
|
||||||
void compute_tables(u32 total_volume_bit = 16, u32 exponent_bit = 4, u32 mantissa_bit = 8, u32 mantissa_shift = 11);
|
void compute_tables(u32 total_volume_bit = 16, u32 exponent_bit = 4, u32 mantissa_bit = 8);
|
||||||
void get_accum_mask(u32 address_integer, u32 address_frac);
|
void get_accum_mask(u32 address_integer = 21, u32 address_frac = 11);
|
||||||
|
|
||||||
virtual inline u32 get_bank(u32 control) { return 0; }
|
virtual inline u32 get_bank(u32 control) { return 0; }
|
||||||
virtual inline u32 get_ca(u32 control) { return 0; }
|
virtual inline u32 get_ca(u32 control) { return 0; }
|
||||||
virtual inline u32 get_lp(u32 control) { return 0; }
|
virtual inline u32 get_lp(u32 control) { return 0; }
|
||||||
|
|
||||||
inline u32 get_volume(u16 volume) { return m_volume_lookup[volume >> m_volume_shift_int]; }
|
template<typename T, typename U> inline T lshift_signed(T val, U shift) { return (shift >= 0) ? val << shift : val >> (-shift); }
|
||||||
inline u32 get_accum_shifted_val(u32 val, int bias = 0) { return val << (m_accum_shift - bias); }
|
template<typename T, typename U> inline T rshift_signed(T val, U shift) { return (shift >= 0) ? val >> shift : val << (-shift); }
|
||||||
inline u32 get_accum_res(u32 val, int bias = 0) { return val >> (m_accum_shift - bias); }
|
|
||||||
inline u32 get_integer_addr(u32 accum, s32 bias = 0) { return ((accum + (bias << ADDRESS_FRAC_BIT)) & m_accum_mask) >> ADDRESS_FRAC_BIT; }
|
|
||||||
|
|
||||||
inline s32 interpolate(s32 sample1, s32 sample2, u32 accum);
|
inline u64 get_shifted_volume_res(u64 volume) { return rshift_signed<u64, s8>(volume, m_volume_shift); }
|
||||||
|
inline u64 get_shifted_volume(u64 volume) { return lshift_signed<u64, s8>(volume, m_volume_shift); }
|
||||||
|
inline u64 get_volume(u32 volume) { return m_volume_lookup[rshift_signed<u32, s8>(volume, m_volume_shift_int)]; }
|
||||||
|
|
||||||
|
inline u64 get_address_acc_shifted_val(u64 val, int bias = 0) { return lshift_signed<u64, s8>(val, m_address_acc_shift - bias); }
|
||||||
|
inline u64 get_address_acc_res(u64 val, int bias = 0) { return rshift_signed<u64, s8>(val, m_address_acc_shift - bias); }
|
||||||
|
inline u64 get_integer_addr(u64 accum, s32 bias = 0) { return ((accum + (bias << ADDRESS_FRAC_BIT)) & m_address_acc_mask) >> ADDRESS_FRAC_BIT; }
|
||||||
|
|
||||||
|
inline s64 get_sample(s32 sample, u32 volume) { return rshift_signed<s64, s8>(sample * get_volume(volume), m_volume_acc_shift); }
|
||||||
|
|
||||||
|
inline s32 interpolate(s32 sample1, s32 sample2, u64 accum);
|
||||||
inline void apply_filters(es550x_voice *voice, s32 &sample);
|
inline void apply_filters(es550x_voice *voice, s32 &sample);
|
||||||
virtual inline void update_envelopes(es550x_voice *voice) {};
|
virtual inline void update_envelopes(es550x_voice *voice) {};
|
||||||
virtual inline void check_for_end_forward(es550x_voice *voice, u32 &accum) {};
|
virtual inline void check_for_end_forward(es550x_voice *voice, u64 &accum) {};
|
||||||
virtual inline void check_for_end_reverse(es550x_voice *voice, u32 &accum) {};
|
virtual inline void check_for_end_reverse(es550x_voice *voice, u64 &accum) {};
|
||||||
void generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
void generate_dummy(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
||||||
void generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
void generate_ulaw(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
||||||
void generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
void generate_pcm(es550x_voice *voice, u16 *base, s32 *lbuffer, s32 *rbuffer, int samples);
|
||||||
@ -116,11 +124,12 @@ protected:
|
|||||||
int m_sample_rate; /* current sample rate */
|
int m_sample_rate; /* current sample rate */
|
||||||
u16 * m_region_base[4]; /* pointer to the base of the region */
|
u16 * m_region_base[4]; /* pointer to the base of the region */
|
||||||
u32 m_master_clock; /* master clock frequency */
|
u32 m_master_clock; /* master clock frequency */
|
||||||
u64 m_accum_shift;
|
s8 m_address_acc_shift;
|
||||||
u64 m_accum_mask;
|
u64 m_address_acc_mask;
|
||||||
|
|
||||||
u64 m_volume_shift;
|
s8 m_volume_shift;
|
||||||
u64 m_volume_shift_int;
|
s8 m_volume_shift_int;
|
||||||
|
s64 m_volume_acc_shift;
|
||||||
|
|
||||||
u8 m_current_page; /* current register page */
|
u8 m_current_page; /* current register page */
|
||||||
u8 m_active_voices; /* number of active voices */
|
u8 m_active_voices; /* number of active voices */
|
||||||
@ -173,8 +182,8 @@ protected:
|
|||||||
virtual inline u32 get_lp(u32 control) override { return (control >> 8) & LP_MASK; }
|
virtual inline u32 get_lp(u32 control) override { return (control >> 8) & LP_MASK; }
|
||||||
|
|
||||||
virtual inline void update_envelopes(es550x_voice *voice) override;
|
virtual inline void update_envelopes(es550x_voice *voice) override;
|
||||||
virtual inline void check_for_end_forward(es550x_voice *voice, u32 &accum) override;
|
virtual inline void check_for_end_forward(es550x_voice *voice, u64 &accum) override;
|
||||||
virtual inline void check_for_end_reverse(es550x_voice *voice, u32 &accum) override;
|
virtual inline void check_for_end_reverse(es550x_voice *voice, u64 &accum) override;
|
||||||
virtual void generate_samples(s32 **outputs, int offset, int samples) override;
|
virtual void generate_samples(s32 **outputs, int offset, int samples) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -218,8 +227,8 @@ protected:
|
|||||||
virtual inline u32 get_bank(u32 control) override { return (control >> 2) & 1; }
|
virtual inline u32 get_bank(u32 control) override { return (control >> 2) & 1; }
|
||||||
|
|
||||||
virtual inline void update_envelopes(es550x_voice *voice) override;
|
virtual inline void update_envelopes(es550x_voice *voice) override;
|
||||||
virtual inline void check_for_end_forward(es550x_voice *voice, u32 &accum) override;
|
virtual inline void check_for_end_forward(es550x_voice *voice, u64 &accum) override;
|
||||||
virtual inline void check_for_end_reverse(es550x_voice *voice, u32 &accum) override;
|
virtual inline void check_for_end_reverse(es550x_voice *voice, u64 &accum) override;
|
||||||
virtual void generate_samples(s32 **outputs, int offset, int samples) override;
|
virtual void generate_samples(s32 **outputs, int offset, int samples) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user