From 1d0d4c80add0ab9398a5ead6b35286e5d5d82407 Mon Sep 17 00:00:00 2001 From: Barry Harris <44396066+barry65536@users.noreply.github.com> Date: Thu, 17 May 2012 13:02:00 +0000 Subject: [PATCH] Added a new function to ay8910.c, AY8910Render() which supports separate route volume and direction. Updated d_1942.cpp as a test. --- src/burn/drv/pre90s/d_1942.cpp | 36 +-------- src/burn/snd/ay8910.c | 130 +++++++++++++++++++++++++++++++++ src/burn/snd/ay8910.h | 12 +++ 3 files changed, 146 insertions(+), 32 deletions(-) diff --git a/src/burn/drv/pre90s/d_1942.cpp b/src/burn/drv/pre90s/d_1942.cpp index cda429885..e4f697cf7 100644 --- a/src/burn/drv/pre90s/d_1942.cpp +++ b/src/burn/drv/pre90s/d_1942.cpp @@ -590,6 +590,8 @@ static void MachineInit() AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910SetAllRoutes(0, 0.25, BURN_SND_ROUTE_BOTH); + AY8910SetAllRoutes(1, 0.25, BURN_SND_ROUTE_BOTH); GenericTilesInit(); @@ -949,49 +951,19 @@ static INT32 DrvFrame() // Render Sound Segment if (pBurnSoundOut) { - INT32 nSample; INT32 nSegmentLength = nBurnSoundLen / nInterleave; INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); - AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); - AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); - for (INT32 n = 0; n < nSegmentLength; n++) { - nSample = pAY8910Buffer[0][n] >> 2; - nSample += pAY8910Buffer[1][n] >> 2; - nSample += pAY8910Buffer[2][n] >> 2; - nSample += pAY8910Buffer[3][n] >> 2; - nSample += pAY8910Buffer[4][n] >> 2; - nSample += pAY8910Buffer[5][n] >> 2; - - nSample = BURN_SND_CLIP(nSample); - - pSoundBuf[(n << 1) + 0] = nSample; - pSoundBuf[(n << 1) + 1] = nSample; - } + AY8910Render(&pAY8910Buffer[0], pSoundBuf, nSegmentLength, 0); nSoundBufferPos += nSegmentLength; } } // Make sure the buffer is entirely filled. if (pBurnSoundOut) { - INT32 nSample; INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); if (nSegmentLength) { - AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); - AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); - for (INT32 n = 0; n < nSegmentLength; n++) { - nSample = pAY8910Buffer[0][n] >> 2; - nSample += pAY8910Buffer[1][n] >> 2; - nSample += pAY8910Buffer[2][n] >> 2; - nSample += pAY8910Buffer[3][n] >> 2; - nSample += pAY8910Buffer[4][n] >> 2; - nSample += pAY8910Buffer[5][n] >> 2; - - nSample = BURN_SND_CLIP(nSample); - - pSoundBuf[(n << 1) + 0] = nSample; - pSoundBuf[(n << 1) + 1] = nSample; - } + AY8910Render(&pAY8910Buffer[0], pSoundBuf, nSegmentLength, 0); } } diff --git a/src/burn/snd/ay8910.c b/src/burn/snd/ay8910.c index ffa41f199..602ff29ae 100644 --- a/src/burn/snd/ay8910.c +++ b/src/burn/snd/ay8910.c @@ -28,11 +28,19 @@ #define STEP 0x8000 +#define BURN_SND_CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) +#define BURN_SND_ROUTE_LEFT 1 +#define BURN_SND_ROUTE_RIGHT 2 +#define BURN_SND_ROUTE_BOTH (BURN_SND_ROUTE_LEFT | BURN_SND_ROUTE_RIGHT) + static void (*AYStreamUpdate)(void); INT32 ay8910_index_ym = 0; static INT32 num = 0, ym_num = 0; +static double AY8910Volumes[3 * 6]; +static INT32 AY8910RouteDirs[3 * 6]; + struct AY8910 { INT32 Channel; @@ -737,6 +745,14 @@ INT32 AY8910Init(INT32 chip, INT32 clock, INT32 sample_rate, AY8910_set_clock(chip, clock); build_mixer_table(chip); + + // default routes + AY8910Volumes[(chip * 3) + BURN_SND_AY8910_ROUTE_1] = 1.00; + AY8910Volumes[(chip * 3) + BURN_SND_AY8910_ROUTE_2] = 1.00; + AY8910Volumes[(chip * 3) + BURN_SND_AY8910_ROUTE_3] = 1.00; + AY8910RouteDirs[(chip * 3) + BURN_SND_AY8910_ROUTE_1] = BURN_SND_ROUTE_BOTH; + AY8910RouteDirs[(chip * 3) + BURN_SND_AY8910_ROUTE_2] = BURN_SND_ROUTE_BOTH; + AY8910RouteDirs[(chip * 3) + BURN_SND_AY8910_ROUTE_3] = BURN_SND_ROUTE_BOTH; AY8910Reset(chip); @@ -817,3 +833,117 @@ INT32 AY8910Scan(INT32 nAction, INT32* pnMin) return 0; } +#define AY8910_ADD_SOUND(route, output) \ + if ((AY8910RouteDirs[route] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) { \ + nLeftSample += (INT32)(output[n] * AY8910Volumes[route]); \ + } \ + if ((AY8910RouteDirs[route] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) { \ + nRightSample += (INT32)(output[n] * AY8910Volumes[route]); \ + } + +void AY8910Render(INT16** buffer, INT16* dest, INT32 length, INT32 bAddSignal) +{ +#if defined FBA_DEBUG +#ifdef __GNUC__ + if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910Render called without init\n")); + if (num >= 7) bprintf(PRINT_ERROR, _T("AY8910Render called with invalid number of chips %i (max is 6)\n"), num); +#endif +#endif + + INT32 i; + for (i = 0; i < num; i++) { + AY8910Update(i, buffer + (i * 3), length); + } + + INT16 *buf0 = buffer[0]; + INT16 *buf1 = buffer[1]; + INT16 *buf2 = buffer[2]; + INT16 *buf3, *buf4, *buf5, *buf6, *buf7, *buf8, *buf9, *buf10, *buf11, *buf12, *buf13, *buf14, *buf15, *buf16, *buf17; + if (num >= 2) { + buf3 = buffer[3]; + buf4 = buffer[4]; + buf5 = buffer[5]; + } + if (num >= 3) { + buf6 = buffer[6]; + buf7 = buffer[7]; + buf8 = buffer[8]; + } + if (num >= 4) { + buf9 = buffer[9]; + buf10 = buffer[10]; + buf11 = buffer[11]; + } + if (num >= 5) { + buf12 = buffer[12]; + buf13 = buffer[13]; + buf14 = buffer[14]; + } + if (num >= 6) { + buf15 = buffer[15]; + buf16 = buffer[16]; + buf17 = buffer[17]; + } + + INT32 n; + for (n = 0; n < length; n++) { + INT32 nLeftSample = 0, nRightSample = 0; + + AY8910_ADD_SOUND(BURN_SND_AY8910_ROUTE_1, buf0) + AY8910_ADD_SOUND(BURN_SND_AY8910_ROUTE_2, buf1) + AY8910_ADD_SOUND(BURN_SND_AY8910_ROUTE_3, buf2) + + if (num >= 2) { + AY8910_ADD_SOUND(3 + BURN_SND_AY8910_ROUTE_1, buf3) + AY8910_ADD_SOUND(3 + BURN_SND_AY8910_ROUTE_2, buf4) + AY8910_ADD_SOUND(3 + BURN_SND_AY8910_ROUTE_3, buf5) + } + + if (num >= 3) { + AY8910_ADD_SOUND(6 + BURN_SND_AY8910_ROUTE_1, buf6) + AY8910_ADD_SOUND(6 + BURN_SND_AY8910_ROUTE_2, buf7) + AY8910_ADD_SOUND(6 + BURN_SND_AY8910_ROUTE_3, buf8) + } + + if (num >= 4) { + AY8910_ADD_SOUND(9 + BURN_SND_AY8910_ROUTE_1, buf9) + AY8910_ADD_SOUND(9 + BURN_SND_AY8910_ROUTE_2, buf10) + AY8910_ADD_SOUND(9 + BURN_SND_AY8910_ROUTE_3, buf11) + } + + if (num >= 5) { + AY8910_ADD_SOUND(12 + BURN_SND_AY8910_ROUTE_1, buf12) + AY8910_ADD_SOUND(12 + BURN_SND_AY8910_ROUTE_2, buf13) + AY8910_ADD_SOUND(12 + BURN_SND_AY8910_ROUTE_3, buf14) + } + + if (num >= 6) { + AY8910_ADD_SOUND(15 + BURN_SND_AY8910_ROUTE_1, buf15) + AY8910_ADD_SOUND(15 + BURN_SND_AY8910_ROUTE_2, buf16) + AY8910_ADD_SOUND(15 + BURN_SND_AY8910_ROUTE_3, buf17) + } + + nLeftSample = BURN_SND_CLIP(nLeftSample); + nRightSample = BURN_SND_CLIP(nRightSample); + + if (bAddSignal) { + dest[(n << 1) + 0] += nLeftSample; + dest[(n << 1) + 1] += nRightSample; + } else { + dest[(n << 1) + 0] = nLeftSample; + dest[(n << 1) + 1] = nRightSample; + } + } +} + +void AY8910SetRoute(INT32 chip, INT32 nIndex, double nVolume, INT32 nRouteDir) +{ +#if defined FBA_DEBUG + if (!DebugSnd_AY8910Initted) bprintf(PRINT_ERROR, _T("AY8910SetRoute called without init\n")); + if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("AY8910SetRoute called with invalid index %i\n"), nIndex); + if (chip >= num) bprintf(PRINT_ERROR, _T("AY8910SetRoute called with invalid chip %i\n"), chip); +#endif + + AY8910Volumes[(chip * 3) + nIndex] = nVolume; + AY8910RouteDirs[(chip * 3) + nIndex] = nRouteDir; +} diff --git a/src/burn/snd/ay8910.h b/src/burn/snd/ay8910.h index 41de410ba..ca548f029 100644 --- a/src/burn/snd/ay8910.h +++ b/src/burn/snd/ay8910.h @@ -41,5 +41,17 @@ INT32 AY8910Scan(INT32 nAction, INT32* pnMin); INT32 AY8910SetPorts(INT32 chip, read8_handler portAread, read8_handler portBread, write8_handler portAwrite, write8_handler portBwrite); + +void AY8910Render(INT16** buffer, INT16* dest, INT32 length, INT32 bAddSignal); +void AY8910SetRoute(INT32 chip, INT32 nIndex, double nVolume, INT32 nRouteDir); + +#define BURN_SND_AY8910_ROUTE_1 0 +#define BURN_SND_AY8910_ROUTE_2 1 +#define BURN_SND_AY8910_ROUTE_3 2 + +#define AY8910SetAllRoutes(i, v, d) \ + AY8910SetRoute(i, BURN_SND_AY8910_ROUTE_1, v, d); \ + AY8910SetRoute(i, BURN_SND_AY8910_ROUTE_2, v, d); \ + AY8910SetRoute(i, BURN_SND_AY8910_ROUTE_3, v, d); #endif