/* 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; } } }