From 006813063ee7eae6ed7ef4a048abe764d8c72bc8 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Wed, 4 Jan 2017 16:38:39 -0800 Subject: [PATCH] remove aica frame skipping, unnecessary being that we're timing based on the aica buffer state, not the host's buffer (#2) give ta a fixed amount of time to render each frame until a better heuristic is figured out --- src/audio/soundio_backend.c | 30 +++++++++--------------------- src/emu/emulator.c | 4 ++-- src/hw/aica/aica.c | 11 ----------- src/hw/aica/aica.h | 3 ++- src/hw/pvr/ta.c | 8 +++----- 5 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/audio/soundio_backend.c b/src/audio/soundio_backend.c index 451943e8..b6db7a17 100644 --- a/src/audio/soundio_backend.c +++ b/src/audio/soundio_backend.c @@ -9,7 +9,7 @@ struct audio_backend { struct SoundIo *soundio; struct SoundIoDevice *device; struct SoundIoOutStream *outstream; - int frames_silenced; + uint32_t frames[AICA_SAMPLE_FREQ]; }; static void audio_write_callback(struct SoundIoOutStream *outstream, @@ -19,21 +19,10 @@ static void audio_write_callback(struct SoundIoOutStream *outstream, struct SoundIoChannelArea *areas; int err; - /* if any frames were silenced previously in order to prevent an underflow, - discard the same number of incoming aica frames to keep the audio time - domain in sync with the emulator */ - while (audio->frames_silenced) { - int skipped = aica_skip_frames(audio->aica, audio->frames_silenced); - if (!skipped) { - break; - } - audio->frames_silenced -= skipped; - } - - uint32_t frames[10]; - int16_t *samples = (int16_t *)frames; - int frames_remaining = frame_count_max; + int16_t *samples = (int16_t *)audio->frames; int frames_available = aica_available_frames(audio->aica); + int frames_silence = frame_count_max - frames_available; + int frames_remaining = frames_available + frames_silence; while (frames_remaining > 0) { int frame_count = frames_remaining; @@ -49,16 +38,15 @@ static void audio_write_callback(struct SoundIoOutStream *outstream, } for (int frame = 0; frame < frame_count;) { - int n = MIN(frame_count - frame, array_size(frames)); + int n = MIN(frame_count - frame, array_size(audio->frames)); if (frames_available > 0) { /* batch read frames from aica */ - n = aica_read_frames(audio->aica, frames, n); + n = aica_read_frames(audio->aica, audio->frames, n); frames_available -= n; } else { /* write out silence */ - memset(frames, 0, sizeof(frames)); - audio->frames_silenced += n; + memset(audio->frames, 0, n * 4); } /* copy frames to output stream */ @@ -92,7 +80,7 @@ void audio_pump_events(struct audio_backend *audio) { } int audio_buffer_low(struct audio_backend *audio) { - int low_water_mark = (int)(44100.0f * (OPTION_latency / 1000.0f)); + int low_water_mark = (int)((float)AICA_SAMPLE_FREQ * (OPTION_latency / 1000.0f)); return aica_available_frames(audio->aica) <= low_water_mark; } @@ -163,7 +151,7 @@ struct audio_backend *audio_create(struct aica *aica) { { audio->outstream = soundio_outstream_create(audio->device); audio->outstream->format = SoundIoFormatS16NE; - audio->outstream->sample_rate = 44100; + audio->outstream->sample_rate = AICA_SAMPLE_FREQ; audio->outstream->userdata = audio; audio->outstream->write_callback = &audio_write_callback; audio->outstream->underflow_callback = &audio_underflow_callback; diff --git a/src/emu/emulator.c b/src/emu/emulator.c index da2ceb27..621e1055 100644 --- a/src/emu/emulator.c +++ b/src/emu/emulator.c @@ -214,13 +214,13 @@ static void *emu_core_thread(void *data) { int64_t next_pump_time = 0; while (emu->running) { - current_time = time_nanoseconds(); - while (audio_buffer_low(audio)) { dc_tick(emu->dc, MACHINE_STEP); } /* audio events are just for device connections, check infrequently */ + current_time = time_nanoseconds(); + if (current_time > next_pump_time) { audio_pump_events(audio); next_pump_time = current_time + NS_PER_SEC; diff --git a/src/hw/aica/aica.c b/src/hw/aica/aica.c index 82e9bcd8..d6c7362c 100644 --- a/src/hw/aica/aica.c +++ b/src/hw/aica/aica.c @@ -22,7 +22,6 @@ DEFINE_AGGREGATE_COUNTER(aica_samples); #define LOG_AICA(...) #endif -#define AICA_SAMPLE_FREQ 44100 #define AICA_SAMPLE_BATCH 10 #define AICA_NUM_CHANNELS 64 @@ -391,16 +390,6 @@ static void aica_write_frames(struct aica *aica, const void *frames, } } -int aica_skip_frames(struct aica *aica, int num_frames) { - int available = ringbuf_available(aica->frames); - int size = MIN(available, num_frames * 4); - CHECK_EQ(size % 4, 0); - - ringbuf_advance_read_ptr(aica->frames, size); - - return size / 4; -} - int aica_read_frames(struct aica *aica, void *frames, int num_frames) { int available = ringbuf_available(aica->frames); int size = MIN(available, num_frames * 4); diff --git a/src/hw/aica/aica.h b/src/hw/aica/aica.h index 1cc02721..0f17abc9 100644 --- a/src/hw/aica/aica.h +++ b/src/hw/aica/aica.h @@ -7,6 +7,8 @@ struct aica; struct dreamcast; +#define AICA_SAMPLE_FREQ 44100 + AM_DECLARE(aica_reg_map); AM_DECLARE(aica_data_map); @@ -14,7 +16,6 @@ struct aica *aica_create(struct dreamcast *dc); void aica_destroy(struct aica *aica); int aica_available_frames(struct aica *aica); -int aica_skip_frames(struct aica *aica, int num_frames); int aica_read_frames(struct aica *aica, void *buffer, int num_frames); #endif diff --git a/src/hw/pvr/ta.c b/src/hw/pvr/ta.c index 6eaaae2e..7a2a7009 100644 --- a/src/hw/pvr/ta.c +++ b/src/hw/pvr/ta.c @@ -733,11 +733,9 @@ static void ta_start_render(struct ta *ta, struct tile_ctx *ctx) { int num_polys = 0; ta_register_texture_sources(ta, ctx, &num_polys); - /* supposedly, the dreamcast can push around ~3 million polygons per second - through the TA / PVR. with that in mind, a very poor estimate can be made - for how long the TA would take to render a frame based on the number of - polys pushed: 1,000,000,000 / 3,000,000 = 333 nanoseconds per polygon */ - int64_t ns = num_polys * INT64_C(333); + /* give each frame 10 ms to finish rendering + TODO figure out a heuristic involving the number of polygons rendered */ + int64_t ns = INT64_C(10000000); scheduler_start_timer(ta->scheduler, &ta_render_timer, ta, ns); if (ta->trace_writer) {