dummy: pass the latency test

See #2
This commit is contained in:
Andrew Kelley 2015-09-02 13:31:43 -07:00
parent 59fca8cb75
commit e5cd076e2e
9 changed files with 92 additions and 29 deletions

View file

@ -1468,7 +1468,9 @@ static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre
return 0;
}
static int outstream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
static int outstream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
soundio_panic("TODO");
}
@ -1742,7 +1744,9 @@ static int instream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoInStream
return 0;
}
static int instream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
static int instream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
soundio_panic("TODO");
}

View file

@ -1052,7 +1052,9 @@ static int outstream_clear_buffer_ca(struct SoundIoPrivate *si, struct SoundIoOu
return SoundIoErrorIncompatibleBackend;
}
static int outstream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
static int outstream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
soundio_panic("TODO");
}
@ -1308,7 +1310,9 @@ static int instream_end_read_ca(struct SoundIoPrivate *si, struct SoundIoInStrea
return 0;
}
static int instream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
static int instream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
soundio_panic("TODO");
}

View file

@ -253,8 +253,13 @@ static int outstream_clear_buffer_dummy(SoundIoPrivate *si, SoundIoOutStreamPriv
return 0;
}
static int outstream_get_latency_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
soundio_panic("TODO");
static int outstream_get_latency_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, double *out_latency) {
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
*out_latency = (fill_bytes / outstream->bytes_per_frame) / (double)outstream->sample_rate;
return 0;
}
static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
@ -361,8 +366,13 @@ static int instream_end_read_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *i
return 0;
}
static int instream_get_latency_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
soundio_panic("TODO");
static int instream_get_latency_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, double *out_latency) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *osd = &is->backend_data.dummy;
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
*out_latency = (fill_bytes / instream->bytes_per_frame) / (double)instream->sample_rate;
return 0;
}
static int set_all_device_formats(SoundIoDevice *device) {

View file

@ -572,7 +572,9 @@ static int outstream_clear_buffer_jack(struct SoundIoPrivate *si, struct SoundIo
return SoundIoErrorIncompatibleBackend;
}
static int outstream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
static int outstream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
soundio_panic("TODO");
}
@ -775,7 +777,9 @@ static int instream_end_read_jack(struct SoundIoPrivate *si, struct SoundIoInStr
return 0;
}
static int instream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
static int instream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
soundio_panic("TODO");
}

View file

@ -809,7 +809,7 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b
return 0;
}
static int outstream_get_latency_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
static int outstream_get_latency_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, double *out_latency) {
soundio_panic("TODO");
}
@ -1015,7 +1015,7 @@ static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, boo
return 0;
}
static int instream_get_latency_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
static int instream_get_latency_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, double *out_latency) {
soundio_panic("TODO");
}

View file

@ -537,11 +537,11 @@ int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream) {
return si->outstream_clear_buffer(si, os);
}
int soundio_outstream_get_latency(struct SoundIoOutStream *outstream) {
int soundio_outstream_get_latency(struct SoundIoOutStream *outstream, double *out_latency) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
return si->outstream_get_latency(si, os);
return si->outstream_get_latency(si, os, out_latency);
}
static void default_instream_error_callback(struct SoundIoInStream *is, int err) {
@ -653,7 +653,7 @@ int soundio_instream_get_latency(struct SoundIoInStream *instream, double *out_l
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
return si->instream_get_latency(si, is);
return si->instream_get_latency(si, is, out_latency);
}
void soundio_destroy_devices_info(SoundIoDevicesInfo *devices_info) {

View file

@ -147,7 +147,7 @@ struct SoundIoPrivate {
int (*outstream_end_write)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_clear_buffer)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_pause)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, bool pause);
int (*outstream_get_latency)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_get_latency)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, double *out_latency);
int (*instream_open)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
@ -157,7 +157,7 @@ struct SoundIoPrivate {
SoundIoChannelArea **out_areas, int *out_frame_count);
int (*instream_end_read)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_pause)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, bool pause);
int (*instream_get_latency)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_get_latency)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, double *out_latency);
SoundIoBackendData backend_data;
};

View file

