Trashed the old pre-accurate-clocking STEP based sample averaging scheme from sn76489 and friends, vastly simplifying the code. Made the output bipolar rather than only above the 0 line.
Added missing statement to the get_safe_token function for the recently added SN94624
This commit is contained in:
parent
8be9626ae2
commit
6371d8dc1c
@ -65,8 +65,7 @@
|
||||
#include "sn76496.h"
|
||||
|
||||
|
||||
#define MAX_OUTPUT 0x7fff
|
||||
#define STEP 0x10000
|
||||
#define MAX_OUTPUT 0x3fff
|
||||
#define NOISEMODE (R->Register[6]&4)?1:0
|
||||
|
||||
|
||||
@ -99,6 +98,7 @@ INLINE sn76496_state *get_safe_token(const device_config *device)
|
||||
sound_get_type(device) == SOUND_SN76489 ||
|
||||
sound_get_type(device) == SOUND_SN76489A ||
|
||||
sound_get_type(device) == SOUND_SN76494 ||
|
||||
sound_get_type(device) == SOUND_SN94624 ||
|
||||
sound_get_type(device) == SOUND_GAMEGEAR ||
|
||||
sound_get_type(device) == SOUND_SMSIII);
|
||||
return (sn76496_state *)device->token;
|
||||
@ -148,8 +148,7 @@ WRITE8_DEVICE_HANDLER( sn76496_w )
|
||||
case 2: /* tone 1 : frequency */
|
||||
case 4: /* tone 2 : frequency */
|
||||
if ((data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4);
|
||||
R->Period[c] = STEP * R->Register[r];
|
||||
if (R->Period[c] == 0) R->Period[c] = STEP;
|
||||
R->Period[c] = R->Register[r];
|
||||
if (r == 4)
|
||||
{
|
||||
/* update noise shift frequency */
|
||||
@ -169,7 +168,7 @@ WRITE8_DEVICE_HANDLER( sn76496_w )
|
||||
if ((data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f);
|
||||
n = R->Register[6];
|
||||
/* N/512,N/1024,N/2048,Tone #3 output */
|
||||
R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (STEP << (5+(n&3)));
|
||||
R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (1 << (5+(n&3)));
|
||||
/* Reset noise shifter */
|
||||
R->RNG = R->FeedbackMask;
|
||||
R->OldNoise = 0;
|
||||
@ -180,8 +179,6 @@ WRITE8_DEVICE_HANDLER( sn76496_w )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static STREAM_UPDATE( SN76496Update )
|
||||
{
|
||||
int i;
|
||||
@ -189,113 +186,64 @@ static STREAM_UPDATE( SN76496Update )
|
||||
stream_sample_t *buffer = outputs[0];
|
||||
|
||||
|
||||
/* If the volume is 0, increase the counter; this is more or less
|
||||
a speedup hack for when silence is to be output */
|
||||
for (i = 0;i < 4;i++)
|
||||
{
|
||||
if (R->Volume[i] == 0)
|
||||
{
|
||||
/* note that I do count += samples, NOT count = samples + 1.
|
||||
You might think it's the same since the volume is 0, but doing
|
||||
the latter could cause interferencies when the program is
|
||||
rapidly modulating the volume. */
|
||||
if (R->Count[i] <= samples*STEP) R->Count[i] += samples*STEP;
|
||||
}
|
||||
}
|
||||
|
||||
while (samples > 0)
|
||||
{
|
||||
int vol[4];
|
||||
unsigned int out;
|
||||
int left;
|
||||
// clock chip once
|
||||
INT16 out;
|
||||
|
||||
/* decrement Cycles to READY by one */
|
||||
if (R->CyclestoREADY >0) R->CyclestoREADY--;
|
||||
|
||||
/* vol[] keeps track of how long each square wave stays */
|
||||
/* in the 1 position during the sample period. */
|
||||
vol[0] = vol[1] = vol[2] = vol[3] = 0;
|
||||
|
||||
// handle channels 0,1,2
|
||||
for (i = 0;i < 3;i++)
|
||||
{
|
||||
if (R->Output[i]) vol[i] += R->Count[i];
|
||||
R->Count[i] -= STEP;
|
||||
/* Period[i] is the half period of the square wave. Here, in each
|
||||
loop I add Period[i] twice, so that at the end of the loop the
|
||||
square wave is in the same status (0 or 1) it was at the start.
|
||||
vol[i] is also incremented by Period[i], since the wave has been 1
|
||||
exactly half of the time, regardless of the initial position.
|
||||
If we exit the loop in the middle, Output[i] has to be inverted
|
||||
and vol[i] incremented only if the exit status of the square
|
||||
wave is 1. */
|
||||
while (R->Count[i] <= 0)
|
||||
R->Count[i]--;
|
||||
if (R->Count[i] < 0)
|
||||
{
|
||||
R->Count[i] += R->Period[i];
|
||||
if (R->Count[i] > 0)
|
||||
{
|
||||
R->Output[i] ^= 1;
|
||||
if (R->Output[i]) vol[i] += R->Period[i];
|
||||
break;
|
||||
}
|
||||
R->Count[i] += R->Period[i];
|
||||
vol[i] += R->Period[i];
|
||||
R->Output[i] ^= 1;
|
||||
R->Count[i] = R->Period[i];
|
||||
}
|
||||
if (R->Output[i]) vol[i] -= R->Count[i];
|
||||
}
|
||||
|
||||
left = STEP;
|
||||
do
|
||||
// handle channel 3
|
||||
R->Count[3]--;
|
||||
if (R->Count[3] <= 0)
|
||||
{
|
||||
int nextevent;
|
||||
|
||||
|
||||
if (R->Count[3] < left) nextevent = R->Count[3];
|
||||
else nextevent = left;
|
||||
|
||||
if (R->Output[3]) vol[3] += R->Count[3];
|
||||
R->Count[3] -= nextevent;
|
||||
if (R->Count[3] <= 0)
|
||||
if (NOISEMODE == 1) /* White Noise Mode */
|
||||
{
|
||||
if (NOISEMODE == 1) /* White Noise Mode */
|
||||
{
|
||||
if ((((R->RNG & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG & R->WhitenoiseTaps) != 0)) ^ R->FeedbackInvert ) /* XOR or XNOR */
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
R->RNG |= R->FeedbackMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
}
|
||||
}
|
||||
else /* Periodic noise mode */
|
||||
if ((((R->RNG & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG & R->WhitenoiseTaps) != 0)) ^ R->FeedbackInvert ) /* XOR or XNOR */
|
||||
{
|
||||
if (R->RNG & 1)
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
R->RNG |= R->FeedbackMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
}
|
||||
R->RNG >>= 1;
|
||||
R->RNG |= R->FeedbackMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
}
|
||||
R->Output[3] = R->OldNoise;
|
||||
R->OldNoise = R->RNG & 1;
|
||||
R->Count[3] += R->Period[3];
|
||||
if (R->Output[3]) vol[3] += R->Period[3];
|
||||
}
|
||||
if (R->Output[3]) vol[3] -= R->Count[3];
|
||||
else /* Periodic noise mode */
|
||||
{
|
||||
if (R->RNG & 1)
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
R->RNG |= R->FeedbackMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->RNG >>= 1;
|
||||
}
|
||||
}
|
||||
R->Output[3] = R->OldNoise;
|
||||
R->OldNoise = R->RNG & 1;
|
||||
R->Count[3] = R->Period[3];
|
||||
}
|
||||
|
||||
left -= nextevent;
|
||||
} while (left > 0);
|
||||
out = (R->Output[0]?R->Volume[0]:(0-R->Volume[0]))
|
||||
+(R->Output[1]?R->Volume[1]:(0-R->Volume[1]))
|
||||
+(R->Output[2]?R->Volume[2]:(0-R->Volume[2]))
|
||||
+(R->Output[3]?R->Volume[3]:(0-R->Volume[3]));
|
||||
|
||||
out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] +
|
||||
vol[2] * R->Volume[2] + vol[3] * R->Volume[3];
|
||||
|
||||
if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;
|
||||
|
||||
*(buffer++) = out / STEP;
|
||||
*(buffer++) = out;
|
||||
|
||||
samples--;
|
||||
}
|
||||
@ -348,8 +296,7 @@ static int SN76496_init(const device_config *device, sn76496_state *R)
|
||||
|
||||
for (i = 0;i < 4;i++)
|
||||
{
|
||||
R->Output[i] = 0;
|
||||
R->Period[i] = R->Count[i] = STEP;
|
||||
R->Output[i] = R->Period[i] = R->Count[i] = 0;
|
||||
}
|
||||
|
||||
/* Default is SN76489 non-A */
|
||||
|
Loading…
Reference in New Issue
Block a user