core, revisit Pico sound handling

This commit is contained in:
kub 2024-01-20 17:23:44 +01:00
parent ba2b97dc24
commit e348af76ec
3 changed files with 37 additions and 12 deletions

View file

@ -475,6 +475,7 @@ struct PicoSound
unsigned int fm_pos; // last FM position in Q20 unsigned int fm_pos; // last FM position in Q20
unsigned int psg_pos; // last PSG position in Q16 unsigned int psg_pos; // last PSG position in Q16
unsigned int ym2413_pos; // last YM2413 position unsigned int ym2413_pos; // last YM2413 position
unsigned int pcm_pos; // last PCM position in Q16
unsigned int fm_fir_mul, fm_fir_div; // ratio for FM resampling FIR unsigned int fm_fir_mul, fm_fir_div; // ratio for FM resampling FIR
}; };
@ -975,6 +976,7 @@ PICO_INTERNAL void PsndDoDAC(int cycle_to);
PICO_INTERNAL void PsndDoPSG(int cyc_to); PICO_INTERNAL void PsndDoPSG(int cyc_to);
PICO_INTERNAL void PsndDoYM2413(int cyc_to); PICO_INTERNAL void PsndDoYM2413(int cyc_to);
PICO_INTERNAL void PsndDoFM(int cyc_to); PICO_INTERNAL void PsndDoFM(int cyc_to);
PICO_INTERNAL void PsndDoPCM(int cyc_to);
PICO_INTERNAL void PsndClear(void); PICO_INTERNAL void PsndClear(void);
PICO_INTERNAL void PsndGetSamples(int y); PICO_INTERNAL void PsndGetSamples(int y);
PICO_INTERNAL void PsndGetSamplesMS(int y); PICO_INTERNAL void PsndGetSamplesMS(int y);

View file

@ -208,10 +208,9 @@ void SN76496Update(short *buffer, int length, int stereo)
if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;
if ((out /= STEP)) // will be optimized to shift; max 0x4800 = 18432 out /= STEP; // will be optimized to shift; max 0x4800 = 18432
*buffer += out; *buffer++ += out;
if(stereo) buffer+=2; // only left for stereo, to be mixed to right later if (stereo) *buffer++ += out;
else buffer++;
length--; length--;
} }

View file

@ -269,9 +269,6 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to)
if (len <= 0) if (len <= 0)
return; return;
if (!PicoIn.sndOut)
return;
// fill buffer, applying a rather weak order 1 bessel IIR on the way // fill buffer, applying a rather weak order 1 bessel IIR on the way
// y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain) // y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain)
// 1 sample delay for correct IIR filtering over audio frame boundaries // 1 sample delay for correct IIR filtering over audio frame boundaries
@ -307,7 +304,7 @@ PICO_INTERNAL void PsndDoPSG(int cyc_to)
if (len <= 0) if (len <= 0)
return; return;
if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG)) if (!(PicoIn.opt & POPT_EN_PSG))
return; return;
if (PicoIn.opt & POPT_EN_STEREO) { if (PicoIn.opt & POPT_EN_STEREO) {
@ -337,7 +334,7 @@ PICO_INTERNAL void PsndDoSMSFM(int cyc_to)
if (len <= 0) if (len <= 0)
return; return;
if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413)) if (!(PicoIn.opt & POPT_EN_YM2413))
return; return;
if (PicoIn.opt & POPT_EN_STEREO) { if (PicoIn.opt & POPT_EN_STEREO) {
@ -382,6 +379,32 @@ PICO_INTERNAL void PsndDoFM(int cyc_to)
PsndFMUpdate(PsndBuffer + pos, len, stereo, 1); PsndFMUpdate(PsndBuffer + pos, len, stereo, 1);
} }
PICO_INTERNAL void PsndDoPCM(int cyc_to)
{
int pos, len;
int stereo = 0;
// nothing to do if sound is off
if (!PicoIn.sndOut) return;
// Q20, number of samples since last call
len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.pcm_pos;
// update position and calculate buffer offset and length
pos = (Pico.snd.pcm_pos+0x80000) >> 20;
Pico.snd.pcm_pos += len;
len = ((Pico.snd.pcm_pos+0x80000) >> 20) - pos;
if (len <= 0)
return;
// fill buffer
if (PicoIn.opt & POPT_EN_STEREO) {
stereo = 1;
pos <<= 1;
}
PicoPicoPCMUpdate(PicoIn.sndOut + pos, len, stereo);
}
// cdda // cdda
static void cdda_raw_update(s32 *buffer, int length, int stereo) static void cdda_raw_update(s32 *buffer, int length, int stereo)
{ {
@ -434,7 +457,7 @@ PICO_INTERNAL void PsndClear(void)
if (Pico.snd.len_e_add) len++; if (Pico.snd.len_e_add) len++;
// drop pos remainder to avoid rounding errors (not entirely correct though) // drop pos remainder to avoid rounding errors (not entirely correct though)
Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = 0; Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = Pico.snd.pcm_pos = 0;
if (!PicoIn.sndOut) return; if (!PicoIn.sndOut) return;
if (PicoIn.opt & POPT_EN_STEREO) if (PicoIn.opt & POPT_EN_STEREO)
@ -457,6 +480,7 @@ static int PsndRender(int offset, int length)
int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20); int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20);
int daclen = ((Pico.snd.dac_pos+0x80000) >> 20); int daclen = ((Pico.snd.dac_pos+0x80000) >> 20);
int psglen = ((Pico.snd.psg_pos+0x80000) >> 20); int psglen = ((Pico.snd.psg_pos+0x80000) >> 20);
int pcmlen = ((Pico.snd.pcm_pos+0x80000) >> 20);
buf32 = PsndBuffer+(offset<<stereo); buf32 = PsndBuffer+(offset<<stereo);
@ -472,8 +496,8 @@ static int PsndRender(int offset, int length)
if (PicoIn.AHW & PAHW_PICO) { if (PicoIn.AHW & PAHW_PICO) {
// always need to render sound for interrupts // always need to render sound for interrupts
s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (offset<<stereo) : NULL; s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (pcmlen<<stereo) : NULL;
PicoPicoPCMUpdate(buf16, length-offset, stereo); PicoPicoPCMUpdate(buf16, length-pcmlen, stereo);
return length; return length;
} }