From debab8e70f6485ad70cbd6577c2e137b516d8310 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Sep 2015 10:52:53 -0700 Subject: [PATCH] get latency skeleton See #2 --- soundio/soundio.h | 15 +++++++++++++++ src/alsa.cpp | 10 ++++++++++ src/coreaudio.cpp | 10 ++++++++-- src/dummy.cpp | 10 ++++++++++ src/jack.cpp | 9 +++++++++ src/pulseaudio.cpp | 10 ++++++++++ src/soundio.cpp | 14 ++++++++++++++ src/soundio.hpp | 2 ++ src/wasapi.cpp | 10 ++++++++++ 9 files changed, 88 insertions(+), 2 deletions(-) diff --git a/soundio/soundio.h b/soundio/soundio.h index 7f56ea3..03ed33d 100644 --- a/soundio/soundio.h +++ b/soundio/soundio.h @@ -1004,6 +1004,13 @@ SOUNDIO_EXPORT int soundio_outstream_clear_buffer(struct SoundIoOutStream *outst /// device does not support pausing/unpausing. SOUNDIO_EXPORT int soundio_outstream_pause(struct SoundIoOutStream *outstream, bool pause); +/// Obtain the total number of seconds that the next frame you write to the +/// outstream will take to become audible. This includes both software and +/// hardware latency. +/// +/// This function must be called only from within SoundIoOutStream::write_callback. +SOUNDIO_EXPORT int soundio_outstream_get_latency(struct SoundIoOutStream *outstream, + double *out_latency); @@ -1099,6 +1106,14 @@ SOUNDIO_EXPORT int soundio_instream_end_read(struct SoundIoInStream *instream); /// * #SoundIoErrorIncompatibleDevice - device does not support pausing/unpausing SOUNDIO_EXPORT int soundio_instream_pause(struct SoundIoInStream *instream, bool pause); +/// Obtain the number of seconds that the next frame of sound being +/// captured will take to arrive in the buffer, plus the amount of time that is +/// represented in the buffer. This includes both software and hardware latency. +/// +/// This function must be called only from within SoundIoInStream::read_callback. +SOUNDIO_EXPORT int soundio_instream_get_latency(struct SoundIoInStream *instream, + double *out_latency); + // Ring Buffer struct SoundIoRingBuffer; diff --git a/src/alsa.cpp b/src/alsa.cpp index e94efe0..a0285e0 100644 --- a/src/alsa.cpp +++ b/src/alsa.cpp @@ -1468,6 +1468,10 @@ static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre return 0; } +static int outstream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { + soundio_panic("TODO"); +} + static void instream_destroy_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { SoundIoInStreamAlsa *isa = &is->backend_data.alsa; @@ -1738,6 +1742,10 @@ static int instream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoInStream return 0; } +static int instream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) { + soundio_panic("TODO"); +} + int soundio_alsa_init(SoundIoPrivate *si) { SoundIoAlsa *sia = &si->backend_data.alsa; int err; @@ -1818,6 +1826,7 @@ int soundio_alsa_init(SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_alsa; si->outstream_clear_buffer = outstream_clear_buffer_alsa; si->outstream_pause = outstream_pause_alsa; + si->outstream_get_latency = outstream_get_latency_alsa; si->instream_open = instream_open_alsa; si->instream_destroy = instream_destroy_alsa; @@ -1825,6 +1834,7 @@ int soundio_alsa_init(SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_alsa; si->instream_end_read = instream_end_read_alsa; si->instream_pause = instream_pause_alsa; + si->instream_get_latency = instream_get_latency_alsa; return 0; } diff --git a/src/coreaudio.cpp b/src/coreaudio.cpp index b225396..e13850a 100644 --- a/src/coreaudio.cpp +++ b/src/coreaudio.cpp @@ -1052,6 +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) { + soundio_panic("TODO"); +} static OSStatus on_instream_device_overload(AudioObjectID in_object_id, UInt32 in_number_addresses, const AudioObjectPropertyAddress in_addresses[], void *in_client_data) @@ -1305,10 +1308,11 @@ 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) { + soundio_panic("TODO"); +} -// Possible errors: -// * SoundIoErrorNoMem int soundio_coreaudio_init(SoundIoPrivate *si) { SoundIoCoreAudio *sica = &si->backend_data.coreaudio; int err; @@ -1380,6 +1384,7 @@ int soundio_coreaudio_init(SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_ca; si->outstream_clear_buffer = outstream_clear_buffer_ca; si->outstream_pause = outstream_pause_ca; + si->outstream_get_latency = outstream_get_latency_ca; si->instream_open = instream_open_ca; si->instream_destroy = instream_destroy_ca; @@ -1387,6 +1392,7 @@ int soundio_coreaudio_init(SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_ca; si->instream_end_read = instream_end_read_ca; si->instream_pause = instream_pause_ca; + si->instream_get_latency = instream_get_latency_ca; return 0; } diff --git a/src/dummy.cpp b/src/dummy.cpp index 27a696c..11e8ac1 100644 --- a/src/dummy.cpp +++ b/src/dummy.cpp @@ -253,6 +253,10 @@ 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 void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { SoundIoInStreamDummy *isd = &is->backend_data.dummy; @@ -357,6 +361,10 @@ 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 set_all_device_formats(SoundIoDevice *device) { device->format_count = 18; device->formats = allocate(device->format_count); @@ -534,6 +542,7 @@ int soundio_dummy_init(SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_dummy; si->outstream_clear_buffer = outstream_clear_buffer_dummy; si->outstream_pause = outstream_pause_dummy; + si->outstream_get_latency = outstream_get_latency_dummy; si->instream_open = instream_open_dummy; si->instream_destroy = instream_destroy_dummy; @@ -541,6 +550,7 @@ int soundio_dummy_init(SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_dummy; si->instream_end_read = instream_end_read_dummy; si->instream_pause = instream_pause_dummy; + si->instream_get_latency = instream_get_latency_dummy; return 0; } diff --git a/src/jack.cpp b/src/jack.cpp index dd51fdf..a08d0a2 100644 --- a/src/jack.cpp +++ b/src/jack.cpp @@ -572,6 +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) { + soundio_panic("TODO"); +} static void instream_destroy_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) { @@ -772,6 +775,10 @@ 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) { + soundio_panic("TODO"); +} + static void notify_devices_change(SoundIoPrivate *si) { SoundIo *soundio = &si->pub; SoundIoJack *sij = &si->backend_data.jack; @@ -919,6 +926,7 @@ int soundio_jack_init(struct SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_jack; si->outstream_clear_buffer = outstream_clear_buffer_jack; si->outstream_pause = outstream_pause_jack; + si->outstream_get_latency = outstream_get_latency_jack; si->instream_open = instream_open_jack; si->instream_destroy = instream_destroy_jack; @@ -926,6 +934,7 @@ int soundio_jack_init(struct SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_jack; si->instream_end_read = instream_end_read_jack; si->instream_pause = instream_pause_jack; + si->instream_get_latency = instream_get_latency_jack; return 0; } diff --git a/src/pulseaudio.cpp b/src/pulseaudio.cpp index 81cf4a4..7f2a7eb 100644 --- a/src/pulseaudio.cpp +++ b/src/pulseaudio.cpp @@ -809,6 +809,10 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b return 0; } +static int outstream_get_latency_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { + soundio_panic("TODO"); +} + static void recording_stream_state_callback(pa_stream *stream, void *userdata) { SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata; SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; @@ -1011,6 +1015,10 @@ static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, boo return 0; } +static int instream_get_latency_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { + soundio_panic("TODO"); +} + int soundio_pulseaudio_init(SoundIoPrivate *si) { SoundIo *soundio = &si->pub; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; @@ -1084,6 +1092,7 @@ int soundio_pulseaudio_init(SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_pa; si->outstream_clear_buffer = outstream_clear_buffer_pa; si->outstream_pause = outstream_pause_pa; + si->outstream_get_latency = outstream_get_latency_pa; si->instream_open = instream_open_pa; si->instream_destroy = instream_destroy_pa; @@ -1091,6 +1100,7 @@ int soundio_pulseaudio_init(SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_pa; si->instream_end_read = instream_end_read_pa; si->instream_pause = instream_pause_pa; + si->instream_get_latency = instream_get_latency_pa; return 0; } diff --git a/src/soundio.cpp b/src/soundio.cpp index d070826..4b6491d 100644 --- a/src/soundio.cpp +++ b/src/soundio.cpp @@ -537,6 +537,13 @@ int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream) { return si->outstream_clear_buffer(si, os); } +int soundio_outstream_get_latency(struct SoundIoOutStream *outstream) { + SoundIo *soundio = outstream->device->soundio; + SoundIoPrivate *si = (SoundIoPrivate *)soundio; + SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream; + return si->outstream_get_latency(si, os); +} + static void default_instream_error_callback(struct SoundIoInStream *is, int err) { soundio_panic("libsoundio: %s", soundio_strerror(err)); } @@ -642,6 +649,13 @@ int soundio_instream_end_read(struct SoundIoInStream *instream) { return si->instream_end_read(si, is); } +int soundio_instream_get_latency(struct SoundIoInStream *instream, double *out_latency) { + SoundIo *soundio = instream->device->soundio; + SoundIoPrivate *si = (SoundIoPrivate *)soundio; + SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream; + return si->instream_get_latency(si, is); +} + void soundio_destroy_devices_info(SoundIoDevicesInfo *devices_info) { if (!devices_info) return; diff --git a/src/soundio.hpp b/src/soundio.hpp index a26cb5d..42cc5e7 100644 --- a/src/soundio.hpp +++ b/src/soundio.hpp @@ -147,6 +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 (*instream_open)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *); @@ -156,6 +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 *); SoundIoBackendData backend_data; }; diff --git a/src/wasapi.cpp b/src/wasapi.cpp index 499c9ef..7b96f1b 100644 --- a/src/wasapi.cpp +++ b/src/wasapi.cpp @@ -1523,6 +1523,10 @@ 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) { + soundio_panic("TODO"); +} + static void instream_thread_deinit(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { SoundIoInStreamWasapi *isw = &is->backend_data.wasapi; @@ -1920,6 +1924,10 @@ 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) { + soundio_panic("TODO"); +} + static void destroy_wasapi(struct SoundIoPrivate *si) { SoundIoWasapi *siw = &si->backend_data.wasapi; @@ -2073,6 +2081,7 @@ int soundio_wasapi_init(SoundIoPrivate *si) { si->outstream_end_write = outstream_end_write_wasapi; si->outstream_clear_buffer = outstream_clear_buffer_wasapi; si->outstream_pause = outstream_pause_wasapi; + si->outstream_get_latency = outstream_get_latency_wasapi; si->instream_open = instream_open_wasapi; si->instream_destroy = instream_destroy_wasapi; @@ -2080,6 +2089,7 @@ int soundio_wasapi_init(SoundIoPrivate *si) { si->instream_begin_read = instream_begin_read_wasapi; si->instream_end_read = instream_end_read_wasapi; si->instream_pause = instream_pause_wasapi; + si->instream_get_latency = instream_get_latency_wasapi; return 0; }