mirror of https://github.com/inolen/redream.git
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:
parent
93cde7f1d0
commit
006813063e
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue