Added support to qs_c.cpp for volume and left/right selection for each route. Updated necessary drivers to support. Normalised sound levels removing need for per-game volume shifts when initting.

This commit is contained in:
Barry Harris 2012-05-22 13:31:35 +00:00
parent 1b693b0a2a
commit 257aaa3e90
4 changed files with 118 additions and 124 deletions

View File

@ -279,7 +279,11 @@ void DrawFnInit();
INT32 CpsDraw();
INT32 CpsRedraw();
#define BURN_SND_QSND_OUTPUT_1 0
#define BURN_SND_QSND_OUTPUT_2 1
INT32 QsndInit();
void QsndSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
void QsndExit();
void QsndReset();
void QsndNewFrame();
@ -293,7 +297,8 @@ INT32 QsndZExit();
INT32 QsndZScan(INT32 nAction);
// qs_c.cpp
INT32 QscInit(INT32 nRate, INT32 nVolumeShift);
INT32 QscInit(INT32 nRate);
void QscSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
void QscReset();
void QscExit();
INT32 QscScan(INT32 nAction);

View File

@ -143,6 +143,8 @@ INT32 CpsRunInit()
if (QsndInit()) {
return 1;
}
QsndSetRoute(BURN_SND_QSND_OUTPUT_1, 1.00, BURN_SND_ROUTE_LEFT);
QsndSetRoute(BURN_SND_QSND_OUTPUT_2, 1.00, BURN_SND_ROUTE_RIGHT);
}
if (Cps == 2 || PangEEP || Cps1Qs == 1 || CpsBootlegEEPROM) EEPROMReset();

View File

