improved FM & PSG chip synchronization when using resampling (fixes buffers overflow issues and problems with DAC timings that occured with previous "fix")

This commit is contained in:
ekeeke31 2010-02-15 14:02:37 +00:00
parent cea89b4531
commit 27d3fc5328

View File

@ -33,9 +33,6 @@ static unsigned int fm_cycles_count;
/* Run FM chip for required M-cycles */ /* Run FM chip for required M-cycles */
static inline void fm_update(unsigned int cycles) static inline void fm_update(unsigned int cycles)
{ {
/* convert to 21.11 fixed point */
cycles <<= 11;
if (cycles > fm_cycles_count) if (cycles > fm_cycles_count)
{ {
/* period to run */ /* period to run */
@ -76,9 +73,6 @@ static inline void fm_update(unsigned int cycles)
/* Run PSG chip for required M-cycles */ /* Run PSG chip for required M-cycles */
static inline void psg_update(unsigned int cycles) static inline void psg_update(unsigned int cycles)
{ {
/* convert to 21.11 fixed point */
cycles <<= 11;
if (cycles > psg_cycles_count) if (cycles > psg_cycles_count)
{ {
/* period to run */ /* period to run */
@ -145,7 +139,7 @@ void sound_init(void)
if (config.hq_fm) if (config.hq_fm)
{ {
fm_cycles_ratio = 144 * 7 * (1 << 11); fm_cycles_ratio = 144 * 7 * (1 << 11);
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0)); Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0), config.rolloff);
} }
#ifdef LOGSOUND #ifdef LOGSOUND
@ -166,10 +160,11 @@ void sound_reset(void)
/* End of frame update, return the number of samples run so far. */ /* End of frame update, return the number of samples run so far. */
int sound_update(unsigned int cycles) int sound_update(unsigned int cycles)
{ {
/* run PSG chip until end of frame */ /* run PSG & FM chips until end of frame */
cycles <<= 11;
psg_update(cycles); psg_update(cycles);
fm_update(cycles);
/* number of available samples */
int size = snd.psg.pos - snd.psg.buffer; int size = snd.psg.pos - snd.psg.buffer;
#ifdef LOGSOUND #ifdef LOGSOUND
@ -179,30 +174,30 @@ int sound_update(unsigned int cycles)
/* FM resampling */ /* FM resampling */
if (config.hq_fm) if (config.hq_fm)
{ {
/* get remaining FM samples */ /* get available FM samples */
int remain = Fir_Resampler_input_needed(size); int avail = Fir_Resampler_avail();
if (remain > 0) /* resynchronize FM & PSG chips */
if (avail < size)
{ {
/* resynchronize FM & PSG chips */ /* FM chip is late for one sample */
YM2612Update(Fir_Resampler_buffer(), remain); YM2612Update(Fir_Resampler_buffer(), 1);
Fir_Resampler_write(remain << 1); Fir_Resampler_write(2);
fm_cycles_count = psg_cycles_count; fm_cycles_count += fm_cycles_ratio;
}
else
{
/* FM chip is ahead */
fm_cycles_count += (avail - size) * psg_cycles_ratio;
} }
#ifdef LOGSOUND
error("%d FM samples available (%d needed)\n",Fir_Resampler_written() >> 1, remain);
#endif
} }
else
{
/* run FM chip until end of frame */
fm_update(cycles);
#ifdef LOGSOUND #ifdef LOGSOUND
if (config.hq_fm)
error("%d FM samples (%d) available\n",Fir_Resampler_avail(), Fir_Resampler_written() >> 1);
else
error("%d FM samples available\n",(snd.fm.pos - snd.fm.buffer)>>1); error("%d FM samples available\n",(snd.fm.pos - snd.fm.buffer)>>1);
#endif #endif
}
#ifdef LOGSOUND #ifdef LOGSOUND
error("%lu PSG cycles run\n",psg_cycles_count); error("%lu PSG cycles run\n",psg_cycles_count);
@ -210,8 +205,8 @@ int sound_update(unsigned int cycles)
#endif #endif
/* adjust PSG & FM cycle counts for next frame */ /* adjust PSG & FM cycle counts for next frame */
psg_cycles_count -= (cycles << 11); psg_cycles_count -= cycles;
fm_cycles_count -= (cycles << 11); fm_cycles_count -= cycles;
#ifdef LOGSOUND #ifdef LOGSOUND
error("%lu PSG cycles left\n",psg_cycles_count); error("%lu PSG cycles left\n",psg_cycles_count);
@ -224,7 +219,7 @@ int sound_update(unsigned int cycles)
/* Reset FM chip */ /* Reset FM chip */
void fm_reset(unsigned int cycles) void fm_reset(unsigned int cycles)
{ {
fm_update(cycles); fm_update(cycles << 11);
YM2612ResetChip(); YM2612ResetChip();
} }
@ -232,20 +227,20 @@ void fm_reset(unsigned int cycles)
void fm_write(unsigned int cycles, unsigned int address, unsigned int data) void fm_write(unsigned int cycles, unsigned int address, unsigned int data)
{ {
if (address & 1) if (address & 1)
fm_update(cycles); fm_update(cycles << 11);
YM2612Write(address, data); YM2612Write(address, data);
} }
/* Read FM status */ /* Read FM status */
unsigned int fm_read(unsigned int cycles, unsigned int address) unsigned int fm_read(unsigned int cycles, unsigned int address)
{ {
fm_update(cycles); fm_update(cycles << 11);
return YM2612Read(); return YM2612Read();
} }
/* Write PSG chip */ /* Write PSG chip */
void psg_write(unsigned int cycles, unsigned int data) void psg_write(unsigned int cycles, unsigned int data)
{ {
psg_update(cycles); psg_update(cycles << 11);
SN76489_Write(data); SN76489_Write(data);
} }