From: kub <derkub@gmail.com>
Date: Sat, 20 Jan 2024 16:23:44 +0000 (+0100)
Subject: core, revisit Pico sound handling
X-Git-Tag: v2.00~135
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e348af76ec2d0ae83c7178307425d9305ecaa258;p=picodrive.git

core, revisit Pico sound handling
---

diff --git a/pico/pico_int.h b/pico/pico_int.h
index cbf61e43..52734c62 100644
--- a/pico/pico_int.h
+++ b/pico/pico_int.h
@@ -475,6 +475,7 @@ struct PicoSound
   unsigned int fm_pos;                  // last FM position in Q20
   unsigned int psg_pos;                 // last PSG position in Q16
   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
 };
 
@@ -975,6 +976,7 @@ PICO_INTERNAL void PsndDoDAC(int cycle_to);
 PICO_INTERNAL void PsndDoPSG(int cyc_to);
 PICO_INTERNAL void PsndDoYM2413(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 PsndGetSamples(int y);
 PICO_INTERNAL void PsndGetSamplesMS(int y);
diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c
index cb383118..3bb5cf74 100644
--- a/pico/sound/sn76496.c
+++ b/pico/sound/sn76496.c
@@ -208,10 +208,9 @@ void SN76496Update(short *buffer, int length, int stereo)
 
 		if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;
 
-		if ((out /= STEP)) // will be optimized to shift; max 0x4800 = 18432
-			*buffer += out;
-		if(stereo) buffer+=2; // only left for stereo, to be mixed to right later
-		else buffer++;
+		out /= STEP; // will be optimized to shift; max 0x4800 = 18432
+		*buffer++ += out;
+		if (stereo) *buffer++ += out;
 
 		length--;
 	}
diff --git a/pico/sound/sound.c b/pico/sound/sound.c
index c31c2cf4..5d7fac63 100644
--- a/pico/sound/sound.c
+++ b/pico/sound/sound.c
@@ -269,9 +269,6 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to)
   if (len <= 0)
     return;
 
-  if (!PicoIn.sndOut)
-    return;
-
   // 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)
   // 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)
     return;
-  if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG))
+  if (!(PicoIn.opt & POPT_EN_PSG))
     return;
 
   if (PicoIn.opt & POPT_EN_STEREO) {
@@ -337,7 +334,7 @@ PICO_INTERNAL void PsndDoSMSFM(int cyc_to)
 
   if (len <= 0)
     return;
-  if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413))
+  if (!(PicoIn.opt & POPT_EN_YM2413))
     return;
 
   if (PicoIn.opt & POPT_EN_STEREO) {
@@ -382,6 +379,32 @@ PICO_INTERNAL void PsndDoFM(int cyc_to)
     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
 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++;
 
   // 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.opt & POPT_EN_STEREO)
@@ -457,6 +480,7 @@ static int PsndRender(int offset, int length)
   int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20);
   int daclen = ((Pico.snd.dac_pos+0x80000) >> 20);
   int psglen = ((Pico.snd.psg_pos+0x80000) >> 20);
+  int pcmlen = ((Pico.snd.pcm_pos+0x80000) >> 20);
 
   buf32 = PsndBuffer+(offset<<stereo);
 
@@ -472,8 +496,8 @@ static int PsndRender(int offset, int length)
 
   if (PicoIn.AHW & PAHW_PICO) {
     // always need to render sound for interrupts
-    s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (offset<<stereo) : NULL;
-    PicoPicoPCMUpdate(buf16, length-offset, stereo);
+    s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (pcmlen<<stereo) : NULL;
+    PicoPicoPCMUpdate(buf16, length-pcmlen, stereo);
     return length;
   }