static void * alsa_thread(void *arg) { gint16 *ptr; int err, cptr; guint8 *buf; sfx_pcm_device_t *self = (sfx_pcm_device_t *) arg; buf = (guint8 *) malloc(period_size * frame_size); while (run_thread) { ptr = (gint16 *) buf; cptr = period_size; sci_gettime(&last_callback_secs, &last_callback_usecs); self->timer->block(); if (alsa_sfx_timer_callback) alsa_sfx_timer_callback(alsa_sfx_timer_data); self->timer->unblock(); sfx_audbuf_read(&audio_buffer, buf, period_size); while (cptr > 0) { err = snd_pcm_writei(handle, ptr, cptr); if (err == -EAGAIN) continue; if (err < 0) { if (xrun_recovery(handle, err) < 0) { fprintf(stderr, "[SND:ALSA] Write error: %s\n", snd_strerror(err)); run_thread = 0; } break; /* skip one period */ } ptr += err * channels; cptr -= err; } } free(buf); return NULL; }
static void timer_sdl_internal_callback(void *userdata, byte *dest, int len) { sci_gettime(&last_callback_secs, &last_callback_usecs); last_callback_len = len; if (sdl_sfx_timer_callback) sdl_sfx_timer_callback(sdl_sfx_timer_data); #if 0 if (!sfx_audbuf_read_timestamp(&audio_buffer, &ts)) { int delta = (buf_size - len) / frame_size; sfx_timestamp_t real_ts; long deltatime; long sec2, usec2; sci_gettime(&sec2, &usec2); real_ts = sfx_timestamp_add(sfx_new_timestamp(sec, usec, rate), delta); deltatime = sfx_timestamp_usecs_diff(ts, real_ts); fprintf(stderr, "[SDL] Frames requested: %d Playing %ld too late. Needed %ldus for computations.\n", len / frame_size, deltatime, (usec2-usec) + (sec2-sec)*1000000); if (abs(deltatime) > DELTA_TIME_LIMIT) sciprintf("[SND:SDL] Very high delta time for PCM playback: %ld too late (%d frames in the future)\n", deltatime, sfx_timestamp_frame_diff(sfx_new_timestamp(sec, usec, rate), ts)); #if 0 if (deltatime < 0) { /* Read and discard frames, explicitly underrunning */ int max_read = len / frame_size; int frames_to_kill = sfx_timestamp_frame_diff(real_ts, ts); while (frames_to_kill) { int d = frames_to_kill > max_read? max_read : frames_to_kill; sfx_audbuf_read(&audio_buffer, dest, d); frames_to_kill -= d; } } #endif } #endif sfx_audbuf_read(&audio_buffer, dest, len / frame_size); #if 0 if (!fil) { fil = fopen("/tmp/sdl.log", "w"); } { int i; int end = len / frame_size; gint16 *d = dest; fprintf(fil, "Writing %d/%d\n", len, frame_size); for (i = 0; i < end; i++) { fprintf(fil, "\t%d\t%d\n", d[0], d[1]); d += 2; } } #endif }