@ -13,7 +13,6 @@ static INT32 qsndTimerOver(INT32, INT32)
INT32 QsndInit()
{
INT32 nVolumeShift;
INT32 nRate;
// Init QSound z80
@ -36,55 +35,16 @@ INT32 QsndInit()
nRate = 11025;
}
nVolumeShift = 0;
// These games are too soft at normal volumes
if (strncmp(BurnDrvGetTextA(DRV_NAME), "csclub", 6) == 0) {
nVolumeShift = -1;
}
// These games are loud at normal volumes (no clipping)
if (strncmp(BurnDrvGetTextA(DRV_NAME), "1944", 4) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "dimaho", 6) == 0 ||
strcmp( BurnDrvGetTextA(DRV_NAME), "gmahou" ) == 0)
{
nVolumeShift = 1;
}
// These games are too loud at normal volumes (no clipping)
if (strncmp(BurnDrvGetTextA(DRV_NAME), "sgemf", 5) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "progear", 7) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "pzloop2", 7) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "ringdest", 8) == 0 ||
strcmp( BurnDrvGetTextA(DRV_NAME), "ringdstd" ) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "smbomb", 6) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "pfght", 5) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "mpang", 5) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "sfa2", 4) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "sfz2", 4) == 0)
{
nVolumeShift = 1;
}
// These games are too loud at normal volumes (no clipping)
if (strncmp(BurnDrvGetTextA(DRV_NAME), "gigawing", 8) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "spf2", 4) == 0)
{
nVolumeShift = 2;
}
// These games are too loud at normal volumes (clipping)
if (strncmp(BurnDrvGetTextA(DRV_NAME), "19xx", 4) == 0 ||
strncmp(BurnDrvGetTextA(DRV_NAME), "ddtod", 5) == 0)
{
nVolumeShift = 2;
}
QscInit(nRate, nVolumeShift); // Init QSound chip
QscInit(nRate); // Init QSound chip
return 0;
}
void QsndSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
{
QscSetRoute(nIndex, nVolume, nRouteDir);
}
void QsndReset()
{
ZetOpen(0);

View File

@ -8,7 +8,6 @@ static const INT32 nQscClock = 4000000;
static const INT32 nQscClockDivider = 166;
static INT32 nQscRate = 0;
static INT32 nQscVolumeShift;
static INT32 Tams = -1;
static INT32* Qs_s = NULL;
@ -40,6 +39,9 @@ static struct QChan QChan[16];
static INT32 PanningVolumes[33];
static double QsndGain[2];
static INT32 QsndOutputDir[2];
static void MapBank(struct QChan* pc)
{
UINT32 nBank;
@ -104,21 +106,30 @@ void QscExit()
Tams = -1;
}
INT32 QscInit(INT32 nRate, INT32 nVolumeShift)
INT32 QscInit(INT32 nRate)
{
nQscRate = nRate;
nQscVolumeShift = 10 + nVolumeShift;
for (INT32 i = 0; i < 33; i++) {
PanningVolumes[i] = (INT32)((256.0 / sqrt(32.0)) * sqrt((double)i));
}
QsndGain[BURN_SND_QSND_OUTPUT_1] = 1.00;
QsndGain[BURN_SND_QSND_OUTPUT_2] = 1.00;
QsndOutputDir[BURN_SND_QSND_OUTPUT_1] = BURN_SND_ROUTE_LEFT;
QsndOutputDir[BURN_SND_QSND_OUTPUT_2] = BURN_SND_ROUTE_RIGHT;
QscReset();
return 0;
}
void QscSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
{
QsndGain[nIndex] = nVolume;
QsndOutputDir[nIndex] = nRouteDir;
}
INT32 QscScan(INT32 nAction)
{
SCAN_VAR(QChan);
@ -275,8 +286,8 @@ INT32 QscUpdate(INT32 nEnd)
// If the channel is playing, add the samples to the buffer
if (QChan[c].bKey) {
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift;
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift;
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> 8;
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> 8;
INT32* pTemp = Qs_s;
INT32 i = nLen;
INT32 s, p;
@ -315,8 +326,8 @@ INT32 QscUpdate(INT32 nEnd)
s = QChan[c].PlayBank[p] * (1 << 6) + ((QChan[c].nPos) & ((1 << 12) - 1)) * (QChan[c].nEndBuffer[0] - QChan[c].PlayBank[p]) / (1 << 6);
// Add to the sound currently in the buffer
pTemp[0] += s * VolL;
pTemp[1] += s * VolR;
pTemp[0] += (s * VolL) >> 3;
pTemp[1] += (s * VolR) >> 3;
pTemp += 2;
@ -325,12 +336,27 @@ INT32 QscUpdate(INT32 nEnd)
}
}
if (bBurnUseMMX) {
#if defined BUILD_X86_ASM
BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
#endif
} else {
BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
INT16 *pDest = pBurnSoundOut + (nPos << 1);
INT32 *pSrc = Qs_s;
for (INT32 i = 0; i < nLen; i++) {
INT32 nLeftSample = 0, nRightSample = 0;
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)((pSrc[(i << 1) + 0] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_1]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)((pSrc[(i << 1) + 0] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_1]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)((pSrc[(i << 1) + 1] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_2]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)((pSrc[(i << 1) + 1] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_2]);
}
pDest[(i << 1) + 0] = BURN_SND_CLIP(nLeftSample);
pDest[(i << 1) + 1] = BURN_SND_CLIP(nRightSample);
}
nPos = nEnd;
@ -342,8 +368,8 @@ INT32 QscUpdate(INT32 nEnd)
// If the channel is playing, add the samples to the buffer
if (QChan[c].bKey) {
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift;
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift;
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> 11;
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> 11;
INT32* pTemp = Qs_s;
INT32 i = nLen;
@ -372,77 +398,78 @@ INT32 QscUpdate(INT32 nEnd)
}
}
if (bBurnUseMMX && i > 0) {
#if defined BUILD_X86_ASM
QChan[c].bKey = (UINT8)ChannelMix_QS_A(pTemp, i,
(char*)QChan[c].PlayBank,
QChan[c].nEnd,
&(QChan[c].nPos),
VolL,
VolR,
QChan[c].nLoop,
QChan[c].nAdvance,
(char*)QChan[c].nEndBuffer);
#endif
} else {
while (i > 0) {
INT32 s, p;
while (i > 0) {
INT32 s, p;
// Check for end of sample
if (QChan[c].nPos >= (QChan[c].nEnd - 0x3000)) {
if (QChan[c].nPos < QChan[c].nEnd) {
INT32 nIndex = 4 - ((QChan[c].nEnd - QChan[c].nPos) >> 12);
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
QChan[c].nEndBuffer[nIndex + 0],
QChan[c].nEndBuffer[nIndex + 1],
QChan[c].nEndBuffer[nIndex + 2],
QChan[c].nEndBuffer[nIndex + 3],
256);
} else {
if (QChan[c].nLoop) { // Loop sample
if (QChan[c].nLoop <= 0x1000) { // Don't play, but leave bKey on
QChan[c].nPos = QChan[c].nEnd - 0x1000;
break;
}
QChan[c].nPos -= QChan[c].nLoop;
continue;
} else {
QChan[c].bKey = 0; // Stop playing
// Check for end of sample
if (QChan[c].nPos >= (QChan[c].nEnd - 0x3000)) {
if (QChan[c].nPos < QChan[c].nEnd) {
INT32 nIndex = 4 - ((QChan[c].nEnd - QChan[c].nPos) >> 12);
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
QChan[c].nEndBuffer[nIndex + 0],
QChan[c].nEndBuffer[nIndex + 1],
QChan[c].nEndBuffer[nIndex + 2],
QChan[c].nEndBuffer[nIndex + 3],
256);
} else {
if (QChan[c].nLoop) { // Loop sample
if (QChan[c].nLoop <= 0x1000) { // Don't play, but leave bKey on
QChan[c].nPos = QChan[c].nEnd - 0x1000;
break;
}
QChan[c].nPos -= QChan[c].nLoop;
continue;
} else {
QChan[c].bKey = 0; // Stop playing
break;
}
} else {
p = (QChan[c].nPos >> 12) & 0xFFFF;
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
QChan[c].PlayBank[p + 0],
QChan[c].PlayBank[p + 1],
QChan[c].PlayBank[p + 2],
QChan[c].PlayBank[p + 3],
256);
}
// Add to the sound currently in the buffer
pTemp[0] += s * VolL;
pTemp[1] += s * VolR;
pTemp += 2;
QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch
i--;
} else {
p = (QChan[c].nPos >> 12) & 0xFFFF;
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
QChan[c].PlayBank[p + 0],
QChan[c].PlayBank[p + 1],
QChan[c].PlayBank[p + 2],
QChan[c].PlayBank[p + 3],
256);
}
// Add to the sound currently in the buffer
pTemp[0] += s * VolL;
pTemp[1] += s * VolR;
pTemp += 2;
QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch
i--;
}
}
}
if (bBurnUseMMX) {
#if defined BUILD_X86_ASM
BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
#endif
} else {
BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
INT16 *pDest = pBurnSoundOut + (nPos << 1);
INT32 *pSrc = Qs_s;
for (INT32 i = 0; i < nLen; i++) {
INT32 nLeftSample = 0, nRightSample = 0;
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)((pSrc[(i << 1) + 0] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_1]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)((pSrc[(i << 1) + 0] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_1]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
nLeftSample += (INT32)((pSrc[(i << 1) + 1] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_2]);
}
if ((QsndOutputDir[BURN_SND_QSND_OUTPUT_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
nRightSample += (INT32)((pSrc[(i << 1) + 1] >> 8) * QsndGain[BURN_SND_QSND_OUTPUT_2]);
}
pDest[(i << 1) + 0] = BURN_SND_CLIP(nLeftSample);
pDest[(i << 1) + 1] = BURN_SND_CLIP(nRightSample);
}
nPos = nEnd;
nPos = nEnd;
return 0;
}