diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs
index feaf8ad0dd..b91c903f22 100644
--- a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs
@@ -147,7 +147,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
 			if (audio)
 			{
 				byte[] data = new byte[2352];
-				if (lba < _cd.Session1.LeadoutLBA)
+				if (lba < _cd.Session1.LeadoutLBA && lba >= _cd.Session1.Tracks[2].LBA)
 				{
 					_cdReader.ReadLBA_2352(lba, data, 0);
 				}
diff --git a/waterbox/picodrive/bizhawk.c b/waterbox/picodrive/bizhawk.c
index a3b9e710f8..ea384c5863 100644
--- a/waterbox/picodrive/bizhawk.c
+++ b/waterbox/picodrive/bizhawk.c
@@ -122,10 +122,6 @@ void emu_32x_startup(void)
 {
 }
 
-int mp3_get_bitrate(void *f, int size) { return 0; }
-void mp3_start_play(void *f, int pos) {}
-void mp3_update(int *buffer, int length, int stereo) {}
-
 static const uint8_t *TryLoadBios(const char *name)
 {
 	FILE *f = fopen(name, "rb");
diff --git a/waterbox/picodrive/pico/cd/cdd.c b/waterbox/picodrive/pico/cd/cdd.c
index c0c2c86960..3726506bbe 100644
--- a/waterbox/picodrive/pico/cd/cdd.c
+++ b/waterbox/picodrive/pico/cd/cdd.c
@@ -125,6 +125,12 @@ void cdd_reset(void)
 	/* reset logical block address */
 	cdd.lba = 0;
 
+	// reset audio subblock position
+	cdd.sampleOffset = 0;
+
+	// reset audio read position
+	cdd.sampleLba = 0;
+
 	/* reset status */
 	cdd.status = NO_DISC;
 
@@ -198,164 +204,108 @@ void cdd_read_data(uint8 *dst)
 	}
 }
 
