Skip to content

Commit

Permalink
ES5503: support "sync" and "AM" modes
Browse files Browse the repository at this point in the history
This is a port of the recent MAME update, with a few additional fixes.
Rearranging the update loop was necessary to make AM mode work properly.
  • Loading branch information
ValleyBell committed Dec 26, 2023
1 parent b2210a4 commit 76a4bbe
Showing 1 changed file with 69 additions and 39 deletions.
108 changes: 69 additions & 39 deletions emu/cores/es5503.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*
ES5503 - Ensoniq ES5503 "DOC" emulator v2.1.2
ES5503 - Ensoniq ES5503 "DOC" emulator v2.3
By R. Belmont.
Copyright R. Belmont.
Expand All @@ -13,8 +13,8 @@
(used in the "Soundscape" series of ISA PC sound cards) followed on a fundamentally
similar architecture.
Bugs: On the real silicon, oscillators 30 and 31 have random volume fluctuations and are
unusable for playback. We don't attempt to emulate that. :-)
Bugs: On the real silicon, the uppermost enabled oscillator contributes to the output 3 times.
This is likely why the Apple IIgs system software doesn't let you use oscillators 30 and 31.
Additionally, in "swap" mode, there's one cycle when the switch takes place where the
oscillator's output is 0x80 (centerline) regardless of the sample data. This can
Expand All @@ -35,6 +35,7 @@
want to loop.
2.1.3 (RB) - Fixed oscillator enable register off-by-1 which caused everything to be half a step sharp.
2.2 (RB) - More precise one-shot even/swap odd behavior from hardware observations with Ian Brumby's SWAPTEST.
2.3 (RB) - Sync & AM modes added, emulate the volume glitch for the highest-numbered enabled oscillator.
*/

#include <stdlib.h>
Expand Down Expand Up @@ -169,9 +170,26 @@ static void es5503_halt_osc(ES5503Chip *chip, int onum, int type, UINT32 *accumu
{
ES5503Osc *pOsc = &chip->oscillators[onum];
ES5503Osc *pPartner = &chip->oscillators[onum^1];
const int mode = (pOsc->control>>1) & 3;
int mode = (pOsc->control>>1) & 3;
const int partnerMode = (pPartner->control>>1) & 3;

// check for sync mode
if (mode == MODE_SYNCAM)
{
if (!(onum & 1))
{
// we're even, so if the odd oscillator 1 below us is playing,
// restart it.
if (!(chip->oscillators[onum - 1].control & 1))
{
chip->oscillators[onum - 1].accumulator = 0;
}
}

// loop this oscillator for both sync and AM
mode = MODE_FREE;
}

// if 0 found in sample data or mode is not free-run, halt this oscillator
if ((mode != MODE_FREE) || (type != 0))
{
Expand Down Expand Up @@ -225,43 +243,64 @@ static void es5503_pcm_update(void *param, UINT32 samples, DEV_SMPL **outputs)
return;

chnsStereo = chip->output_channels & ~1;
for (osc = 0; osc < chip->oscsenabled; osc++)
for (snum = 0; snum < samples; snum++)
{
ES5503Osc *pOsc = &chip->oscillators[osc];

if (!(pOsc->control & 1) && ! pOsc->Muted)
for (osc = 0; osc < chip->oscsenabled; osc++)
{
UINT32 wtptr = pOsc->wavetblpointer & wavemasks[pOsc->wavetblsize];
UINT32 altram;
UINT32 acc = pOsc->accumulator;
UINT16 wtsize = pOsc->wtsize - 1;
UINT16 freq = pOsc->freq;
INT16 vol = pOsc->vol;
UINT8 chnMask = (pOsc->control >> 4) & 0x0F;
int resshift = resshifts[pOsc->resolution] - pOsc->wavetblsize;
UINT32 sizemask = accmasks[pOsc->wavetblsize];
INT32 outData;

chnMask &= chip->outchn_mask;
for (snum = 0; snum < samples; snum++)
ES5503Osc *pOsc = &chip->oscillators[osc];

if (!(pOsc->control & 1) && ! pOsc->Muted)
{
altram = acc >> resshift;
UINT32 wtptr = pOsc->wavetblpointer & wavemasks[pOsc->wavetblsize];
UINT32 altram;
UINT16 wtsize = pOsc->wtsize - 1;
UINT8 chnMask = (pOsc->control >> 4) & 0x0F;
int resshift = resshifts[pOsc->resolution] - pOsc->wavetblsize;
UINT32 sizemask = accmasks[pOsc->wavetblsize];
const int mode = (pOsc->control>>1) & 3;

chnMask &= chip->outchn_mask;
altram = pOsc->accumulator >> resshift;
ramptr = altram & sizemask;

acc += freq;
pOsc->accumulator += pOsc->freq;

// channel strobe is always valid when reading; this allows potentially banking per voice
chip->channel_strobe = (pOsc->control>>4) & 0xf;
pOsc->data = chip->docram[ramptr + wtptr];

if (pOsc->data == 0x00)
{
es5503_halt_osc(chip, osc, 1, &acc, resshift);
es5503_halt_osc(chip, osc, 1, &pOsc->accumulator, resshift);
}
else
{
outData = (pOsc->data - 0x80) * vol;

INT32 outData;
if (mode != MODE_SYNCAM)
{
outData = (pOsc->data - 0x80) * (INT16)pOsc->vol;
}
else
{
// if we're odd, we play nothing ourselves
if (osc & 1)
{
if (osc < 31)
{
// if the next oscillator up is playing, it's volume becomes our control
if (!(chip->oscillators[osc + 1].control & 1))
{
chip->oscillators[osc + 1].vol = pOsc->data;
}
}
outData = 0;
}
else // hard sync, both oscillators play?
{
outData = (pOsc->data - 0x80) * (INT16)pOsc->vol;
}
}

// send groups of 2 channels to L or R
for (chan = 0; chan < chnsStereo; chan ++)
{
Expand All @@ -281,21 +320,12 @@ static void es5503_pcm_update(void *param, UINT32 samples, DEV_SMPL **outputs)

if (altram >= wtsize)
{
es5503_halt_osc(chip, osc, 0, &acc, resshift);
es5503_halt_osc(chip, osc, 0, &pOsc->accumulator, resshift);
}
}

// if oscillator halted, we've got no more samples to generate
if (pOsc->control & 1)
{
pOsc->control |= 1;
break;
}
}

pOsc->accumulator = acc;
}
}
} // end if (oscillators[osc] playing)
} // end for (osc)
} // end for (snum)
}


Expand Down

0 comments on commit 76a4bbe

Please sign in to comment.