📄 infones_papu.cpp
字号:
ApuC2b = ApuEventQueue[event].data;
break;
case 2:
ApuC2c = ApuEventQueue[event].data;
ApuC2Freq = ( ( ( (WORD)ApuC2d & 0x07 ) << 8 ) + ApuC2c );
ApuC2Atl = ApuAtl[ ( ApuC2d & 0xf8 ) >> 3 ];
if ( ApuC2Freq )
{
ApuC2Skip = ApuPulseMagic / ApuC2Freq;
} else {
ApuC2Skip = 0;
}
break;
case 3:
ApuC2d = ApuEventQueue[event].data;
ApuC2Freq = ( ( ( (WORD)ApuC2d & 0x07 ) << 8 ) + ApuC2c );
ApuC2Atl = ApuAtl[ ( ApuC2d & 0xf8 ) >> 3 ];
if ( ApuC2Freq )
{
ApuC2Skip = ApuPulseMagic / ApuC2Freq;
} else {
ApuC2Skip = 0;
}
break;
}
}
else if ( ApuEventQueue[event].type == APUET_W_CTRL )
{
ctrl = ApuEventQueue[event].data;
}
event++;
}
/* Envelope decay at a rate of ( Envelope Delay + 1 ) / 240 secs */
ApuC2EnvPhase -= 4;
while ( ApuC2EnvPhase < 0 )
{
ApuC2EnvPhase += ApuC2EnvDelay;
if ( ApuC2Hold )
{
ApuC2EnvVol = ( ApuC2EnvVol + 1 ) & 0x0f;
}
else if ( ApuC2EnvVol < 0x0f )
{
ApuC2EnvVol++;
}
}
/*
* TODO: using a table of max frequencies is not technically
* clean, but it is fast and (or should be) accurate
*/
if ( ApuC2Freq < 8 || ( !ApuC2SweepIncDec && ApuC2Freq > ApuC2FreqLimit ) )
{
wave_buffers[1][i] = 0;
break;
}
/* Frequency sweeping at a rate of ( Sweep Delay + 1) / 120 secs */
if ( ApuC2SweepOn && ApuC2SweepShifts )
{
ApuC2SweepPhase -= 2; /* 120/60 */
while ( ApuC2SweepPhase < 0)
{
ApuC2SweepPhase += ApuC2SweepDelay;
if ( ApuC2SweepIncDec ) /* ramp up */
{
/* Rectangular #1 */
ApuC2Freq -= ( ApuC2Freq >> ApuC2SweepShifts );
} else {
/* ramp down */
ApuC2Freq += ( ApuC2Freq >> ApuC2SweepShifts );
}
}
ApuC2Skip = ApuPulseMagic / ApuC2Freq;
}
/* Wave Rendering */
if ( ( ctrl & 0x01 ) && ( ApuC2Atl || ApuC2Hold ) )
{
ApuC2Index += ApuC2Skip;
ApuC2Index &= 0x1fffffff;
if ( ApuC2Env )
{
wave_buffers[1][i] = ApuC2Wave[ApuC2Index >> 24] * ( ApuC2Vol + ApuC2EnvVol );
} else {
wave_buffers[1][i] = ApuC2Wave[ApuC2Index >> 24] * ApuC2Vol;
}
} else {
wave_buffers[1][i] = 0;
}
}
if ( ApuC2Atl )
{
ApuC2Atl--;
}
ApuCtrlNew = ctrl;
}
/*===================================================================*/
/* */
/* InfoNES_pApuWave3() : Rendering Triangle Wave */
/* */
/*===================================================================*/
void InfoNES_pApuWave3( void )
{
int cycles = 0;
int event = 0;
BYTE ctrl = ApuCtrl;
/* note: 41 CPU cycles occur between increments of i */
for ( unsigned int i = 0; i < ApuSamplesPerSync; i++)
{
cycles += ApuCyclesPerSample;
while (( event < cur_event ) && ( ApuEventQueue[event].time < cycles ) )
{
if ( ( ApuEventQueue[event].type & APUET_MASK ) == APUET_C3 )
{
switch ( ApuEventQueue[event].type & 3 )
{
case 0:
ApuC3a = ApuEventQueue[event].data;
ApuC3Llc = ApuC3LinearLength;
break;
case 1:
ApuC3b = ApuEventQueue[event].data;
break;
case 2:
ApuC3c = ApuEventQueue[event].data;
if ( ApuC3Freq )
{
ApuC3Skip = ApuTriangleMagic / ApuC3Freq;
} else {
ApuC3Skip = 0;
}
break;
case 3:
ApuC3d = ApuEventQueue[event].data;
ApuC3Atl = ApuC3LengthCounter;
if ( ApuC3Freq )
{
ApuC3Skip = ApuTriangleMagic / ApuC3Freq;
} else {
ApuC3Skip = 0;
}
}
} else if ( ApuEventQueue[event].type == APUET_W_CTRL )
{
ctrl = ApuEventQueue[event].data;
}
event++;
}
/* Cutting Min Frequency */
if ( ApuC3Freq < 8 )
{
wave_buffers[2][i] = 0;
break;
}
/* Wave Rendering */
if ( ( ctrl & 4 ) && ( ( ApuC3Atl > 0 || ApuC3Holdnote ) && ApuC3Llc > 0 ) )
{
ApuC3Index += ApuC3Skip;
ApuC3Index &= 0x1fffffff;
wave_buffers[2][i] = triangle_50[ ApuC3Index >> 24 ];
} else {
wave_buffers[2][i] = 0;
}
}
/* Counter Control */
if ( ApuC3CounterStarted )
{
if ( ApuC3Atl > 0 && !ApuC3Holdnote )
{
ApuC3Atl--;
}
if ( ApuC3Llc > 0)
{
ApuC3Llc--;
}
} else if ( !ApuC3Holdnote && ApuC3WriteLatency > 0 )
{
if ( --ApuC3WriteLatency == 0 )
{
ApuC3CounterStarted = 0x01;
}
}
ApuCtrlNew = ctrl;
}
/*===================================================================*/
/* */
/* InfoNES_pApuWave4() : Rendering Noise */
/* */
/*===================================================================*/
void InfoNES_pApuWave4(void)
{
int cycles = 0;
int event = 0;
BYTE ctrl = ApuCtrl;
for ( unsigned int i = 0; i < ApuSamplesPerSync; i++ )
{
cycles += ApuCyclesPerSample;
while ((event < cur_event) && (ApuEventQueue[event].time < cycles))
{
if ( ( ApuEventQueue[event].type & APUET_MASK ) == APUET_C4 )
{
switch (ApuEventQueue[event].type & 3) {
case 0:
ApuC4a = ApuEventQueue[event].data;
break;
case 1:
ApuC4b = ApuEventQueue[event].data;
break;
case 2:
ApuC4c = ApuEventQueue[event].data;
if ( ApuC4Small )
{
ApuC4Sr = 0x001f;
} else {
ApuC4Sr = 0x01ff;
}
/* Frequency */
if ( ApuC4Freq )
{
ApuC4Skip = ApuNoiseMagic / ApuC4Freq;
} else {
ApuC4Skip = 0;
}
ApuC4Atl = ApuC4LengthCounter;
break;
case 3:
ApuC4d = ApuEventQueue[event].data;
/* Frequency */
if ( ApuC4Freq )
{
ApuC4Skip = ApuNoiseMagic / ApuC4Freq;
} else {
ApuC4Skip = 0;
}
ApuC4Atl = ApuC4LengthCounter;
}
} else if (ApuEventQueue[event].type == APUET_W_CTRL)
{
ctrl = ApuEventQueue[event].data;
}
event++;
}
/* Envelope decay at a rate of ( Envelope Delay + 1 ) / 240 secs */
ApuC4EnvPhase -= 4;
while ( ApuC4EnvPhase < 0 )
{
ApuC4EnvPhase += ApuC4EnvDelay;
if ( ApuC4Hold )
{
ApuC4EnvVol = ( ApuC4EnvVol + 1 ) & 0x0f;
}
else if ( ApuC4EnvVol < 0x0f )
{
ApuC4EnvVol++;
}
}
/* Wave Rendering */
if ( ctrl & 8 )
{
ApuC4Index += ApuC4Skip;
if (ApuC4Index > 0x1fffffff)
{
if ( ApuC4Small ) /* FIXME: may be wrong */
{
ApuC4Sr |= ((!(ApuC4Sr & 1)) ^ (!(ApuC4Sr & 4))) << 5;
} else {
ApuC4Sr |= ((!(ApuC4Sr & 1)) ^ (!(ApuC4Sr & 16))) << 9;
}
ApuC4Sr >>= 1;
}
ApuC4Index &= 0x1fffffff;
if ( ApuC4Atl && ( ApuC4Sr & 1 ) )
{
if ( !ApuC4Env )
{
wave_buffers[3][i] = ApuC4Vol;
} else {
wave_buffers[3][i] = ApuC4EnvVol ^ 0x0f;
}
} else {
wave_buffers[3][i] = 0;
}
} else {
wave_buffers[3][i] = 0;
}
}
if ( ApuC4Atl && !ApuC4Hold )
{
ApuC4Atl--;
}
ApuCtrlNew = ctrl;
}
/*===================================================================*/
/* */
/* InfoNES_pApuVsync() : Callback Function per Vsync */
/* */
/*===================================================================*/
void InfoNES_pAPUVsync(void)
{
InfoNES_pApuWave1();
InfoNES_pApuWave2();
InfoNES_pApuWave3();
InfoNES_pApuWave4();
ApuCtrl = ApuCtrlNew;
#if 0
{
static FILE *pLog = fopen("log.txt", "wb");
int i;
for(i = 0; i < 735; ++i)
fputc(wave_buffers[0][i]+'0', pLog);
fflush(pLog);
}
#endif
InfoNES_SoundOutput4(ApuSamplesPerSync, wave_buffers[0], wave_buffers[1], wave_buffers[2], wave_buffers[3]);
entertime = g_wPassedClocks;
cur_event = 0;
}
/*===================================================================*/
/* */
/* InfoNES_pApuInit() : Initialize pApu */
/* */
/*===================================================================*/
void InfoNES_pAPUInit(void)
{
/* Sound Hardware Init */
InfoNES_SoundInit();
ApuQuality = pAPU_QUALITY; // 1: 22050, 2: 44100 [samples/sec]
if ( ApuQuality > 0 )
{
if ( ApuQuality > 2 )
{
ApuQuality = 1;
}
else
{
ApuQuality--;
}
ApuPulseMagic = ApuQual[ ApuQuality ].pulse_magic;
ApuTriangleMagic = ApuQual[ ApuQuality ].triangle_magic;
ApuNoiseMagic = ApuQual[ ApuQuality ].noise_magic;
ApuSamplesPerSync = ApuQual[ ApuQuality ].samples_per_sync;
ApuCyclesPerSample = ApuQual[ ApuQuality ].cycles_per_sample;
ApuSampleRate = ApuQual[ ApuQuality ].sample_rate;
InfoNES_SoundOpen( ApuSamplesPerSync, ApuSampleRate );
ApuC1Wave = pulse_50;
ApuC2Wave = pulse_50;
/* Initialize Rectangular Wave's Regs */
ApuC1EnvPhase = 0;
ApuC2EnvPhase = 0;
ApuC4EnvPhase = 0;
ApuC1EnvVol = 0;
ApuC2EnvVol = 0;
ApuC4EnvVol = 0;
ApuC1SweepPhase = 0;
ApuC2SweepPhase = 0;
/* Initialize Triangle Wave's Regs */
ApuC3WriteLatency = 3; /* Magic Number */
ApuC3CounterStarted = NULL;
}
entertime = g_wPassedClocks;
cur_event = 0;
}
/*===================================================================*/
/* */
/* InfoNES_pApuDone() : Finalize pApu */
/* */
/*===================================================================*/
void InfoNES_pAPUDone(void)
{
InfoNES_SoundClose();
}
/*
* End of InfoNES_pAPU.cpp
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -