示例#1
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();
}
示例#2
0
ECL_EXPORT void FrameAdvance(MyFrameInfo &f)
{
	if (sgb)
	{
		sgb_set_controller_data((uint8_t *)&f.Keys);
	}
	else
	{
		GB_set_key_state(&GB, f.Keys & 0xff);
	}
	sound_start_clock = GB_epoch(&GB);
	CurrentFramebuffer = f.VideoBuffer;
	GB_set_lagged(&GB, true);
	GB.frontend_rtc_time = f.Time;

	uint32_t target = 35112 - FrameOverflow;
	f.Cycles = GB_run_cycles(&GB, target);
	FrameOverflow = f.Cycles - target;
	if (sgb)
	{
		f.Width = 256;
		f.Height = 224;
		sgb_render_audio(GB_epoch(&GB), SgbSampleCallback);
	}
	else
	{
		f.Width = 160;
		f.Height = 144;
	}
	blip_end_frame(leftblip, f.Cycles);
	blip_end_frame(rightblip, f.Cycles);
	f.Samples = blip_read_samples(leftblip, f.SoundBuffer, 2048, 1);
	blip_read_samples(rightblip, f.SoundBuffer + 1, 2048, 1);
	CurrentFramebuffer = NULL;
	f.Lagged = GB_get_lagged(&GB);
}
示例#3
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]);
}