mirror of
https://github.com/holub/mame
synced 2025-05-22 13:48:55 +03:00
support for mid-playing channel updates, and fixed pseudoreverb
This commit is contained in:
parent
967ed3cfbd
commit
471c20077a
@ -75,6 +75,7 @@ typedef struct
|
|||||||
INT16 FN; /* f-number */
|
INT16 FN; /* f-number */
|
||||||
INT8 OCT; /* octave */
|
INT8 OCT; /* octave */
|
||||||
INT8 PRVB; /* pseudo-reverb */
|
INT8 PRVB; /* pseudo-reverb */
|
||||||
|
INT8 PRVB_active;
|
||||||
INT8 DAMP; /* damping */
|
INT8 DAMP; /* damping */
|
||||||
INT8 LD; /* level direct */
|
INT8 LD; /* level direct */
|
||||||
INT8 TL; /* total level */
|
INT8 TL; /* total level */
|
||||||
@ -191,6 +192,23 @@ static int ymf278b_compute_rate(YMF278BSlot *slot, int val)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ymf278b_compute_rate_d(YMF278BSlot *slot, int val)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
// rate override with damping/pseudo reverb
|
||||||
|
if (slot->DAMP)
|
||||||
|
res = 63;
|
||||||
|
else if (slot->PRVB && slot->env_vol > ((6*8)<<23))
|
||||||
|
{
|
||||||
|
slot->PRVB_active = 1;
|
||||||
|
res = 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = ymf278b_compute_rate(slot, val);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
INLINE UINT32 ymf278_compute_attack_rate(int num)
|
INLINE UINT32 ymf278_compute_attack_rate(int num)
|
||||||
{
|
{
|
||||||
// estimated (less accurate on high rates)
|
// estimated (less accurate on high rates)
|
||||||
@ -221,7 +239,20 @@ static UINT32 ymf278_compute_decay_rate(int num)
|
|||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ymf278b_envelope_next(YMF278BSlot *slot)
|
static void ymf278b_compute_step(YMF278BSlot *slot)
|
||||||
|
{
|
||||||
|
unsigned int step;
|
||||||
|
int oct;
|
||||||
|
|
||||||
|
oct = slot->OCT;
|
||||||
|
if(oct & 8)
|
||||||
|
oct |= -8;
|
||||||
|
|
||||||
|
step = (slot->FN | 1024) << (oct + 7);
|
||||||
|
slot->step = step / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ymf278b_compute_envelope(YMF278BSlot *slot)
|
||||||
{
|
{
|
||||||
if(slot->env_step == 0)
|
if(slot->env_step == 0)
|
||||||
{
|
{
|
||||||
@ -229,13 +260,13 @@ static void ymf278b_envelope_next(YMF278BSlot *slot)
|
|||||||
int rate = ymf278b_compute_rate(slot, slot->AR);
|
int rate = ymf278b_compute_rate(slot, slot->AR);
|
||||||
slot->env_vol = 256U<<23;
|
slot->env_vol = 256U<<23;
|
||||||
slot->env_vol_lim = (256U<<23) - 1;
|
slot->env_vol_lim = (256U<<23) - 1;
|
||||||
slot->env_step++;
|
|
||||||
|
|
||||||
if (rate==63)
|
if (rate==63)
|
||||||
{
|
{
|
||||||
// immediate
|
// immediate
|
||||||
slot->env_vol = 0;
|
slot->env_vol = 0;
|
||||||
slot->env_vol_lim = 256U<<23;
|
slot->env_vol_lim = 256U<<23;
|
||||||
|
slot->env_step++;
|
||||||
// ..fall through
|
// ..fall through
|
||||||
}
|
}
|
||||||
else if (rate<4)
|
else if (rate<4)
|
||||||
@ -254,17 +285,9 @@ static void ymf278b_envelope_next(YMF278BSlot *slot)
|
|||||||
if(slot->env_step == 1)
|
if(slot->env_step == 1)
|
||||||
{
|
{
|
||||||
// Decay 1
|
// Decay 1
|
||||||
slot->env_vol = 0;
|
|
||||||
slot->env_step++;
|
|
||||||
if(slot->DL)
|
if(slot->DL)
|
||||||
{
|
{
|
||||||
int rate;
|
int rate = ymf278b_compute_rate_d(slot, slot->D1R);
|
||||||
// rate override with damping/pseudo reverb
|
|
||||||
// NOTE: pseudo reverb starts at 0dB here, but should start at -18dB (which is actually between D1 and D2)
|
|
||||||
if (slot->DAMP) rate = 63;
|
|
||||||
else if (slot->PRVB) rate = 5;
|
|
||||||
else rate = ymf278b_compute_rate(slot, slot->D1R);
|
|
||||||
|
|
||||||
LOG(("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g\n", slot->DL, slot->D1R, rate, ymf278_compute_decay_rate(rate)*1000.0));
|
LOG(("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g\n", slot->DL, slot->D1R, rate, ymf278_compute_decay_rate(rate)*1000.0));
|
||||||
if(rate<4)
|
if(rate<4)
|
||||||
slot->env_vol_step = 0;
|
slot->env_vol_step = 0;
|
||||||
@ -273,24 +296,20 @@ static void ymf278b_envelope_next(YMF278BSlot *slot)
|
|||||||
slot->env_vol_lim = (slot->DL*8)<<23;
|
slot->env_vol_lim = (slot->DL*8)<<23;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ..fall through
|
else
|
||||||
|
slot->env_step++;
|
||||||
|
// ..fall through
|
||||||
}
|
}
|
||||||
if(slot->env_step == 2)
|
if(slot->env_step == 2)
|
||||||
{
|
{
|
||||||
// Decay 2
|
// Decay 2
|
||||||
int rate;
|
int rate = ymf278b_compute_rate_d(slot, slot->D2R);
|
||||||
// rate override with damping/pseudo reverb
|
|
||||||
if (slot->DAMP) rate = 63;
|
|
||||||
else if (slot->PRVB) rate = 5;
|
|
||||||
else rate = ymf278b_compute_rate(slot, slot->D2R);
|
|
||||||
|
|
||||||
LOG(("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, current vol = %d\n", slot->D2R, rate, ymf278_compute_decay_rate(rate)*1000.0, slot->env_vol >> 23));
|
LOG(("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, current vol = %d\n", slot->D2R, rate, ymf278_compute_decay_rate(rate)*1000.0, slot->env_vol >> 23));
|
||||||
if(rate<4)
|
if(rate<4)
|
||||||
slot->env_vol_step = 0;
|
slot->env_vol_step = 0;
|
||||||
else
|
else
|
||||||
slot->env_vol_step = ((256U-slot->DL*8)<<23) / ymf278_compute_decay_rate(rate);
|
slot->env_vol_step = ((256U-slot->DL*8)<<23) / ymf278_compute_decay_rate(rate);
|
||||||
slot->env_vol_lim = 256U<<23;
|
slot->env_vol_lim = 256U<<23;
|
||||||
slot->env_step++;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(slot->env_step == 3)
|
if(slot->env_step == 3)
|
||||||
@ -303,19 +322,13 @@ static void ymf278b_envelope_next(YMF278BSlot *slot)
|
|||||||
if(slot->env_step == 4)
|
if(slot->env_step == 4)
|
||||||
{
|
{
|
||||||
// Release
|
// Release
|
||||||
int rate;
|
int rate = ymf278b_compute_rate_d(slot, slot->RR);
|
||||||
// rate override with damping/pseudo reverb
|
|
||||||
if (slot->DAMP) rate = 63;
|
|
||||||
else if (slot->PRVB) rate = 5;
|
|
||||||
else rate = ymf278b_compute_rate(slot, slot->RR);
|
|
||||||
|
|
||||||
LOG(("YMF278B: Release, val = %d, rate = %d, delay = %g\n", slot->RR, rate, ymf278_compute_decay_rate(rate)*1000.0));
|
LOG(("YMF278B: Release, val = %d, rate = %d, delay = %g\n", slot->RR, rate, ymf278_compute_decay_rate(rate)*1000.0));
|
||||||
if(rate<4)
|
if(rate<4)
|
||||||
slot->env_vol_step = 0;
|
slot->env_vol_step = 0;
|
||||||
else
|
else
|
||||||
slot->env_vol_step = ((256U<<23)-slot->env_vol) / ymf278_compute_decay_rate(rate);
|
slot->env_vol_step = ((256U<<23)-slot->env_vol) / ymf278_compute_decay_rate(rate);
|
||||||
slot->env_vol_lim = 256U<<23;
|
slot->env_vol_lim = 256U<<23;
|
||||||
slot->env_step++;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(slot->env_step == 5)
|
if(slot->env_step == 5)
|
||||||
@ -358,12 +371,9 @@ static STREAM_UPDATE( ymf278b_pcm_update )
|
|||||||
// If the step is bigger than the loop, finish the sample forcibly
|
// If the step is bigger than the loop, finish the sample forcibly
|
||||||
if(slot->stepptr >= slot->endaddr)
|
if(slot->stepptr >= slot->endaddr)
|
||||||
{
|
{
|
||||||
slot->env_vol = 256U<<23;
|
slot->env_step = 5;
|
||||||
slot->env_vol_step = 0;
|
ymf278b_compute_envelope(slot);
|
||||||
slot->env_vol_lim = 0;
|
break;
|
||||||
slot->active = 0;
|
|
||||||
slot->stepptr = 0;
|
|
||||||
slot->step = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +407,12 @@ static STREAM_UPDATE( ymf278b_pcm_update )
|
|||||||
// update envelope
|
// update envelope
|
||||||
slot->env_vol += slot->env_vol_step;
|
slot->env_vol += slot->env_vol_step;
|
||||||
if(((INT32)(slot->env_vol - slot->env_vol_lim)) >= 0)
|
if(((INT32)(slot->env_vol - slot->env_vol_lim)) >= 0)
|
||||||
ymf278b_envelope_next(slot);
|
{
|
||||||
|
slot->env_step++;
|
||||||
|
ymf278b_compute_envelope(slot);
|
||||||
|
}
|
||||||
|
else if (slot->PRVB && !slot->PRVB_active && slot->env_step && slot->env_vol > ((6*8)<<23))
|
||||||
|
ymf278b_compute_envelope(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,8 +557,6 @@ static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data, int init)
|
|||||||
chip->stream->update();
|
chip->stream->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->pcmregs[reg] = data;
|
|
||||||
|
|
||||||
// Handle slot registers specifically
|
// Handle slot registers specifically
|
||||||
if (reg >= 0x08 && reg <= 0xf7)
|
if (reg >= 0x08 && reg <= 0xf7)
|
||||||
{
|
{
|
||||||
@ -594,101 +607,105 @@ static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data, int init)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->lfo = (p[7] >> 3) & 7;
|
|
||||||
slot->vib = p[7] & 7;
|
|
||||||
slot->AR = p[8] >> 4;
|
|
||||||
slot->D1R = p[8] & 0xf;
|
|
||||||
slot->DL = p[9] >> 4;
|
|
||||||
slot->D2R = p[9] & 0xf;
|
|
||||||
slot->RC = p[10] >> 4;
|
|
||||||
slot->RR = p[10] & 0xf;
|
|
||||||
slot->AM = p[11] & 7;
|
|
||||||
|
|
||||||
slot->startaddr = (p[2] | (p[1]<<8) | ((p[0]&0x3f)<<16));
|
slot->startaddr = (p[2] | (p[1]<<8) | ((p[0]&0x3f)<<16));
|
||||||
slot->loopaddr = (p[4]<<16) | (p[3]<<24);
|
slot->loopaddr = (p[4]<<16) | (p[3]<<24);
|
||||||
slot->endaddr = (p[6]<<16) | (p[5]<<24);
|
slot->endaddr = (p[6]<<16) | (p[5]<<24);
|
||||||
slot->endaddr -= 0x00010000U;
|
slot->endaddr -= 0x00010000U;
|
||||||
slot->endaddr ^= 0xffff0000U;
|
slot->endaddr ^= 0xffff0000U;
|
||||||
|
|
||||||
|
// copy internal registers data
|
||||||
|
for (i = 7; i < 12; i++)
|
||||||
|
ymf278b_C_w(chip, 8 + snum + (i-2) * 24, p[i], 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
slot->wave &= 0xff;
|
slot->wave &= 0xff;
|
||||||
slot->wave |= ((data&0x1)<<8);
|
slot->wave |= ((data&0x1)<<8);
|
||||||
slot->FN &= 0x380;
|
slot->FN &= 0x380;
|
||||||
slot->FN |= (data>>1);
|
slot->FN |= (data>>1);
|
||||||
|
if (slot->active && data != chip->pcmregs[reg])
|
||||||
|
ymf278b_compute_step(slot);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
slot->FN &= 0x07f;
|
slot->FN &= 0x07f;
|
||||||
slot->FN |= ((data&0x07)<<7);
|
slot->FN |= ((data&0x07)<<7);
|
||||||
slot->PRVB = ((data&0x4)>>3);
|
slot->PRVB = ((data&0x8)>>3);
|
||||||
slot->OCT = ((data&0xf0)>>4);
|
slot->OCT = ((data&0xf0)>>4);
|
||||||
|
if (slot->active && data != chip->pcmregs[reg])
|
||||||
|
{
|
||||||
|
ymf278b_compute_step(slot);
|
||||||
|
ymf278b_compute_envelope(slot);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
slot->TL = (data>>1);
|
slot->TL = (data>>1);
|
||||||
slot->LD = data&0x1;
|
slot->LD = data&0x1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
slot->pan = data&0xf;
|
slot->pan = data&0xf;
|
||||||
slot->DAMP = (data&0x40)>>6;
|
slot->DAMP = (data&0x40)>>6;
|
||||||
if (data & 0x80)
|
if (data & 0x80)
|
||||||
{
|
{
|
||||||
unsigned int step;
|
|
||||||
int oct;
|
|
||||||
|
|
||||||
slot->active = 1;
|
slot->active = 1;
|
||||||
|
slot->PRVB_active = 0;
|
||||||
oct = slot->OCT;
|
|
||||||
if(oct & 8)
|
|
||||||
oct |= -8;
|
|
||||||
|
|
||||||
slot->env_step = 0;
|
slot->env_step = 0;
|
||||||
slot->env_vol = 256U<<23;
|
slot->env_vol = 256U<<23;
|
||||||
slot->env_vol_step = 0;
|
slot->env_vol_step = 0;
|
||||||
slot->env_vol_lim = 256U<<23;
|
slot->env_vol_lim = 256U<<23;
|
||||||
slot->stepptr = 0;
|
slot->stepptr = 0;
|
||||||
slot->step = 0;
|
|
||||||
|
|
||||||
step = (slot->FN | 1024) << (oct + 7);
|
ymf278b_compute_step(slot);
|
||||||
slot->step = step / 4;
|
ymf278b_compute_envelope(slot);
|
||||||
|
|
||||||
ymf278b_envelope_next(slot);
|
|
||||||
|
|
||||||
LOG(("YMF278B: slot %2d wave %3d lfo=%d vib=%d ar=%d d1r=%d dl=%d d2r=%d rc=%d rr=%d am=%d\n", snum, slot->wave,
|
LOG(("YMF278B: slot %2d wave %3d lfo=%d vib=%d ar=%d d1r=%d dl=%d d2r=%d rc=%d rr=%d am=%d\n", snum, slot->wave,
|
||||||
slot->lfo, slot->vib, slot->AR, slot->D1R, slot->DL, slot->D2R, slot->RC, slot->RR, slot->AM));
|
slot->lfo, slot->vib, slot->AR, slot->D1R, slot->DL, slot->D2R, slot->RC, slot->RR, slot->AM));
|
||||||
LOG((" b=%d, start=%x, loop=%x, end=%x, oct=%d, fn=%d, step=%x\n", slot->bits, slot->startaddr, slot->loopaddr>>16, slot->endaddr>>16, oct, slot->FN, slot->step));
|
LOG((" b=%d, start=%x, loop=%x, end=%x, oct=%d, fn=%d, step=%x\n", slot->bits, slot->startaddr, slot->loopaddr>>16, slot->endaddr>>16, slot->OCT, slot->FN, slot->step));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(("YMF278B: slot %2d off\n", snum));
|
if (slot->active)
|
||||||
if(slot->active)
|
|
||||||
{
|
{
|
||||||
|
LOG(("YMF278B: slot %2d off - ", snum));
|
||||||
slot->env_step = 4;
|
slot->env_step = 4;
|
||||||
ymf278b_envelope_next(slot);
|
ymf278b_compute_envelope(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
slot->vib = data&0x7;
|
slot->vib = data&0x7;
|
||||||
slot->lfo = (data>>3)&0x7;
|
slot->lfo = (data>>3)&0x7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
slot->AR = data>>4;
|
slot->AR = data>>4;
|
||||||
slot->D1R = data&0xf;
|
slot->D1R = data&0xf;
|
||||||
|
if (slot->active && data != chip->pcmregs[reg])
|
||||||
|
ymf278b_compute_envelope(slot);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
slot->DL = data>>4;
|
slot->DL = data>>4;
|
||||||
slot->D2R = data&0xf;
|
slot->D2R = data&0xf;
|
||||||
|
if (slot->active && data != chip->pcmregs[reg])
|
||||||
|
ymf278b_compute_envelope(slot);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
slot->RC = data>>4;
|
slot->RC = data>>4;
|
||||||
slot->RR = data&0xf;
|
slot->RR = data&0xf;
|
||||||
break;
|
if (slot->active && data != chip->pcmregs[reg])
|
||||||
case 9:
|
ymf278b_compute_envelope(slot);
|
||||||
slot->AM = data & 0x7;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 9:
|
||||||
logerror("YMF278B: Port C write %02x, %02x\n", reg, data);
|
slot->AM = data & 0x7;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -739,6 +756,8 @@ static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data, int init)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->pcmregs[reg] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TIMER_CALLBACK( ymf278b_timer_busy_clear )
|
static TIMER_CALLBACK( ymf278b_timer_busy_clear )
|
||||||
@ -877,7 +896,7 @@ static DEVICE_RESET( ymf278b )
|
|||||||
slot->endaddr = 0;
|
slot->endaddr = 0;
|
||||||
|
|
||||||
slot->env_step = 5;
|
slot->env_step = 5;
|
||||||
ymf278b_envelope_next(slot);
|
ymf278b_compute_envelope(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->timer_a->reset();
|
chip->timer_a->reset();
|
||||||
@ -933,6 +952,7 @@ static void ymf278b_register_save_state(device_t *device, YMF278BChip *chip)
|
|||||||
device->save_item(NAME(chip->slots[i].FN), i);
|
device->save_item(NAME(chip->slots[i].FN), i);
|
||||||
device->save_item(NAME(chip->slots[i].OCT), i);
|
device->save_item(NAME(chip->slots[i].OCT), i);
|
||||||
device->save_item(NAME(chip->slots[i].PRVB), i);
|
device->save_item(NAME(chip->slots[i].PRVB), i);
|
||||||
|
device->save_item(NAME(chip->slots[i].PRVB_active), i);
|
||||||
device->save_item(NAME(chip->slots[i].DAMP), i);
|
device->save_item(NAME(chip->slots[i].DAMP), i);
|
||||||
device->save_item(NAME(chip->slots[i].LD), i);
|
device->save_item(NAME(chip->slots[i].LD), i);
|
||||||
device->save_item(NAME(chip->slots[i].TL), i);
|
device->save_item(NAME(chip->slots[i].TL), i);
|
||||||
|
Loading…
Reference in New Issue
Block a user