Add FM Interpolation support to burn_ym2612.cpp

This commit is contained in:
Barry Harris 2012-05-16 19:47:20 +00:00
parent fe7fe9d75c
commit 8bb3873836
1 changed files with 167 additions and 2 deletions

View File

@ -15,6 +15,7 @@ static INT16* pYM2612Buffer[2 * MAX_YM2612];
static INT32 nYM2612Position;
static UINT32 nSampleSize;
static INT32 nFractionalPosition;
static INT32 nNumChips = 0;
@ -69,6 +70,156 @@ static void YM2612Render(INT32 nSegmentLength)
// ----------------------------------------------------------------------------
// Update the sound buffer
#define INTERPOLATE_ADD_SOUND_LEFT(route, buffer) \
if ((YM2612RouteDirs[route] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) { \
nLeftSample[0] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2612Volumes[route]); \
nLeftSample[1] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2612Volumes[route]); \
nLeftSample[2] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2612Volumes[route]); \
nLeftSample[3] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2612Volumes[route]); \
}
#define INTERPOLATE_ADD_SOUND_RIGHT(route, buffer) \
if ((YM2612RouteDirs[route] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) { \
nRightSample[0] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2612Volumes[route]); \
nRightSample[1] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2612Volumes[route]); \
nRightSample[2] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2612Volumes[route]); \
nRightSample[3] += (INT32)(pYM2612Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2612Volumes[route]); \
}
static void YM2612UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
{
#if defined FBA_DEBUG
if (!DebugSnd_YM2612Initted) bprintf(PRINT_ERROR, _T("YM2612UpdateResample called without init\n"));
#endif
INT32 nSegmentLength = nSegmentEnd;
INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2612SoundRate / nBurnSoundRate + 1;
if (nSamplesNeeded < nYM2612Position) {
nSamplesNeeded = nYM2612Position;
}
if (nSegmentLength > nBurnSoundLen) {
nSegmentLength = nBurnSoundLen;
}
nSegmentLength <<= 1;
YM2612Render(nSamplesNeeded);
pYM2612Buffer[0] = pBuffer + 0 * 4096 + 4;
pYM2612Buffer[1] = pBuffer + 1 * 4096 + 4;
if (nNumChips > 1) {
pYM2612Buffer[2] = pBuffer + 2 * 4096 + 4;
pYM2612Buffer[3] = pBuffer + 3 * 4096 + 4;
}
for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
INT32 nLeftSample[4] = {0, 0, 0, 0};
INT32 nRightSample[4] = {0, 0, 0, 0};
INT32 nTotalLeftSample, nTotalRightSample;
/*if ((YM2612RouteDirs[BURN_SND_YM2612_YM2612_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample[0] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 3] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[1] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 2] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[2] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 1] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[3] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 0] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
}
if ((YM2612RouteDirs[BURN_SND_YM2612_YM2612_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample[0] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 3] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[1] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 2] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[2] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 1] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[3] += (INT32)(pYM2612Buffer[0][(nFractionalPosition >> 16) - 0] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_1]);
}
if ((YM2612RouteDirs[BURN_SND_YM2612_YM2612_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample[0] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 3] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[1] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 2] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[2] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 1] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[3] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 0] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
}
if ((YM2612RouteDirs[BURN_SND_YM2612_YM2612_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample[0] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 3] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[1] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 2] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[2] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 1] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[3] += (INT32)(pYM2612Buffer[1][(nFractionalPosition >> 16) - 0] * YM2612Volumes[BURN_SND_YM2612_YM2612_ROUTE_2]);
}
if (nNumChips > 1) {
if ((YM2612RouteDirs[2 + BURN_SND_YM2612_YM2612_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample[0] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 3] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[1] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 2] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[2] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 1] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nLeftSample[3] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 0] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
}
if ((YM2612RouteDirs[2 + BURN_SND_YM2612_YM2612_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample[0] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 3] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[1] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 2] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[2] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 1] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
nRightSample[3] += (INT32)(pYM2612Buffer[2][(nFractionalPosition >> 16) - 0] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_1]);
}
if ((YM2612RouteDirs[2 + BURN_SND_YM2612_YM2612_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample[0] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 3] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[1] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 2] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[2] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 1] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nLeftSample[3] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 0] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
}
if ((YM2612RouteDirs[2 + BURN_SND_YM2612_YM2612_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample[0] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 3] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[1] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 2] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[2] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 1] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
nRightSample[3] += (INT32)(pYM2612Buffer[3][(nFractionalPosition >> 16) - 0] * YM2612Volumes[2 + BURN_SND_YM2612_YM2612_ROUTE_2]);
}
}*/
INTERPOLATE_ADD_SOUND_LEFT (BURN_SND_YM2612_YM2612_ROUTE_1, 0)
INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2612_YM2612_ROUTE_1, 0)
INTERPOLATE_ADD_SOUND_LEFT (BURN_SND_YM2612_YM2612_ROUTE_2, 1)
INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2612_YM2612_ROUTE_2, 1)
if (nNumChips > 1) {
INTERPOLATE_ADD_SOUND_LEFT (2 + BURN_SND_YM2612_YM2612_ROUTE_1, 2)
INTERPOLATE_ADD_SOUND_RIGHT (2 + BURN_SND_YM2612_YM2612_ROUTE_1, 2)
INTERPOLATE_ADD_SOUND_LEFT (2 + BURN_SND_YM2612_YM2612_ROUTE_2, 3)
INTERPOLATE_ADD_SOUND_RIGHT (2 + BURN_SND_YM2612_YM2612_ROUTE_2, 3)
}
nTotalLeftSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3]);
nTotalRightSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3]);
nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
if (bYM2612AddSignal) {
pSoundBuf[i + 0] += nTotalLeftSample;
pSoundBuf[i + 1] += nTotalRightSample;
} else {
pSoundBuf[i + 0] = nTotalLeftSample;
pSoundBuf[i + 1] = nTotalRightSample;
}
}
if (nSegmentEnd >= nBurnSoundLen) {
INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
for (INT32 i = -4; i < nExtraSamples; i++) {
pYM2612Buffer[0][i] = pYM2612Buffer[0][(nFractionalPosition >> 16) + i];
pYM2612Buffer[1][i] = pYM2612Buffer[1][(nFractionalPosition >> 16) + i];
if (nNumChips > 1) {
pYM2612Buffer[2][i] = pYM2612Buffer[2][(nFractionalPosition >> 16) + i];
pYM2612Buffer[3][i] = pYM2612Buffer[3][(nFractionalPosition >> 16) + i];
}
}
nFractionalPosition &= 0xFFFF;
nYM2612Position = nExtraSamples;
dTime += 100.0 / nBurnFPS;
}
}
static void YM2612UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd)
{
#if defined FBA_DEBUG
@ -230,8 +381,22 @@ INT32 BurnYM2612Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback
BurnYM2612StreamCallback = StreamCallback;
nBurnYM2612SoundRate = nBurnSoundRate;
BurnYM2612Update = YM2612UpdateNormal;
if (nFMInterpolation == 3) {
// Set YM2612 core samplerate to match the hardware
nBurnYM2612SoundRate = nClockFrequency / 144;
// Bring YM2612 core samplerate within usable range
while (nBurnYM2612SoundRate > nBurnSoundRate * 3) {
nBurnYM2612SoundRate >>= 1;
}
BurnYM2612Update = YM2612UpdateResample;
nSampleSize = (UINT32)nBurnYM2612SoundRate * (1 << 16) / nBurnSoundRate;
} else {
nBurnYM2612SoundRate = nBurnSoundRate;
BurnYM2612Update = YM2612UpdateNormal;
}
YM2612Init(num, nClockFrequency, nBurnYM2612SoundRate, &BurnOPNTimerCallback, IRQCallback);