From 70aecd15b023843ed010b5853028f2beeaa34e0f Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 24 Apr 2020 19:05:27 +0200 Subject: [PATCH] audio: SN76496 fixes --- pico/memory.c | 2 +- pico/pico_int.h | 2 +- pico/sms.c | 2 +- pico/sound/sn76496.c | 8 +++++++- pico/sound/sound.c | 39 +++++++++++++++++++++++++++++++++------ 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index e1afb4db..c0ba9ffe 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -883,7 +883,7 @@ static void m68k_mem_setup(void) static int get_scanline(int is_from_z80) { if (is_from_z80) { - int mclk_z80 = z80_cyclesDone() * 15; + int mclk_z80 = (z80_cyclesLeft<0 ? Pico.t.z80c_aim : z80_cyclesDone()) * 15; int mclk_line = Pico.t.z80_scanline * 488 * 7; while (mclk_z80 - mclk_line >= 488 * 7) Pico.t.z80_scanline++, mclk_line += 488 * 7; diff --git a/pico/pico_int.h b/pico/pico_int.h index 7539379a..088c7aa5 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -213,7 +213,7 @@ extern struct DrZ80 drZ80; #define z80_cyclesDone() \ (Pico.t.z80c_aim - z80_cyclesLeft) -#define cycles_68k_to_z80(x) ((x) * 3823 >> 13) +#define cycles_68k_to_z80(x) ((x) * 3822 >> 13) // ----------------------- SH2 CPU ----------------------- diff --git a/pico/sms.c b/pico/sms.c index 901f2f55..0f4a48ad 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -152,7 +152,7 @@ static void z80_sms_out(unsigned short a, unsigned char d) case 0x40: case 0x41: - if ((d & 0x90) == 0x90); + if ((d & 0x90) == 0x90) PsndDoPSG(Pico.m.scanline); SN76496Write(d); break; diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index b2127594..4507507c 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -173,9 +173,12 @@ void SN76496Update(short *buffer, int length, int stereo) /* If we exit the loop in the middle, Output[i] has to be inverted */ /* and vol[i] incremented only if the exit status of the square */ /* wave is 1. */ + left = 0; while (R->Count[i] <= 0) { - R->Count[i] += R->Period[i]; + if (R->Count[i] + R->Period[i]*4 < R->Period[i]) + left+= 4, R->Count[i] += R->Period[i]*4; + else left++, R->Count[i] += R->Period[i]; if (R->Count[i] > 0) { R->Output[i] ^= 1; @@ -186,6 +189,9 @@ void SN76496Update(short *buffer, int length, int stereo) vol[i] += R->Period[i]; } if (R->Output[i]) vol[i] -= R->Count[i]; + /* Cut of anything above the sample freqency. It will only create */ + /* aliasing and hearable distortions anyway. */ + if (left > 1) vol[i] = STEP/2; } left = STEP; diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 54521601..a6d55df2 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -259,6 +259,7 @@ static int PsndRender(int offset, int length) int stereo = (PicoIn.opt & 8) >> 3; int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20); int daclen = ((Pico.snd.dac_pos+0x80000) >> 20); + int psglen = ((Pico.snd.psg_pos+0x8000) >> 16); buf32 = PsndBuffer+(offset< 0) { + short *psgbuf = PicoIn.sndOut + (psglen << stereo); + Pico.snd.psg_pos += (length-psglen) << 16; + if (PicoIn.opt & POPT_EN_PSG) + SN76496Update(psgbuf, length-psglen, stereo); + } + // Add in parts of the FM buffer not yet done if (length-fmlen > 0) { int *fmbuf = buf32 + ((fmlen-offset) << stereo); @@ -323,8 +332,6 @@ PICO_INTERNAL void PsndGetSamples(int y) { static int curr_pos = 0; - PsndDoPSG(y - 1); - curr_pos = PsndRender(0, Pico.snd.len_use); if (PicoIn.writeSound) @@ -333,11 +340,20 @@ PICO_INTERNAL void PsndGetSamples(int y) PsndClear(); } -PICO_INTERNAL void PsndGetSamplesMS(int y) +static int PsndRenderMS(int offset, int length) { - int length = Pico.snd.len_use; + int stereo = (PicoIn.opt & 8) >> 3; + int psglen = ((Pico.snd.psg_pos+0x8000) >> 16); - PsndDoPSG(y - 1); + pprof_start(sound); + + // Add in parts of the PSG output not yet done + if (length-psglen > 0) { + short *psgbuf = PicoIn.sndOut + (psglen << stereo); + Pico.snd.psg_pos += (length-psglen) << 16; + if (PicoIn.opt & POPT_EN_PSG) + SN76496Update(psgbuf, length-psglen, stereo); + } // upmix to "stereo" if needed if (PicoIn.opt & POPT_EN_STEREO) { @@ -346,8 +362,19 @@ PICO_INTERNAL void PsndGetSamplesMS(int y) *p |= *p << 16; } + pprof_end(sound); + + return length; +} + +PICO_INTERNAL void PsndGetSamplesMS(int y) +{ + static int curr_pos = 0; + + curr_pos = PsndRenderMS(0, Pico.snd.len_use); + if (PicoIn.writeSound != NULL) - PicoIn.writeSound(length * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); + PicoIn.writeSound(curr_pos * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2)); PsndClear(); } -- 2.39.2