@ -1523,7 +1523,9 @@ static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct Sound
return 0;
}
static int outstream_get_latency_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
static int outstream_get_latency_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
soundio_panic("TODO");
}
@ -1924,7 +1926,9 @@ static int instream_end_read_wasapi(struct SoundIoPrivate *si, struct SoundIoInS
return 0;
}
static int instream_get_latency_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
static int instream_get_latency_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
soundio_panic("TODO");
}

View file

@ -47,12 +47,25 @@ static void write_sample_float64ne(char *ptr, double sample) {
static void (*write_sample)(char *ptr, double sample);
static int frames_until_pulse = 0;
static int pulse_frames_left = 0;
static int pulse_frames_left = -1;
static const double PI = 3.14159265358979323846264338328;
static double seconds_offset = 0.0;
static SoundIoRingBuffer pulse_rb;
static void write_time(SoundIoOutStream *outstream) {
double latency;
int err;
if ((err = soundio_outstream_get_latency(outstream, &latency))) {
soundio_panic("getting latency: %s", soundio_strerror(err));
}
double now = soundio_os_get_time();
double audible_time = now + latency;
double *write_ptr = (double *)soundio_ring_buffer_write_ptr(&pulse_rb);
*write_ptr = audible_time;
soundio_ring_buffer_advance_write_ptr(&pulse_rb, sizeof(double));
}
static void write_callback(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) {
double float_sample_rate = outstream->sample_rate;
double seconds_per_frame = 1.0f / float_sample_rate;
@ -77,13 +90,18 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m
for (int frame = 0; frame < frame_count; frame += 1) {
double sample;
if (frames_until_pulse <= 0) {
if (pulse_frames_left <= 0) {
frames_until_pulse = (1.0 + (rand() / (double)RAND_MAX) * 3.0) * float_sample_rate;
pulse_frames_left = 0.05 * float_sample_rate;
sample = 0.0;
} else {
if (pulse_frames_left == -1) {
pulse_frames_left = 0.25 * float_sample_rate;
write_time(outstream); // announce beep start
}
if (pulse_frames_left > 0) {
pulse_frames_left -= 1;
sample = sinf((seconds_offset + frame * seconds_per_frame) * radians_per_second);
} else {
frames_until_pulse = (0.5 + (rand() / (double)RAND_MAX) * 2.0) * float_sample_rate;
pulse_frames_left = -1;
sample = 0.0;
write_time(outstream); // announce beep end
}
} else {
frames_until_pulse -= 1;
@ -105,8 +123,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m
}
static void underflow_callback(struct SoundIoOutStream *outstream) {
static int count = 0;
fprintf(stderr, "underflow %d\n", count++);
soundio_panic("underflow\n");
}
int main(int argc, char **argv) {
@ -186,6 +203,9 @@ int main(int argc, char **argv) {
soundio_panic("No suitable device format available.\n");
}
if ((err = soundio_ring_buffer_init(&pulse_rb, 1024)))
soundio_panic("ring buffer init: %s", soundio_strerror(err));
if ((err = soundio_outstream_open(outstream)))
soundio_panic("unable to open device: %s", soundio_strerror(err));
@ -195,8 +215,25 @@ int main(int argc, char **argv) {
if ((err = soundio_outstream_start(outstream)))
soundio_panic("unable to start device: %s", soundio_strerror(err));
for (;;)
soundio_wait_events(soundio);
bool beep_on = true;
for (;;) {
int fill_count = soundio_ring_buffer_fill_count(&pulse_rb);
if (fill_count >= (int)sizeof(double)) {
double *read_ptr = (double *)soundio_ring_buffer_read_ptr(&pulse_rb);
double audible_time = *read_ptr;
while (audible_time > soundio_os_get_time()) {
// Burn the CPU while we wait for our precisely timed event.
}
if (beep_on) {
fprintf(stderr, "BEEP!\r");
} else {
fprintf(stderr, " \r");
}
fflush(stderr);
beep_on = !beep_on;
soundio_ring_buffer_advance_read_ptr(&pulse_rb, sizeof(double));
}
}
soundio_outstream_destroy(outstream);
soundio_device_unref(device);