Example #1
0
/* Finishes syncing by using more accurate system sleep functions*/
void
S9xSyncSpeedFinish (void)
{
    if (!syncing)
        return;

    gettimeofday (&now, NULL);

    if (Settings.SoundSync)
    {
        while (!S9xSyncSound ())
        {
            usleep (100);

            gettimeofday (&next_frame_time, NULL);

            /* If we can't sync sound within a second, we're probably deadlocked */
            if (TIMER_DIFF (next_frame_time, now) > 1000000)
            {
                /* Flush out our sample buffer and give up. */
                S9xClearSamples ();

                break;
            }
        }

        next_frame_time = now;
        return;
    }

    if (TIMER_DIFF (next_frame_time, now) < -500000)
    {
        next_frame_time = now;
    }

    while (timercmp (&next_frame_time, &now, >))
    {
        int time_left = TIMER_DIFF (next_frame_time, now);

        if (time_left > 500000)
        {
            next_frame_time = now;
            break;
        }

        usleep (time_left);

        gettimeofday (&now, NULL);
    }

    next_frame_time.tv_usec += Settings.FrameTime;

    if (next_frame_time.tv_usec >= 1000000)
    {
        next_frame_time.tv_sec += next_frame_time.tv_usec / 1000000;
        next_frame_time.tv_usec %= 1000000;
    }

    syncing = 0;

    return;
}
void S9xAlsaSoundDriver::samples_available()
{
    snd_pcm_sframes_t frames_written, frames;
    int bytes;

    frames = snd_pcm_avail(pcm);

    if (frames < 0)
    {
        frames = snd_pcm_recover(pcm, frames, 1);
        return;
    }

    if (Settings.DynamicRateControl)
    {
        S9xUpdateDynamicRate(snd_pcm_frames_to_bytes(pcm, frames),
                             output_buffer_size);
    }

    int snes_frames_available = S9xGetSampleCount() >> 1;

    if (Settings.DynamicRateControl && !Settings.SoundSync)
    {
        // Using rate control, we should always keep the emulator's sound buffers empty to
        // maintain an accurate measurement.
        if (frames < snes_frames_available)
        {
            S9xClearSamples();
            return;
        }
    }

    if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
    {
        snd_pcm_nonblock(pcm, 0);
        frames = snes_frames_available;
    }
    else
    {
        snd_pcm_nonblock(pcm, 1);
        frames = MIN(frames, snes_frames_available);
    }

    bytes = snd_pcm_frames_to_bytes(pcm, frames);
    if (bytes <= 0)
        return;

    if (sound_buffer_size < bytes || sound_buffer == NULL)
    {
        sound_buffer = (uint8 *)realloc(sound_buffer, bytes);
        sound_buffer_size = bytes;
    }

    S9xMixSamples(sound_buffer, frames * 2);

    frames_written = 0;

    while (frames_written < frames)
    {
        int result;

        result = snd_pcm_writei(pcm,
                                sound_buffer +
                                    snd_pcm_frames_to_bytes(pcm, frames_written),
                                frames - frames_written);

        if (result < 0)
        {
            result = snd_pcm_recover(pcm, result, 1);

            if (result < 0)
            {
                break;
            }
        }
        else
        {
            frames_written += result;
        }
    }
}