Allow sn76496 to output to mono.

This commit is contained in:
iq_132 2015-02-11 04:09:45 +00:00
parent c419f723bf
commit 2c71402654
2 changed files with 126 additions and 0 deletions

View File

@ -177,6 +177,131 @@ void SN76496Update(INT32 Num, INT16* pSoundBuf, INT32 Length)
}
}
void SN76496UpdateToBuffer(INT32 Num, INT16* pSoundBuf, INT32 Length)
{
#if defined FBA_DEBUG
if (!DebugSnd_SN76496Initted) bprintf(PRINT_ERROR, _T("SN76496Update called without init\n"));
if (Num > NumChips) bprintf(PRINT_ERROR, _T("SN76496Update called with invalid chip %x\n"), Num);
#endif
INT32 i;
struct SN76496 *R = Chip0;
if (Num >= MAX_SN76496_CHIPS) return;
if (Num == 1) R = Chip1;
if (Num == 2) R = Chip2;
if (Num == 3) R = Chip3;
if (Num == 4) R = Chip4;
/* If the volume is 0, increase the counter */
for (i = 0;i < 4;i++)
{
if (R->Volume[i] == 0)
{
/* note that I do count += length, NOT count = length + 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] <= Length*STEP) R->Count[i] += Length*STEP;
}
}
while (Length > 0)
{
INT32 Vol[4];
UINT32 Out;
INT32 Left;
/* 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;
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] += 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];
}
if (R->Output[i]) Vol[i] -= R->Count[i];
}
Left = STEP;
do
{
INT32 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 (R->NoiseMode == 1) /* White Noise Mode */
{
if (((R->RNG & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG & R->WhitenoiseTaps) != 0)) /* crappy xor! */
{
R->RNG >>= 1;
R->RNG |= R->FeedbackMask;
}
else
{
R->RNG >>= 1;
}
R->Output[3] = R->WhitenoiseInvert ? !(R->RNG & 1) : R->RNG & 1;
}
else /* Periodic noise mode */
{
if (R->RNG & 1)
{
R->RNG >>= 1;
R->RNG |= R->FeedbackMask;
}
else
{
R->RNG >>= 1;
}
R->Output[3] = 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];
Left -= NextEvent;
} while (Left > 0);
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;
pSoundBuf[0] = BURN_SND_CLIP(((INT32)((Out / STEP) * R->nVolume)));
pSoundBuf++;
Length--;
}
}
void SN76496Write(INT32 Num, INT32 Data)
{
#if defined FBA_DEBUG

View File

@ -1,4 +1,5 @@
void SN76496Update(INT32 Num, INT16* pSoundBuf, INT32 Length);
void SN76496UpdateToBuffer(INT32 Num, INT16* pSoundBuf, INT32 Length); // output mono
void SN76496Write(INT32 Num, INT32 Data);
void SN76489Init(INT32 Num, INT32 Clock, INT32 SignalAdd);
void SN76489AInit(INT32 Num, INT32 Clock, INT32 SignalAdd);