示例#1
0
文件: blip.c 项目: ben401/OpenEmu
void blip_end_frame( blip_buffer_t* s, int clocks )
{
  s->offset += clocks * s->factor;

  /* Ensure time wasn't past end of buffer */
  assert( blip_samples_avail( s ) <= s->size );
}
示例#2
0
文件: blip.c 项目: ben401/OpenEmu
/* Removes n samples from buffer */
static void remove_samples( blip_buffer_t* s, int n )
{
  int remain = blip_samples_avail( s ) + buf_extra - n;

  s->offset -= n * time_unit;
  assert( s->offset >= 0 );

  /* Copy remaining samples to beginning of buffer and clear the rest */
  memmove( s->buf, &s->buf [n], remain * sizeof (buf_t) );
  memset( &s->buf [remain], 0, n * sizeof (buf_t) );
}
示例#3
0
void end_audio_frame() {
    if (frame_offset == 0)
        // No audio added; blip_end_frame() dislikes being called with an
        // offset of 0
        return;

    assert(!(is_backwards_frame && frame_offset != get_frame_len()));

    // Bring the signal level at the end of the frame to zero as outlined in
    // set_audio_signal_level()
    set_audio_signal_level(0);

    blip_end_frame(blip, frame_offset);

    if (playback_started) {
        // Fudge playback rate by an amount proportional to the difference
        // between the desired and current buffer fill levels to try to steer
        // towards it

        double const fudge_factor = 1.0 + 2*max_adjust*(0.5 - fill_level());
        blip_set_rates(blip, cpu_clock_rate, sample_rate*fudge_factor);
    }
    else {
        if (fill_level() >= 0.5) {
            start_audio_playback();
            playback_started = true;
        }
    }

    int const n_samples = blip_read_samples(blip, blip_samples, ARRAY_LEN(blip_samples), 0);
    // We expect to read all samples from blip_buf. If something goes wrong and
    // we don't, clear the buffer to prevent data piling up in blip_buf's
    // buffer (which lacks bounds checking).
    int const avail = blip_samples_avail(blip);
    if (avail != 0) {
        printf("Warning: didn't read all samples from blip_buf (%d samples remain) - dropping samples\n",
          avail);
        blip_clear(blip);
    }

#ifdef RECORD_MOVIE
    add_movie_audio_frame(blip_samples, n_samples);
#endif

    // Save the samples to the audio ring buffer

    lock_audio();
    write_samples(blip_samples, n_samples);
    unlock_audio();
}
示例#4
0
文件: sdl-audio.c 项目: leiradel/mgba
static void _mSDLAudioCallback(void* context, Uint8* data, int len) {
	struct mSDLAudio* audioContext = context;
	if (!context || !audioContext->core) {
		memset(data, 0, len);
		return;
	}
	blip_t* left = NULL;
	blip_t* right = NULL;
	int32_t clockRate = GBA_ARM7TDMI_FREQUENCY;
	if (audioContext->core) {
		left = audioContext->core->getAudioChannel(audioContext->core, 0);
		right = audioContext->core->getAudioChannel(audioContext->core, 1);
		clockRate = audioContext->core->frequency(audioContext->core);
	}
	double fauxClock = 1;
	if (audioContext->sync) {
		if (audioContext->sync->fpsTarget > 0) {
			fauxClock = GBAAudioCalculateRatio(1, audioContext->sync->fpsTarget, 1);
		}
		mCoreSyncLockAudio(audioContext->sync);
	}
	blip_set_rates(left, clockRate, audioContext->obtainedSpec.freq * fauxClock);
	blip_set_rates(right, clockRate, audioContext->obtainedSpec.freq * fauxClock);
	len /= 2 * audioContext->obtainedSpec.channels;
	int available = blip_samples_avail(left);
	if (available > len) {
		available = len;
	}
	blip_read_samples(left, (short*) data, available, audioContext->obtainedSpec.channels == 2);
	if (audioContext->obtainedSpec.channels == 2) {
		blip_read_samples(right, ((short*) data) + 1, available, 1);
	}

	if (audioContext->sync) {
		mCoreSyncConsumeAudio(audioContext->sync);
	}
	if (available < len) {
		memset(((short*) data) + audioContext->obtainedSpec.channels * available, 0, (len - available) * audioContext->obtainedSpec.channels * sizeof(short));
	}
}
示例#5
0
static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
	struct GBASDLAudio* audioContext = context;
	if (!context || !audioContext->thread || !audioContext->thread->gba) {
		memset(data, 0, len);
		return;
	}
#if RESAMPLE_LIBRARY == RESAMPLE_NN
	audioContext->ratio = GBAAudioCalculateRatio(audioContext->thread->gba->audio.sampleRate, audioContext->thread->fpsTarget, audioContext->obtainedSpec.freq);
	if (audioContext->ratio == INFINITY) {
		memset(data, 0, len);
		return;
	}
	struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data;
	len /= 2 * audioContext->obtainedSpec.channels;
	if (audioContext->obtainedSpec.channels == 2) {
		GBAAudioResampleNN(&audioContext->thread->gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len);
	}
#elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
	double fauxClock = GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1);
	GBASyncLockAudio(&audioContext->thread->sync);
	blip_set_rates(audioContext->thread->gba->audio.left, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock);
	blip_set_rates(audioContext->thread->gba->audio.right, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock);
	len /= 2 * audioContext->obtainedSpec.channels;
	int available = blip_samples_avail(audioContext->thread->gba->audio.left);
	if (available > len) {
		available = len;
	}
	blip_read_samples(audioContext->thread->gba->audio.left, (short*) data, available, audioContext->obtainedSpec.channels == 2);
	if (audioContext->obtainedSpec.channels == 2) {
		blip_read_samples(audioContext->thread->gba->audio.right, ((short*) data) + 1, available, 1);
	}
	GBASyncConsumeAudio(&audioContext->thread->sync);
	if (available < len) {
		memset(((short*) data) + audioContext->obtainedSpec.channels * available, 0, (len - available) * audioContext->obtainedSpec.channels * sizeof(short));
	}
#endif
}
示例#6
0
文件: blip.c 项目: ben401/OpenEmu
int blip_read_samples( blip_buffer_t* s, short out [], int count, int stereo )
{
  /* can't read more than available */
  int avail = blip_samples_avail( s );
  if ( count > avail )
    count = avail;

  if ( count )
  {
    /* Sum deltas and write out */
    int i;
    for ( i = 0; i < count; ++i )
    {
      int sample;

      /* Apply slight high-pass filter */
      s->amp -= s->amp >> 9;

      /* Add next delta */
      s->amp += s->buf [i];

      /* Calculate output sample */
      sample = s->amp >> phase_bits;

      /* Keep within 16-bit sample range */
      if ( sample < -32768 ) sample = -32768;
      if ( sample > +32767 ) sample = +32767;

      out [i << stereo] = sample;
    }

    remove_samples( s, count );
  }

  return count;
}
示例#7
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]);
}