core, revisit Pico sound handling
authorkub <derkub@gmail.com>
Sat, 20 Jan 2024 16:23:44 +0000 (17:23 +0100)
committerkub <derkub@gmail.com>
Sat, 20 Jan 2024 16:23:44 +0000 (17:23 +0100)
pico/pico_int.h
pico/sound/sn76496.c
pico/sound/sound.c

index cbf61e4..52734c6 100644 (file)
@@ -475,6 +475,7 @@ struct PicoSound
   unsigned int fm_pos;                  // last FM position in Q20\r
   unsigned int psg_pos;                 // last PSG position in Q16\r
   unsigned int ym2413_pos;              // last YM2413 position\r
+  unsigned int pcm_pos;                 // last PCM position in Q16\r
   unsigned int fm_fir_mul, fm_fir_div;  // ratio for FM resampling FIR\r
 };\r
 \r
@@ -975,6 +976,7 @@ PICO_INTERNAL void PsndDoDAC(int cycle_to);
 PICO_INTERNAL void PsndDoPSG(int cyc_to);\r
 PICO_INTERNAL void PsndDoYM2413(int cyc_to);\r
 PICO_INTERNAL void PsndDoFM(int cyc_to);\r
+PICO_INTERNAL void PsndDoPCM(int cyc_to);\r
 PICO_INTERNAL void PsndClear(void);\r
 PICO_INTERNAL void PsndGetSamples(int y);\r
 PICO_INTERNAL void PsndGetSamplesMS(int y);\r
index cb38311..3bb5cf7 100644 (file)
@@ -208,10 +208,9 @@ void SN76496Update(short *buffer, int length, int stereo)
 \r
                if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;\r
 \r
-               if ((out /= STEP)) // will be optimized to shift; max 0x4800 = 18432\r
-                       *buffer += out;\r
-               if(stereo) buffer+=2; // only left for stereo, to be mixed to right later\r
-               else buffer++;\r
+               out /= STEP; // will be optimized to shift; max 0x4800 = 18432\r
+               *buffer++ += out;\r
+               if (stereo) *buffer++ += out;\r
 \r
                length--;\r
        }\r
index c31c2cf..5d7fac6 100644 (file)
@@ -269,9 +269,6 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to)
   if (len <= 0)\r
     return;\r
 \r
-  if (!PicoIn.sndOut)\r
-    return;\r
-\r
   // fill buffer, applying a rather weak order 1 bessel IIR on the way\r
   // y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain)\r
   // 1 sample delay for correct IIR filtering over audio frame boundaries\r
@@ -307,7 +304,7 @@ PICO_INTERNAL void PsndDoPSG(int cyc_to)
 \r
   if (len <= 0)\r
     return;\r
-  if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG))\r
+  if (!(PicoIn.opt & POPT_EN_PSG))\r
     return;\r
 \r
   if (PicoIn.opt & POPT_EN_STEREO) {\r
@@ -337,7 +334,7 @@ PICO_INTERNAL void PsndDoSMSFM(int cyc_to)
 \r
   if (len <= 0)\r
     return;\r
-  if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413))\r
+  if (!(PicoIn.opt & POPT_EN_YM2413))\r
     return;\r
 \r
   if (PicoIn.opt & POPT_EN_STEREO) {\r
@@ -382,6 +379,32 @@ PICO_INTERNAL void PsndDoFM(int cyc_to)
     PsndFMUpdate(PsndBuffer + pos, len, stereo, 1);\r
 }\r
 \r
+PICO_INTERNAL void PsndDoPCM(int cyc_to)\r
+{\r
+  int pos, len;\r
+  int stereo = 0;\r
+\r
+  // nothing to do if sound is off\r
+  if (!PicoIn.sndOut) return;\r
+\r
+  // Q20, number of samples since last call\r
+  len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.pcm_pos;\r
+\r
+  // update position and calculate buffer offset and length\r
+  pos = (Pico.snd.pcm_pos+0x80000) >> 20;\r
+  Pico.snd.pcm_pos += len;\r
+  len = ((Pico.snd.pcm_pos+0x80000) >> 20) - pos;\r
+  if (len <= 0)\r
+    return;\r
+\r
+  // fill buffer\r
+  if (PicoIn.opt & POPT_EN_STEREO) {\r
+    stereo = 1;\r
+    pos <<= 1;\r
+  }\r
+  PicoPicoPCMUpdate(PicoIn.sndOut + pos, len, stereo);\r
+}\r
+\r
 // cdda\r
 static void cdda_raw_update(s32 *buffer, int length, int stereo)\r
 {\r
@@ -434,7 +457,7 @@ PICO_INTERNAL void PsndClear(void)
   if (Pico.snd.len_e_add) len++;\r
 \r
   // drop pos remainder to avoid rounding errors (not entirely correct though)\r
-  Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = 0;\r
+  Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = Pico.snd.pcm_pos = 0;\r
   if (!PicoIn.sndOut) return;\r
 \r
   if (PicoIn.opt & POPT_EN_STEREO)\r
@@ -457,6 +480,7 @@ static int PsndRender(int offset, int length)
   int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20);\r
   int daclen = ((Pico.snd.dac_pos+0x80000) >> 20);\r
   int psglen = ((Pico.snd.psg_pos+0x80000) >> 20);\r
+  int pcmlen = ((Pico.snd.pcm_pos+0x80000) >> 20);\r
 \r
   buf32 = PsndBuffer+(offset<<stereo);\r
 \r
@@ -472,8 +496,8 @@ static int PsndRender(int offset, int length)
 \r
   if (PicoIn.AHW & PAHW_PICO) {\r
     // always need to render sound for interrupts\r
-    s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (offset<<stereo) : NULL;\r
-    PicoPicoPCMUpdate(buf16, length-offset, stereo);\r
+    s16 *buf16 = PicoIn.sndOut ? PicoIn.sndOut + (pcmlen<<stereo) : NULL;\r
+    PicoPicoPCMUpdate(buf16, length-pcmlen, stereo);\r
     return length;\r
   }\r
 \r