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
This commit is contained in:
Anthony Pesch 2017-01-04 16:38:39 -08:00
parent 93cde7f1d0
commit 006813063e
5 changed files with 16 additions and 40 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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) {