Exemplo n.º 1
0
int sound_update(unsigned int cycles)
{
    int delta, preamp, time, l, r, *ptr;

    /* Run PSG & FM chips until end of frame */
    SN76489_Update(cycles);
    fm_update(cycles);

    /* FM output pre-amplification */
    preamp = config.fm_preamp;

    /* FM frame initial timestamp */
    time = fm_cycles_start;

    /* Restore last FM outputs from previous frame */
    l = fm_last[0];
    r = fm_last[1];

    /* FM buffer start pointer */
    ptr = fm_buffer;

    /* flush FM samples */
    if (config.hq_fm)
    {
        /* high-quality Band-Limited synthesis */
        do
        {
            /* left channel */
            delta = ((*ptr++ * preamp) / 100) - l;
            l += delta;
            blip_add_delta(snd.blips[0][0], time, delta);

            /* right channel */
            delta = ((*ptr++ * preamp) / 100) - r;
            r += delta;
            blip_add_delta(snd.blips[0][1], time, delta);

            /* increment time counter */
            time += fm_cycles_ratio;
        }
        while (time < cycles);
    }
    else
    {
        /* faster Linear Interpolation */
        do
        {
            /* left channel */
            delta = ((*ptr++ * preamp) / 100) - l;
            l += delta;
            blip_add_delta_fast(snd.blips[0][0], time, delta);

            /* right channel */
            delta = ((*ptr++ * preamp) / 100) - r;
            r += delta;
            blip_add_delta_fast(snd.blips[0][1], time, delta);

            /* increment time counter */
            time += fm_cycles_ratio;
        }
        while (time < cycles);
    }

    /* reset FM buffer pointer */
    fm_ptr = fm_buffer;

    /* save last FM output for next frame */
    fm_last[0] = l;
    fm_last[1] = r;

    /* adjust FM cycle counters for next frame */
    fm_cycles_count = fm_cycles_start = time - cycles;

    /* end of blip buffers time frame */
    blip_end_frame(snd.blips[0][0], cycles);
    blip_end_frame(snd.blips[0][1], cycles);

    /* return number of available samples */
    return blip_samples_avail(snd.blips[0][0]);
}
Exemplo n.º 2
0
void cdd_read_audio(unsigned int samples)
{
  /* previous audio outputs */
  int16 l = cdd.audio[0];
  int16 r = cdd.audio[1];

  /* get number of internal clocks (samples) needed */
  samples = blip_clocks_needed(blip[0], samples);

  /* audio track playing ? */
  if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
  {
    int i, mul, delta;

    /* 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
    {
#ifdef LSB_FIRST
      int16 *ptr = (int16 *) (cdc.ram);
#else
      uint8 *ptr = cdc.ram;
#endif
      fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);

      /* 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++;
  #else
        delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
        ptr += 2;
  #endif
        l += delta;
        blip_add_delta_fast(blip[0], i, delta);

        /* right channel */
  #ifdef LSB_FIRST
        delta = ((ptr[0] * mul) / 1024) - r;
        ptr++;
  #else
        delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
        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;
        }
      }
    }

    /* save current CD-DA fader volume */
    cdd.volume = curVol;

    /* save last audio output for next frame */
    cdd.audio[0] = l;
    cdd.audio[1] = r;
  }
Exemplo n.º 3
0
void pcm_run(unsigned int length)
{
#ifdef LOG_PCM
  error("[%d][%d]run %d PCM samples (from %d)\n", v_counter, s68k.cycles, length, pcm.cycles);
#endif
  /* check if PCM chip is running */
  if (pcm.enabled)
  {
    int i, j, l, r;

    /* generate PCM samples */
    for (i = 0; i != length; i++)
    {
      /* clear output */
      l = r = 0;

      /* run eight PCM channels */
      for (j = 0; j != 8; j++)
      {
        /* check if channel is enabled */
        if (pcm.status & (1 << j))
        {
          /* read from current WAVE RAM address */
          short data = pcm.ram[(pcm.chan[j].addr >> 11) & 0xffff];

          /* loop data ? */
          if (data == 0xff)
          {
            /* reset WAVE RAM address */
            pcm.chan[j].addr = pcm.chan[j].ls.w << 11;

            /* read again from WAVE RAM address */
            data = pcm.ram[pcm.chan[j].ls.w];
          }
          else
          {
            /* increment WAVE RAM address */
            pcm.chan[j].addr += pcm.chan[j].fd.w;
          }

          /* infinite loop should not output any data */
          if (data != 0xff)
          {
            /* check sign bit (output centered around 0) */
            if (data & 0x80)
            {
              /* PCM data is positive */
              data = data & 0x7f;
            }
            else
            {
              /* PCM data is negative */
              data = -(data & 0x7f);
            }

            /* multiply PCM data with ENV & stereo PAN data then add to L/R outputs (14.5 fixed point) */
            l += ((data * pcm.chan[j].env * (pcm.chan[j].pan & 0x0F)) >> 5);
            r += ((data * pcm.chan[j].env * (pcm.chan[j].pan >> 4)) >> 5);
          }
        }
      }

      /* limiter */
      if      (l < -32768) l = -32768;
      else if (l >  32767) l =  32767;
      if      (r < -32768) r = -32768;
      else if (r >  32767) r =  32767;

      /* check if PCM left output changed */
      if (pcm.out[0] != l)
      {
        blip_add_delta_fast(snd.blips[1][0], i, l-pcm.out[0]);
        pcm.out[0] = l;
      }

      /* check if PCM right output changed */
      if (pcm.out[1] != r)
      {
        blip_add_delta_fast(snd.blips[1][1], i, r-pcm.out[1]);
        pcm.out[1] = r;
      }
    }
Exemplo n.º 4
0
int psg_context_load(uint8 *state)
{
  int delta[2];
  int i, bufferptr = 0;

  /* initialize delta with current noise channel output */
  if (psg.noiseShiftValue & 1)
  {
    delta[0] = -psg.chanOut[3][0];
    delta[1] = -psg.chanOut[3][1];
  }
  else
  {
    delta[0] = 0;
    delta[1] = 0;
  }

  /* add current tone channels output */
  for (i=0; i<3; i++)
  {
    if (psg.polarity[i] > 0)
    {
      delta[0] -= psg.chanOut[i][0];
      delta[1] -= psg.chanOut[i][1];
    }
  }

  load_param(&psg.clocks,sizeof(psg.clocks));
  load_param(&psg.latch,sizeof(psg.latch));
  load_param(&psg.noiseShiftValue,sizeof(psg.noiseShiftValue));
  load_param(psg.regs,sizeof(psg.regs));
  load_param(psg.freqInc,sizeof(psg.freqInc));
  load_param(psg.freqCounter,sizeof(psg.freqCounter));
  load_param(psg.polarity,sizeof(psg.polarity));
  load_param(psg.chanOut,sizeof(psg.chanOut));

  /* add noise channel output variation */
  if (psg.noiseShiftValue & 1)
  {
    delta[0] += psg.chanOut[3][0];
    delta[1] += psg.chanOut[3][1];
  }

  /* add tone channels output variation */
  for (i=0; i<3; i++)
  {
    if (psg.polarity[i] > 0)
    {
      delta[0] += psg.chanOut[i][0];
      delta[1] += psg.chanOut[i][1];
    }
  }

  /* update mixed channels output */
  if (config.hq_psg)
  {
    blip_add_delta(snd.blips[0], psg.clocks, delta[0], delta[1]);
  }
  else
  {
    blip_add_delta_fast(snd.blips[0], psg.clocks, delta[0], delta[1]);
  }

  return bufferptr;
}