void fs_emu_audio_video_sync(int time_ms) { for (int i = 0; i < MAX_STREAMS; i++) { if (g_streams[i]) { unqueue_old_buffers(i); update_stats(i, time_ms); pid_controller_step(i, time_ms); } } }
int fs_emu_queue_audio_buffer(int stream, int16_t* data, int size) { if (g_fs_emu_benchmarking) { // no audio output while benchmarking return 0; } //fs_log("fs_emu_queue_audio_buffer stream %d\n", stream); audio_stream *s = g_streams[stream]; ALuint buffer = 0; g_mutex_lock(s->mutex); //while (1) { buffer = GPOINTER_TO_UINT(g_queue_pop_head(s->queue)); if (!buffer) { fs_log("no audio buffer available - dropping data\n"); g_mutex_unlock(s->mutex); return 0; } s->buffers_queued += 1; // create a local copy while we have the lock int buffers_queued = s->buffers_queued; g_mutex_unlock(s->mutex); alBufferData(buffer, AL_FORMAT_STEREO16, data, size, s->frequency); check_al_error("alBufferData"); alSourceQueueBuffers(s->source, 1, &buffer); check_al_error("alSourceQueueBuffers"); ALint state; alGetSourcei(s->source, AL_SOURCE_STATE, &state); check_al_error("alGetSourcei (AL_SOURCE_STATE)"); if (state != AL_PLAYING) { // we have had a buffer underrun - we now wait until we have queued // some buffers if (buffers_queued < s->min_buffers) { // want more buffers } else { fs_log("restarting audio stream %d (buffer underrun)\n", stream); alSourcePlay(s->source); check_al_error("alSourcePlay"); } } double want_volume = g_volume * 0.9; if (want_volume != s->source_volume_current) { s->source_volume_current = want_volume; alSourcef(s->source, AL_GAIN, want_volume); } unqueue_old_buffers(stream); return buffer; }
int fs_emu_check_audio_buffer_done(int stream, int buffer) { unqueue_old_buffers(stream); audio_stream *s = g_streams[stream]; // not extremely efficient g_mutex_lock(s->mutex); GList *link = g_queue_peek_head_link(s->queue); while (link) { if ((unsigned int) buffer == GPOINTER_TO_UINT(link->data)) { g_mutex_unlock(s->mutex); return 1; } link = link->next; } g_mutex_unlock(s->mutex); return 0; }
static int queue_buffer(int stream, int16_t* data, int size) { if (g_fs_emu_benchmark_mode) { /* no audio output while benchmarking */ return 0; } if (g_fs_emu_benchmarking) { /* no audio output while benchmarking */ return 0; } //fs_log("fs_emu_queue_audio_buffer stream %d size %d\n", stream, size); audio_stream *s = g_streams[stream]; ALuint buffer = 0; fs_mutex_lock(s->mutex); //while (1) { buffer = FS_POINTER_TO_UINT(g_queue_pop_head(s->queue)); if (!buffer) { fs_log("no audio buffer available - dropping data\n"); fs_mutex_unlock(s->mutex); return 0; } s->buffers_queued += 1; // create a local copy while we have the lock //int buffers_queued = s->buffers_queued; fs_mutex_unlock(s->mutex); #if 0 /* for debugging, clear one of the stereo channels */ int16_t *d = data; for (int i = 0; i < size / 4; i++) { d++; *d = 0; d++; } #endif alBufferData(buffer, AL_FORMAT_STEREO16, data, size, s->frequency); check_al_error("alBufferData"); alSourceQueueBuffers(s->source, 1, &buffer); check_al_error("alSourceQueueBuffers"); ALint state; alGetSourcei(s->source, AL_SOURCE_STATE, &state); check_al_error("alGetSourcei (AL_SOURCE_STATE)"); if (state != AL_PLAYING) { g_fs_emu_audio_buffer_underrun_time = fs_get_monotonic_time(); g_fs_emu_audio_buffer_underruns += 1; // we have had a buffer underrun - we now wait until we have queued // some buffers //if (buffers_queued < s->min_buffers) { // // want more buffers //} //else { fs_log("restarting audio stream %d (buffer underrun)\n", stream); alSourcePlay(s->source); g_fs_emu_audio_stream_playing[stream] = 1; check_al_error("alSourcePlay"); //} } double want_volume = g_fs_emu_audio_want_volume[stream] * 0.9; if (want_volume != s->source_volume_current) { s->source_volume_current = want_volume; alSourcef(s->source, AL_GAIN, want_volume); } unqueue_old_buffers(stream); return buffer; }