mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 11:41:48 +01:00
[Core/Sound] fixed PSG noise channel bug
This commit is contained in:
parent
3a0ec7e895
commit
31906b20cf
Binary file not shown.
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB |
Binary file not shown.
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 3.4 MiB |
152
core/sound/psg.c
152
core/sound/psg.c
@ -151,7 +151,6 @@ int psg_context_save(uint8 *state)
|
|||||||
save_param(psg.freqInc,sizeof(psg.freqInc));
|
save_param(psg.freqInc,sizeof(psg.freqInc));
|
||||||
save_param(psg.freqCounter,sizeof(psg.freqCounter));
|
save_param(psg.freqCounter,sizeof(psg.freqCounter));
|
||||||
save_param(psg.polarity,sizeof(psg.polarity));
|
save_param(psg.polarity,sizeof(psg.polarity));
|
||||||
save_param(psg.chanDelta,sizeof(psg.chanDelta));
|
|
||||||
save_param(psg.chanOut,sizeof(psg.chanOut));
|
save_param(psg.chanOut,sizeof(psg.chanOut));
|
||||||
|
|
||||||
return bufferptr;
|
return bufferptr;
|
||||||
@ -159,34 +158,29 @@ int psg_context_save(uint8 *state)
|
|||||||
|
|
||||||
int psg_context_load(uint8 *state)
|
int psg_context_load(uint8 *state)
|
||||||
{
|
{
|
||||||
int chanOut[4][2], delta[2];
|
int delta[2];
|
||||||
int i, bufferptr = 0;
|
int i, bufferptr = 0;
|
||||||
|
|
||||||
/* get current tone channels output */
|
/* initialize delta with current noise channel output */
|
||||||
|
if (psg.noiseShiftValue & 1)
|
||||||
|
{
|
||||||
|
delta[0] = -psg.chanOut[3][0];
|
||||||
|
delta[1] = -psg.chanOut[3][1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delta[0] = 0;
|
||||||
|
delta[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add current tone channels output */
|
||||||
for (i=0; i<3; i++)
|
for (i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
if (psg.polarity[i] > 0)
|
if (psg.polarity[i] > 0)
|
||||||
{
|
{
|
||||||
chanOut[i][0] = psg.chanOut[i][0];
|
delta[0] -= psg.chanOut[i][0];
|
||||||
chanOut[i][1] = psg.chanOut[i][1];
|
delta[1] -= psg.chanOut[i][1];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
chanOut[i][0] = 0;
|
|
||||||
chanOut[i][1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get current noise channel output */
|
|
||||||
if (psg.noiseShiftValue & 1)
|
|
||||||
{
|
|
||||||
chanOut[3][0] = psg.chanOut[3][0];
|
|
||||||
chanOut[3][1] = psg.chanOut[3][1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chanOut[3][0] = 0;
|
|
||||||
chanOut[3][1] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_param(&psg.clocks,sizeof(psg.clocks));
|
load_param(&psg.clocks,sizeof(psg.clocks));
|
||||||
@ -196,46 +190,22 @@ int psg_context_load(uint8 *state)
|
|||||||
load_param(psg.freqInc,sizeof(psg.freqInc));
|
load_param(psg.freqInc,sizeof(psg.freqInc));
|
||||||
load_param(psg.freqCounter,sizeof(psg.freqCounter));
|
load_param(psg.freqCounter,sizeof(psg.freqCounter));
|
||||||
load_param(psg.polarity,sizeof(psg.polarity));
|
load_param(psg.polarity,sizeof(psg.polarity));
|
||||||
load_param(psg.chanDelta,sizeof(psg.chanDelta));
|
|
||||||
load_param(psg.chanOut,sizeof(psg.chanOut));
|
load_param(psg.chanOut,sizeof(psg.chanOut));
|
||||||
|
|
||||||
/* apply any pending channel volume variation */
|
/* add noise channel output variation */
|
||||||
for (i=0; i<4; i++)
|
|
||||||
{
|
|
||||||
psg.chanOut[i][0] += psg.chanDelta[i][0];
|
|
||||||
psg.chanOut[i][1] += psg.chanDelta[i][1];
|
|
||||||
psg.chanDelta[i][0] = 0;
|
|
||||||
psg.chanDelta[i][1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate noise channel output variations */
|
|
||||||
if (psg.noiseShiftValue & 1)
|
if (psg.noiseShiftValue & 1)
|
||||||
{
|
{
|
||||||
/* channel output is high */
|
delta[0] += psg.chanOut[3][0];
|
||||||
delta[0] = psg.chanOut[3][0] - chanOut[3][0];
|
delta[1] += psg.chanOut[3][1];
|
||||||
delta[1] = psg.chanOut[3][0] - chanOut[3][1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low */
|
|
||||||
delta[0] = -chanOut[3][0];
|
|
||||||
delta[1] = -chanOut[3][1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add tone channels output variations */
|
/* add tone channels output variation */
|
||||||
for (i=0; i<3; i++)
|
for (i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
if (psg.polarity[i] > 0)
|
if (psg.polarity[i] > 0)
|
||||||
{
|
{
|
||||||
/* channel output is high */
|
delta[0] += psg.chanOut[i][0];
|
||||||
delta[0] += (psg.chanOut[i][0] - chanOut[i][0]);
|
delta[1] += psg.chanOut[i][1];
|
||||||
delta[1] += (psg.chanOut[i][0] - chanOut[i][1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low */
|
|
||||||
delta[0] -= chanOut[i][0];
|
|
||||||
delta[1] -= chanOut[i][1];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +287,7 @@ void psg_write(unsigned int clocks, unsigned int data)
|
|||||||
|
|
||||||
case 6: /* Noise control */
|
case 6: /* Noise control */
|
||||||
{
|
{
|
||||||
/* noise signal generator frequency (----?xxx) */
|
/* noise signal generator frequency (-----?xx) */
|
||||||
int noiseFreq = (data & 0x03);
|
int noiseFreq = (data & 0x03);
|
||||||
|
|
||||||
if (noiseFreq == 0x03)
|
if (noiseFreq == 0x03)
|
||||||
@ -336,8 +306,8 @@ void psg_write(unsigned int clocks, unsigned int data)
|
|||||||
if (psg.noiseShiftValue & 1)
|
if (psg.noiseShiftValue & 1)
|
||||||
{
|
{
|
||||||
/* high to low transition will be applied at next internal cycle update */
|
/* high to low transition will be applied at next internal cycle update */
|
||||||
psg.chanDelta[3][0] = -psg.chanOut[3][0];
|
psg.chanDelta[3][0] -= psg.chanOut[3][0];
|
||||||
psg.chanDelta[3][1] = -psg.chanOut[3][1];
|
psg.chanDelta[3][1] -= psg.chanOut[3][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset noise shift register value (noise channel output is forced low) */
|
/* reset noise shift register value (noise channel output is forced low) */
|
||||||
@ -348,48 +318,56 @@ void psg_write(unsigned int clocks, unsigned int data)
|
|||||||
|
|
||||||
case 7: /* Noise channel attenuation */
|
case 7: /* Noise channel attenuation */
|
||||||
{
|
{
|
||||||
|
int chanOut[2];
|
||||||
|
|
||||||
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
|
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
|
||||||
data = chanVolume[data & 0x0f];
|
data = chanVolume[data & 0x0f];
|
||||||
|
|
||||||
|
/* channel pre-amplification */
|
||||||
|
chanOut[0] = (data * psg.chanAmp[3][0]) / 100;
|
||||||
|
chanOut[1] = (data * psg.chanAmp[3][1]) / 100;
|
||||||
|
|
||||||
/* check noise shift register output */
|
/* check noise shift register output */
|
||||||
if (psg.noiseShiftValue & 1)
|
if (psg.noiseShiftValue & 1)
|
||||||
{
|
{
|
||||||
/* channel output is high, volume variation will be applied at next internal cycle update */
|
/* channel output is high, volume variation will be applied at next internal cycle update */
|
||||||
psg.chanDelta[3][0] = ((data * psg.chanAmp[3][0]) / 100) - psg.chanOut[3][0];
|
psg.chanDelta[3][0] += (chanOut[0] - psg.chanOut[3][0]);
|
||||||
psg.chanDelta[3][1] = ((data * psg.chanAmp[3][1]) / 100) - psg.chanOut[3][1];
|
psg.chanDelta[3][1] += (chanOut[1] - psg.chanOut[3][1]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low, volume variation will be applied at next transition */
|
|
||||||
psg.chanOut[3][0] = (data * psg.chanAmp[3][0]) / 100;
|
|
||||||
psg.chanOut[3][1] = (data * psg.chanAmp[3][1]) / 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update channel volume */
|
||||||
|
psg.chanOut[3][0] = chanOut[0];
|
||||||
|
psg.chanOut[3][1] = chanOut[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: /* Tone channels attenuation */
|
default: /* Tone channels attenuation */
|
||||||
{
|
{
|
||||||
|
int chanOut[2];
|
||||||
|
|
||||||
/* channel number (0-2) */
|
/* channel number (0-2) */
|
||||||
int i = index >> 1;
|
int i = index >> 1;
|
||||||
|
|
||||||
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
|
/* convert 4-bit attenuation value (----xxxx) to 16-bit volume value */
|
||||||
data = chanVolume[data & 0x0f];
|
data = chanVolume[data & 0x0f];
|
||||||
|
|
||||||
|
/* channel pre-amplification */
|
||||||
|
chanOut[0] = (data * psg.chanAmp[i][0]) / 100;
|
||||||
|
chanOut[1] = (data * psg.chanAmp[i][1]) / 100;
|
||||||
|
|
||||||
/* check tone generator polarity */
|
/* check tone generator polarity */
|
||||||
if (psg.polarity[i] > 0)
|
if (psg.polarity[i] > 0)
|
||||||
{
|
{
|
||||||
/* channel output is high, volume variation will be applied at next internal cycle update */
|
/* channel output is high, volume variation will be applied at next internal cycle update */
|
||||||
psg.chanDelta[i][0] = ((data * psg.chanAmp[i][0]) / 100) - psg.chanOut[i][0];
|
psg.chanDelta[i][0] += (chanOut[0] - psg.chanOut[i][0]);
|
||||||
psg.chanDelta[i][1] = ((data * psg.chanAmp[i][1]) / 100) - psg.chanOut[i][1];
|
psg.chanDelta[i][1] += (chanOut[1] - psg.chanOut[i][1]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low, volume variation will be applied at next transition */
|
|
||||||
psg.chanOut[i][0] = (data * psg.chanAmp[i][0]) / 100;
|
|
||||||
psg.chanOut[i][1] = (data * psg.chanAmp[i][1]) / 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update channel volume */
|
||||||
|
psg.chanOut[i][0] = chanOut[0];
|
||||||
|
psg.chanOut[i][1] = chanOut[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,14 +406,8 @@ void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning)
|
|||||||
if (psg.polarity[i] > 0)
|
if (psg.polarity[i] > 0)
|
||||||
{
|
{
|
||||||
/* channel output is high, volume variation will be applied at next internal cycle update */
|
/* channel output is high, volume variation will be applied at next internal cycle update */
|
||||||
psg.chanDelta[i][0] = ((volume * psg.chanAmp[i][0]) / 100) - psg.chanOut[i][0];
|
psg.chanDelta[i][0] += (((volume * psg.chanAmp[i][0]) / 100) - psg.chanOut[i][0]);
|
||||||
psg.chanDelta[i][1] = ((volume * psg.chanAmp[i][1]) / 100) - psg.chanOut[i][1];
|
psg.chanDelta[i][1] += (((volume * psg.chanAmp[i][1]) / 100) - psg.chanOut[i][1]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low, volume variation will be applied at next transition*/
|
|
||||||
psg.chanOut[i][0] = (volume * psg.chanAmp[i][0]) / 100;
|
|
||||||
psg.chanOut[i][1] = (volume * psg.chanAmp[i][1]) / 100;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,16 +418,14 @@ void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning)
|
|||||||
if (psg.noiseShiftValue & 1)
|
if (psg.noiseShiftValue & 1)
|
||||||
{
|
{
|
||||||
/* channel output is high, volume variation will be applied at next internal cycle update */
|
/* channel output is high, volume variation will be applied at next internal cycle update */
|
||||||
psg.chanDelta[3][0] = ((volume * psg.chanAmp[3][0]) / 100) - psg.chanOut[3][0];
|
psg.chanDelta[3][0] += (((volume * psg.chanAmp[3][0]) / 100) - psg.chanOut[3][0]);
|
||||||
psg.chanDelta[3][1] = ((volume * psg.chanAmp[3][1]) / 100) - psg.chanOut[3][1];
|
psg.chanDelta[3][1] += (((volume * psg.chanAmp[3][1]) / 100) - psg.chanOut[3][1]);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* channel output is low, volume variation will be applied at next transition */
|
|
||||||
psg.chanOut[3][0] = (volume * psg.chanAmp[3][0]) / 100;
|
|
||||||
psg.chanOut[3][1] = (volume * psg.chanAmp[3][1]) / 100;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update channel volume */
|
||||||
|
psg.chanOut[i][0] = (volume * psg.chanAmp[i][0]) / 100;
|
||||||
|
psg.chanOut[i][1] = (volume * psg.chanAmp[i][1]) / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,10 +471,6 @@ static void psg_update(unsigned int clocks)
|
|||||||
blip_add_delta_fast(snd.blips[0], psg.clocks, psg.chanDelta[i][0], psg.chanDelta[i][1]);
|
blip_add_delta_fast(snd.blips[0], psg.clocks, psg.chanDelta[i][0], psg.chanDelta[i][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update channel volume */
|
|
||||||
psg.chanOut[i][0] += psg.chanDelta[i][0];
|
|
||||||
psg.chanOut[i][1] += psg.chanDelta[i][1];
|
|
||||||
|
|
||||||
/* clear pending channel volume variations */
|
/* clear pending channel volume variations */
|
||||||
psg.chanDelta[i][0] = 0;
|
psg.chanDelta[i][0] = 0;
|
||||||
psg.chanDelta[i][1] = 0;
|
psg.chanDelta[i][1] = 0;
|
||||||
@ -558,14 +524,14 @@ static void psg_update(unsigned int clocks)
|
|||||||
/* current shift register output */
|
/* current shift register output */
|
||||||
int shiftOutput = shiftValue & 0x01;
|
int shiftOutput = shiftValue & 0x01;
|
||||||
|
|
||||||
/* White noise (----1xxx) */
|
/* White noise (-----1xx) */
|
||||||
if (psg.regs[6] & 0x04)
|
if (psg.regs[6] & 0x04)
|
||||||
{
|
{
|
||||||
/* shift and apply XOR feedback network */
|
/* shift and apply XOR feedback network */
|
||||||
shiftValue = (shiftValue >> 1) | (noiseFeedback[shiftValue & psg.noiseBitMask] << psg.noiseShiftWidth);
|
shiftValue = (shiftValue >> 1) | (noiseFeedback[shiftValue & psg.noiseBitMask] << psg.noiseShiftWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Periodic noise (----0xxx) */
|
/* Periodic noise (-----0xx) */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* shift and feedback current output */
|
/* shift and feedback current output */
|
||||||
|
Loading…
Reference in New Issue
Block a user