summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2023-05-25 22:46:05 -0400
committer arbee <rb6502@users.noreply.github.com>2023-05-25 22:46:05 -0400
commitfe33ad0eac5382b0bd6ff1df02687844d6d6b157 (patch)
tree82ec6d6d268ee84e9a80d79866c2ca7afe0ed18e /src
parent66baabf26b19858ab7b740e7fd36524e45c01427 (diff)
sound/es5503.cpp: Support sync and AM modes and the last oscillator volume bug. [R. Belmont]
Diffstat (limited to 'src')
-rw-r--r--src/devices/sound/es5503.cpp69
1 files changed, 60 insertions, 9 deletions
diff --git a/src/devices/sound/es5503.cpp b/src/devices/sound/es5503.cpp
index 08b12f3512c..70117baaca2 100644
--- a/src/devices/sound/es5503.cpp
+++ b/src/devices/sound/es5503.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*
- ES5503 - Ensoniq ES5503 "DOC" emulator v2.1.3
+ ES5503 - Ensoniq ES5503 "DOC" emulator v2.3
By R. Belmont.
Copyright R. Belmont.
@@ -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
@@ -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 "emu.h"
@@ -93,9 +94,26 @@ void es5503_device::halt_osc(int onum, int type, uint32_t *accumulator, int ress
{
ES5503Osc *pOsc = &oscillators[onum];
ES5503Osc *pPartner = &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 (!(oscillators[onum - 1].control & 1))
+ {
+ 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))
{
@@ -154,13 +172,14 @@ void es5503_device::sound_stream_update(sound_stream &stream, std::vector<read_s
{
uint32_t wtptr = pOsc->wavetblpointer & wavemasks[pOsc->wavetblsize], altram;
uint32_t acc = pOsc->accumulator;
- uint16_t wtsize = pOsc->wtsize - 1;
+ const uint16_t wtsize = pOsc->wtsize - 1;
uint8_t ctrl = pOsc->control;
- uint16_t freq = pOsc->freq;
+ const uint16_t freq = pOsc->freq;
int16_t vol = pOsc->vol;
int8_t data = -128;
- int resshift = resshifts[pOsc->resolution] - pOsc->wavetblsize;
- uint32_t sizemask = accmasks[pOsc->wavetblsize];
+ const int resshift = resshifts[pOsc->resolution] - pOsc->wavetblsize;
+ const uint32_t sizemask = accmasks[pOsc->wavetblsize];
+ const int mode = (pOsc->control>>1) & 3;
mixp = &m_mix_buffer[0] + chan;
for (snum = 0; snum < samples; snum++)
@@ -180,7 +199,39 @@ void es5503_device::sound_stream_update(sound_stream &stream, std::vector<read_s
}
else
{
- *mixp += data * vol;
+ if (mode != MODE_SYNCAM)
+ {
+ *mixp += data * vol;
+ if (chan == (output_channels - 1))
+ {
+ *mixp += data * vol;
+ *mixp += data * 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 (!(oscillators[osc + 1].control & 1))
+ {
+ oscillators[osc + 1].vol = data ^ 0x80;
+ }
+ }
+ }
+ else // hard sync, both oscillators play?
+ {
+ *mixp += data * vol;
+ if (chan == (output_channels - 1))
+ {
+ *mixp += data * vol;
+ *mixp += data * vol;
+ }
+ }
+ }
mixp += output_channels;
if (altram >= wtsize)