-#if 0
-void cdd_read_audio(unsigned int samples)
+void cdd_read_audio(short *buffer, unsigned int samples)
 {
-  /* previous audio outputs */
-  int16 l = cdd.audio[0];
-  int16 r = cdd.audio[1];
+	printf("cdd_read_audio %u\n", samples);
+	short *outptr = buffer;
+	/* audio track playing ? */
+	if (!Pico_mcd->s68k_regs[0x36 + 0])
+	{
+		int i, mul;
 
-  /* get number of internal clocks (samples) needed */
-  samples = blip_clocks_needed(blip[0], samples);
+		/* current CD-DA fader volume */
+		int curVol = cdd.volume;
 
-  /* audio track playing ? */
-  if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
-  {
-    int i, mul, delta;
+		/* CD-DA fader volume setup (0-1024) */
+		int endVol = Pico_mcd->s68k_regs[0x34] << 4 | Pico_mcd->s68k_regs[0x35] >> 4;
 
-    /* current CD-DA fader volume */
-    int curVol = cdd.volume;
-
-    /* CD-DA fader volume setup (0-1024) */
-    int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
-
-    /* read samples from current block */
-#ifdef USE_LIBTREMOR
-    if (cdd.toc.tracks[cdd.index].vf.datasource)
-    {
-      int len, done = 0;
-      int16 *ptr = (int16 *) (cdc.ram);
-      samples = samples * 4;
-      while (done < samples)
-      {
-        len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
-        if (len <= 0) 
-        {
-          done = samples;
-          break;
-        }
-        done += len;
-      }
-      samples = done / 4;
-
-      /* process 16-bit (host-endian) stereo samples */
-      for (i=0; i<samples; i++)
-      {
-        /* CD-DA fader multiplier (cf. LC7883 datasheet) */
-        /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
-        mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
-
-        /* left channel */
-        delta = ((ptr[0] * mul) / 1024) - l;
-        ptr++;
-        l += delta;
-        blip_add_delta_fast(blip[0], i, delta);
-
-        /* right channel */
-        delta = ((ptr[0] * mul) / 1024) - r;
-        ptr++;
-        r += delta;
-        blip_add_delta_fast(blip[1], i, delta);
-
-        /* update CD-DA fader volume (one step/sample) */
-        if (curVol < endVol)
-        {
-          /* fade-in */
-          curVol++;
-        }
-        else if (curVol > endVol)
-        {
-          /* fade-out */
-          curVol--;
-        }
-        else if (!curVol)
-        {
-          /* audio will remain muted until next setup */
-          break;
-        }
-      }
-    }
-    else
-#endif
-    {
+		/* read samples from current block */
+		{
+			uint8_t audio_scratch[4096];
 #ifdef LSB_FIRST
-      int16 *ptr = (int16 *) (cdc.ram);
+			int16 *ptr = (int16 *)audio_scratch;
 #else
-      uint8 *ptr = cdc.ram;
+			uint8 *ptr = audio_scratch;
 #endif
-      fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
+			{
+				char scratch[2352];
+				int nsampreq = samples;
+				unsigned char *dest = audio_scratch;
+				while (nsampreq > 0)
+				{
+					int tocopy = 588 - cdd.sampleOffset;
+					if (tocopy > nsampreq)
+						tocopy = nsampreq;
+					CDReadSector(cdd.sampleLba, scratch, 1);
+					memcpy(dest, scratch + cdd.sampleOffset * 4, tocopy * 4);
+					nsampreq -= tocopy;
+					dest += tocopy * 4;
+					cdd.sampleOffset += tocopy;
+					if (cdd.sampleOffset == 588)
+					{
+						cdd.sampleOffset = 0;
+						cdd.sampleLba++;
+					}
+				}
 
-      /* process 16-bit (little-endian) stereo samples */
-      for (i=0; i<samples; i++)
-      {
-        /* CD-DA fader multiplier (cf. LC7883 datasheet) */
-        /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
-        mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
+				//printf("samples: %i\n", samples);
+				//memset(cdc.ram, 0, samples * 4);
+				//fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
+			}
 
-        /* left channel */
+			/* process 16-bit (little-endian) stereo samples */
+			for (i = 0; i < samples; i++)
+			{
+				/* CD-DA fader multiplier (cf. LC7883 datasheet) */
+				/* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
+				mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
+
+/* left channel */
 #ifdef LSB_FIRST
-        delta = ((ptr[0] * mul) / 1024) - l;
-        ptr++;
+				*outptr++ = ((ptr[0] * mul) / 1024);
+				ptr++;
 #else
-        delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
-        ptr += 2;
+				*outptr++ = (((int16)((ptr[0] + ptr[1] * 256)) * mul) / 1024);
+				ptr += 2;
 #endif
-        l += delta;
-        blip_add_delta_fast(blip[0], i, delta);
 
-        /* right channel */
+/* right channel */
 #ifdef LSB_FIRST
-        delta = ((ptr[0] * mul) / 1024) - r;
-        ptr++;
+				*outptr++ = ((ptr[0] * mul) / 1024);
+				ptr++;
 #else
-        delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
-        ptr += 2;
+				*outptr++ = (((int16)((ptr[0] + ptr[1] * 256)) * mul) / 1024);
+				ptr += 2;
 #endif
-        r += delta;
-        blip_add_delta_fast(blip[1], i, delta);
 
-        /* update CD-DA fader volume (one step/sample) */
-        if (curVol < endVol)
-        {
-          /* fade-in */
-          curVol++;
-        }
-        else if (curVol > endVol)
-        {
-          /* fade-out */
-          curVol--;
-        }
-        else if (!curVol)
-        {
-          /* audio will remain muted until next setup */
-          break;
-        }
-      }
-    }
+				/* update CD-DA fader volume (one step/sample) */
+				if (curVol < endVol)
+				{
+					/* fade-in */
+					curVol++;
+				}
+				else if (curVol > endVol)
+				{
+					/* fade-out */
+					curVol--;
+				}
+				else if (!curVol)
+				{
+					/* audio will remain muted until next setup */
+					break;
+				}
+			}
+		}
 
-    /* save current CD-DA fader volume */
-    cdd.volume = curVol;
-
-    /* save last audio output for next frame */
-    cdd.audio[0] = l;
-    cdd.audio[1] = r;
-  }
-  else
-  {
-    /* no audio output */
-    if (l) blip_add_delta_fast(blip[0], 0, -l);
-    if (r) blip_add_delta_fast(blip[1], 0, -r);
-
-    /* save audio output for next frame */
-    cdd.audio[0] = 0;
-    cdd.audio[1] = 0;
-  }
-
-  /* end of Blip Buffer timeframe */
-  blip_end_frame(blip[0], samples);
-  blip_end_frame(blip[1], samples);
+		/* save current CD-DA fader volume */
+		cdd.volume = curVol;
+	}
+	else
+	{
+		/* no audio output */
+		memset(buffer, 0, samples * 4);
+	}
 }
-#endif
 
 void cdd_update(void)
 {
@@ -411,6 +361,12 @@ void cdd_update(void)
 			if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
 			{
 				/* audio track playing */
+				// if it wasn't before, set the audio start position
+				if (Pico_mcd->s68k_regs[0x36 + 0])
+				{
+					cdd.sampleLba = cdd.lba + 1;
+					cdd.sampleOffset = 0;
+				}
 				Pico_mcd->s68k_regs[0x36 + 0] = 0x00;
 			}
 
@@ -455,6 +411,7 @@ void cdd_update(void)
 	{
 		/* fast-forward or fast-rewind */
 		cdd.lba += cdd.scanOffset;
+		cdd.sampleLba += cdd.scanOffset;
 
 		/* check current track limits */
 		if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
@@ -469,6 +426,9 @@ void cdd_update(void)
 			if (cdd.status == CD_PLAY)
 			{
 				Pico_mcd->s68k_regs[0x36 + 0] = 0x00;
+				// set audio start point
+				cdd.sampleLba = cdd.lba;
+				cdd.sampleOffset = 0;
 			}
 		}
 		else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
diff --git a/waterbox/picodrive/pico/cd/cdd.h b/waterbox/picodrive/pico/cd/cdd.h
index a660d2bf26..9b7ca065d0 100644
--- a/waterbox/picodrive/pico/cd/cdd.h
+++ b/waterbox/picodrive/pico/cd/cdd.h
@@ -80,6 +80,8 @@ typedef struct
 	int lba;
 	int scanOffset;
 	int volume;
+	int sampleOffset;
+	int sampleLba;
 	uint8_t status;
 	toc_t toc;
 	int16_t audio[2];
diff --git a/waterbox/picodrive/pico/pico.h b/waterbox/picodrive/pico/pico.h
index 818a6af33c..e64e85cef4 100644
--- a/waterbox/picodrive/pico/pico.h
+++ b/waterbox/picodrive/pico/pico.h
@@ -19,11 +19,6 @@ extern "C" {
 // message log
 extern void lprintf(const char *fmt, ...);
 
-// external funcs for Sega/Mega CD
-extern int  mp3_get_bitrate(void *f, int size);
-extern void mp3_start_play(void *f, int pos);
-extern void mp3_update(int *buffer, int length, int stereo);
-
 // this one should handle display mode changes
 extern void emu_video_mode_change(int start_line, int line_count, int is_32cols);
 
diff --git a/waterbox/picodrive/pico/pico_int.h b/waterbox/picodrive/pico/pico_int.h
index 2d3d04b03b..baca076ad0 100644
--- a/waterbox/picodrive/pico/pico_int.h
+++ b/waterbox/picodrive/pico/pico_int.h
@@ -438,8 +438,6 @@ typedef struct
   unsigned char bram[0x2000];			// 110200: 8K
   struct mcd_misc m;				// 112200: misc
   struct mcd_pcm pcm;				// 112240:
-  void *cdda_stream;
-  int cdda_type;
   int pcm_mixbuf[PCM_MIXBUF_LEN * 2];
   int pcm_mixpos;
   char pcm_mixbuf_dirty;
@@ -605,7 +603,7 @@ unsigned short cdc_host_r(void);
 // cd/cdd.c
 void cdd_reset(void);
 void cdd_read_data(unsigned char *dst);
-void cdd_read_audio(unsigned int samples);
+void cdd_read_audio(short *buffer, unsigned int samples);
 void cdd_update(void);
 void cdd_process(void);
 
@@ -709,7 +707,6 @@ PICO_INTERNAL int  SekInterruptS68k(int irq);
 void SekInterruptClearS68k(int irq);
 
 // sound/sound.c
-extern short cdda_out_buffer[2*1152];
 extern int PsndLen_exc_cnt;
 extern int PsndLen_exc_add;
 extern int timer_a_next_oflow, timer_a_step; // in z80 cycles
diff --git a/waterbox/picodrive/pico/sound/sound.c b/waterbox/picodrive/pico/sound/sound.c
index 76c5c62df6..84061f4987 100644
--- a/waterbox/picodrive/pico/sound/sound.c
+++ b/waterbox/picodrive/pico/sound/sound.c
@@ -24,7 +24,7 @@ static int PsndBuffer[2*(44100+100)/50];
 static unsigned short dac_info[312+4]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample
 
 // cdda output buffer
-short cdda_out_buffer[2*1152];
+static short cdda_out_buffer[2*1152];
 
 // for Pico
 int PsndRate=0;
@@ -190,50 +190,30 @@ PICO_INTERNAL void PsndDoDAC(int line_to)
 // cdda
 static void cdda_raw_update(int *buffer, int length)
 {
-  /*int ret, cdda_bytes, mult = 1;
+	cdd_read_audio(cdda_out_buffer, length);
 
-  cdda_bytes = length*4;
-  if (PsndRate <= 22050 + 100) mult = 2;
-  if (PsndRate <  22050 - 100) mult = 4;
-  cdda_bytes *= mult;
+	int mult = 1;
 
-  ret = pm_read(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream);
-  if (ret < cdda_bytes) {
-    memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret);
-    Pico_mcd->cdda_stream = NULL;
-    return;
-  }
+	if (PsndRate <= 22050 + 100)
+		mult = 2;
+	if (PsndRate < 22050 - 100)
+		mult = 4;
 
-  // now mix
-  switch (mult) {
-    case 1: mix_16h_to_32(buffer, cdda_out_buffer, length*2); break;
-    case 2: mix_16h_to_32_s1(buffer, cdda_out_buffer, length*2); break;
-    case 4: mix_16h_to_32_s2(buffer, cdda_out_buffer, length*2); break;
-  }*/
+	// now mix
+	switch (mult)
+	{
+	case 1:
+		mix_16h_to_32(buffer, cdda_out_buffer, length * 2);
+		break;
+	case 2:
+		mix_16h_to_32_s1(buffer, cdda_out_buffer, length * 2);
+		break;
+	case 4:
+		mix_16h_to_32_s2(buffer, cdda_out_buffer, length * 2);
+		break;
+	}
 }
 
-void cdda_start_play(int lba_base, int lba_offset, int lb_len)
-{
-  /*if (Pico_mcd->cdda_type == CT_MP3)
-  {
-    int pos1024 = 0;
-
-    if (lba_offset)
-      pos1024 = lba_offset * 1024 / lb_len;
-
-    mp3_start_play(Pico_mcd->cdda_stream, pos1024);
-    return;
-  }
-
-  pm_seek(Pico_mcd->cdda_stream, (lba_base + lba_offset) * 2352, SEEK_SET);
-  if (Pico_mcd->cdda_type == CT_WAV)
-  {
-    // skip headers, assume it's 44kHz stereo uncompressed
-    pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR);
-  }*/
-}
-
-
 PICO_INTERNAL void PsndClear(void)
 {
   int len = PsndLen;
@@ -297,7 +277,6 @@ static int PsndRender(int offset, int length)
   // CD: CDDA audio
   // CD mode, cdda enabled, not data track, CDC is reading
   if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA)
-      && Pico_mcd->cdda_stream != NULL
       && !(Pico_mcd->s68k_regs[0x36] & 1))
   {
     // note: only 44, 22 and 11 kHz supported, with forced stereo