mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2025-01-03 14:15:47 +00:00
Delete the concept of prebuffering
This commit is contained in:
parent
d3cf8f02db
commit
44569708a0
|
@ -20,10 +20,10 @@ behavior on every platform.
|
|||
## Features and Limitations
|
||||
|
||||
* Supported backends:
|
||||
- [JACK](http://jackaudio.org/)
|
||||
- [PulseAudio](http://www.freedesktop.org/wiki/Software/PulseAudio/)
|
||||
- [ALSA](http://www.alsa-project.org/)
|
||||
- Dummy (silence)
|
||||
- [JACK](http://jackaudio.org/)
|
||||
- (planned) [CoreAudio](https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html)
|
||||
- (planned) [WASAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455%28v=vs.85%29.aspx)
|
||||
- (planned) [ASIO](http://www.asio4all.com/)
|
||||
|
@ -245,19 +245,15 @@ view `coverage/index.html` in a browser.
|
|||
0. implement CoreAudio (OSX) backend, get examples working
|
||||
0. implement WASAPI (Windows) backend, get examples working
|
||||
0. implement ASIO (Windows) backend, get examples working
|
||||
0. JACK: implement prebuffering ...or delete prebuffering as a concept
|
||||
0. Avoid calling `soundio_panic` in PulseAudio.
|
||||
0. Figure out a way to test prebuf. I suspect prebuf not working for ALSA
|
||||
which is why we have to pre-fill the ring buffer with silence for
|
||||
the microphone example.
|
||||
0. PulseAudio: when prebuf gets set to 0 need to pass `PA_STREAM_START_CORKED`.
|
||||
0. clear buffer maybe could take an argument to say how many frames to not clear
|
||||
0. In ALSA do we need to wake up the poll when destroying the in or out stream?
|
||||
0. Verify that JACK xrun callback context is the same as process callback.
|
||||
If not, might need to hav xrun callback set a flag and have process callback
|
||||
call the underflow callback.
|
||||
0. Detect PulseAudio server going offline and emit `on_backend_disconnect`.
|
||||
0. Instead fo open(), start(), pause(), open() starts it and it starts paused.
|
||||
0. Create a test for clearing the playback buffer and prebuffering.
|
||||
0. Create a test for pausing and resuming input and output streams.
|
||||
0. Create a test for the latency / synchronization API.
|
||||
- Input is an audio file and some events indexed at particular frame - when
|
||||
|
@ -290,7 +286,6 @@ view `coverage/index.html` in a browser.
|
|||
0. make rtprio warning a callback and have existing behavior be the default callback
|
||||
0. write detailed docs on buffer underflows explaining when they occur, what state
|
||||
changes are related to them, and how to recover from them.
|
||||
0. API to trigger playback even if prebuf condition isn't met yet.
|
||||
0. Consider testing on FreeBSD
|
||||
|
||||
## Planned Uses for libsoundio
|
||||
|
|
|
@ -61,7 +61,6 @@ static void read_callback(struct SoundIoInStream *instream, int available_frame_
|
|||
int write_count = min_int(available_frame_count, free_count);
|
||||
int frames_left = write_count;
|
||||
|
||||
|
||||
for (;;) {
|
||||
int frame_count = frames_left;
|
||||
|
||||
|
@ -148,7 +147,7 @@ static void underflow_callback(struct SoundIoOutStream *outstream) {
|
|||
}
|
||||
|
||||
static int usage(char *exe) {
|
||||
fprintf(stderr, "Usage: %s [--dummy] [--alsa] [--pulseaudio] [--in-device name] [--out-device name]\n", exe);
|
||||
fprintf(stderr, "Usage: %s [--dummy] [--alsa] [--pulseaudio] [--jack] [--in-device name] [--out-device name]\n", exe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -165,6 +164,8 @@ int main(int argc, char **argv) {
|
|||
backend = SoundIoBackendAlsa;
|
||||
} else if (strcmp("--pulseaudio", arg) == 0) {
|
||||
backend = SoundIoBackendPulseAudio;
|
||||
} else if (strcmp("--jack", arg) == 0) {
|
||||
backend = SoundIoBackendJack;
|
||||
} else if (strcmp("--in-device", arg) == 0) {
|
||||
if (++i >= argc) {
|
||||
return usage(exe);
|
||||
|
@ -290,7 +291,6 @@ int main(int argc, char **argv) {
|
|||
outstream->period_duration = 0.1;
|
||||
outstream->write_callback = write_callback;
|
||||
outstream->underflow_callback = underflow_callback;
|
||||
outstream->prebuf_duration = 0.0;
|
||||
|
||||
if ((err = soundio_outstream_open(outstream)))
|
||||
panic("unable to open output stream: %s", soundio_strerror(err));
|
||||
|
|
20
src/alsa.cpp
20
src/alsa.cpp
|
@ -1086,8 +1086,6 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
outstream->period_duration = clamp(device->period_duration_min,
|
||||
outstream->buffer_duration / 2.0, device->period_duration_max);
|
||||
}
|
||||
if (outstream->prebuf_duration == -1.0)
|
||||
outstream->prebuf_duration = outstream->buffer_duration;
|
||||
|
||||
int ch_count = outstream->layout.channel_count;
|
||||
|
||||
|
@ -1196,8 +1194,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t prebuf_frames = ceil(outstream->prebuf_duration * (double)outstream->sample_rate);
|
||||
if ((err = snd_pcm_sw_params_set_start_threshold(osa->handle, swparams, prebuf_frames)) < 0) {
|
||||
if ((err = snd_pcm_sw_params_set_start_threshold(osa->handle, swparams, 0)) < 0) {
|
||||
outstream_destroy_alsa(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
@ -1243,16 +1240,23 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
}
|
||||
|
||||
static int outstream_start_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
||||
SoundIoOutStream *outstream = &os->pub;
|
||||
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
|
||||
|
||||
assert(!osa->thread);
|
||||
|
||||
osa->thread_exit_flag.test_and_set();
|
||||
// Give the API user a chance to fill the buffer before playback commences.
|
||||
snd_pcm_sframes_t avail = snd_pcm_avail_update(osa->handle);
|
||||
int err;
|
||||
if ((err = soundio_os_thread_create(outstream_thread_run, os, true, &osa->thread))) {
|
||||
outstream_destroy_alsa(si, os);
|
||||
return err;
|
||||
if (avail < 0) {
|
||||
if ((err = xrun_recovery(os, avail)) < 0)
|
||||
return SoundIoErrorStreaming;
|
||||
}
|
||||
outstream->write_callback(outstream, avail);
|
||||
|
||||
osa->thread_exit_flag.test_and_set();
|
||||
if ((err = soundio_os_thread_create(outstream_thread_run, os, true, &osa->thread)))
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,12 @@ static void playback_thread_run(void *arg) {
|
|||
SoundIoOutStream *outstream = &os->pub;
|
||||
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
|
||||
|
||||
double start_time = soundio_os_get_time();
|
||||
osd->playback_start_time = start_time;
|
||||
osd->frames_consumed = 0;
|
||||
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
|
||||
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
|
||||
int fill_frames = fill_bytes / outstream->bytes_per_frame;
|
||||
int free_frames = free_bytes / outstream->bytes_per_frame;
|
||||
osd->prebuf_frames_left = osd->prebuf_frame_count - fill_frames;
|
||||
outstream->write_callback(outstream, free_frames);
|
||||
double start_time = soundio_os_get_time();
|
||||
long frames_consumed = 0;
|
||||
|
||||
while (osd->abort_flag.test_and_set()) {
|
||||
double now = soundio_os_get_time();
|
||||
|
@ -39,22 +36,20 @@ static void playback_thread_run(void *arg) {
|
|||
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
|
||||
int fill_frames = fill_bytes / outstream->bytes_per_frame;
|
||||
int free_frames = free_bytes / outstream->bytes_per_frame;
|
||||
if (osd->prebuf_frames_left > 0) {
|
||||
outstream->write_callback(outstream, free_frames);
|
||||
continue;
|
||||
}
|
||||
|
||||
double total_time = soundio_os_get_time() - osd->playback_start_time;
|
||||
double total_time = soundio_os_get_time() - start_time;
|
||||
long total_frames = total_time * outstream->sample_rate;
|
||||
int frames_to_kill = total_frames - osd->frames_consumed;
|
||||
int frames_to_kill = total_frames - frames_consumed;
|
||||
int read_count = min(frames_to_kill, fill_frames);
|
||||
int byte_count = read_count * outstream->bytes_per_frame;
|
||||
soundio_ring_buffer_advance_read_ptr(&osd->ring_buffer, byte_count);
|
||||
osd->frames_consumed += read_count;
|
||||
frames_consumed += read_count;
|
||||
|
||||
if (frames_to_kill > read_count) {
|
||||
osd->prebuf_frames_left = osd->prebuf_frame_count;
|
||||
if (frames_to_kill > fill_frames) {
|
||||
outstream->underflow_callback(outstream);
|
||||
outstream->write_callback(outstream, free_frames);
|
||||
frames_consumed = 0;
|
||||
start_time = soundio_os_get_time();
|
||||
} else if (free_frames > 0) {
|
||||
outstream->write_callback(outstream, free_frames);
|
||||
}
|
||||
|
@ -70,26 +65,33 @@ static void capture_thread_run(void *arg) {
|
|||
double start_time = soundio_os_get_time();
|
||||
while (isd->abort_flag.test_and_set()) {
|
||||
double now = soundio_os_get_time();
|
||||
double total_time = now - start_time;
|
||||
long total_frames = total_time * instream->sample_rate;
|
||||
int frames_to_kill = total_frames - frames_consumed;
|
||||
int free_bytes = soundio_ring_buffer_free_count(&isd->ring_buffer);
|
||||
int free_frames = free_bytes / instream->bytes_per_frame;
|
||||
int write_count = min(frames_to_kill, free_frames);
|
||||
int frames_left = max(frames_to_kill - write_count, 0);
|
||||
int byte_count = write_count * instream->bytes_per_frame;
|
||||
soundio_ring_buffer_advance_write_ptr(&isd->ring_buffer, byte_count);
|
||||
frames_consumed += write_count;
|
||||
|
||||
isd->hole_size += frames_left;
|
||||
if (write_count > 0)
|
||||
instream->read_callback(instream, write_count);
|
||||
now = soundio_os_get_time();
|
||||
double time_passed = now - start_time;
|
||||
double next_period = start_time +
|
||||
ceil(time_passed / instream->period_duration) * instream->period_duration;
|
||||
double relative_time = next_period - now;
|
||||
soundio_os_cond_timed_wait(isd->cond, nullptr, relative_time);
|
||||
|
||||
int fill_bytes = soundio_ring_buffer_fill_count(&isd->ring_buffer);
|
||||
int free_bytes = soundio_ring_buffer_capacity(&isd->ring_buffer) - fill_bytes;
|
||||
int fill_frames = fill_bytes / instream->bytes_per_frame;
|
||||
int free_frames = free_bytes / instream->bytes_per_frame;
|
||||
|
||||
double total_time = soundio_os_get_time() - start_time;
|
||||
long total_frames = total_time * instream->sample_rate;
|
||||
int frames_to_kill = total_frames - frames_consumed;
|
||||
int write_count = min(frames_to_kill, free_frames);
|
||||
int byte_count = write_count * instream->bytes_per_frame;
|
||||
soundio_ring_buffer_advance_write_ptr(&isd->ring_buffer, byte_count);
|
||||
frames_consumed += write_count;
|
||||
|
||||
if (frames_to_kill > free_frames) {
|
||||
// TODO overflow callback
|
||||
frames_consumed = 0;
|
||||
start_time = soundio_os_get_time();
|
||||
}
|
||||
if (fill_frames > 0) {
|
||||
instream->read_callback(instream, fill_frames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,11 +162,6 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
osd->buffer_frame_count = actual_capacity / outstream->bytes_per_frame;
|
||||
outstream->buffer_duration = osd->buffer_frame_count / (double) outstream->sample_rate;
|
||||
|
||||
if (outstream->prebuf_duration == -1.0)
|
||||
outstream->prebuf_duration = outstream->buffer_duration;
|
||||
outstream->prebuf_duration = min(outstream->prebuf_duration, outstream->buffer_duration);
|
||||
osd->prebuf_frame_count = ceil(outstream->prebuf_duration * (double) outstream->sample_rate);
|
||||
|
||||
osd->cond = soundio_os_cond_create();
|
||||
if (!osd->cond) {
|
||||
outstream_destroy_dummy(si, os);
|
||||
|
@ -231,20 +228,12 @@ static int outstream_end_write_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate
|
|||
SoundIoOutStream *outstream = &os->pub;
|
||||
int byte_count = frame_count * outstream->bytes_per_frame;
|
||||
soundio_ring_buffer_advance_write_ptr(&osd->ring_buffer, byte_count);
|
||||
if (osd->prebuf_frames_left > 0) {
|
||||
osd->prebuf_frames_left -= frame_count;
|
||||
if (osd->prebuf_frames_left <= 0) {
|
||||
osd->playback_start_time = soundio_os_get_time();
|
||||
osd->frames_consumed = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int outstream_clear_buffer_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
||||
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
|
||||
soundio_ring_buffer_clear(&osd->ring_buffer);
|
||||
osd->prebuf_frames_left = osd->prebuf_frame_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -329,13 +318,6 @@ static int instream_begin_read_dummy(SoundIoPrivate *si,
|
|||
assert(*frame_count >= 0);
|
||||
assert(*frame_count <= isd->buffer_frame_count);
|
||||
|
||||
if (isd->hole_size > 0) {
|
||||
*out_areas = nullptr;
|
||||
isd->read_frame_count = min(isd->hole_size, *frame_count);
|
||||
*frame_count = isd->read_frame_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fill_byte_count = soundio_ring_buffer_fill_count(&isd->ring_buffer);
|
||||
int fill_frame_count = fill_byte_count / instream->bytes_per_frame;
|
||||
isd->read_frame_count = min(*frame_count, fill_frame_count);
|
||||
|
@ -357,14 +339,8 @@ static int instream_begin_read_dummy(SoundIoPrivate *si,
|
|||
static int instream_end_read_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
|
||||
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
|
||||
SoundIoInStream *instream = &is->pub;
|
||||
|
||||
if (isd->hole_size > 0) {
|
||||
isd->hole_size -= isd->read_frame_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int byte_count = isd->read_frame_count * instream->bytes_per_frame;
|
||||
soundio_ring_buffer_advance_write_ptr(&isd->ring_buffer, byte_count);
|
||||
soundio_ring_buffer_advance_read_ptr(&isd->ring_buffer, byte_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -493,7 +469,7 @@ int soundio_dummy_init(SoundIoPrivate *si) {
|
|||
device->ref_count = 1;
|
||||
device->soundio = soundio;
|
||||
device->name = strdup("dummy-in");
|
||||
device->description = strdup("Dummy input device");
|
||||
device->description = strdup("Dummy Input Device");
|
||||
if (!device->name || !device->description) {
|
||||
soundio_device_unref(device);
|
||||
destroy_dummy(si);
|
||||
|
|
|
@ -31,9 +31,6 @@ struct SoundIoOutStreamDummy {
|
|||
atomic_flag abort_flag;
|
||||
int buffer_frame_count;
|
||||
struct SoundIoRingBuffer ring_buffer;
|
||||
int prebuf_frame_count;
|
||||
int prebuf_frames_left;
|
||||
long frames_consumed;
|
||||
double playback_start_time;
|
||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
@ -45,7 +42,6 @@ struct SoundIoInStreamDummy {
|
|||
int read_frame_count;
|
||||
int buffer_frame_count;
|
||||
struct SoundIoRingBuffer ring_buffer;
|
||||
int hole_size;
|
||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
|
|
|
@ -428,7 +428,6 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
|
|||
|
||||
outstream->buffer_duration = 0.0;
|
||||
outstream->period_duration = device->period_duration_current;
|
||||
outstream->prebuf_duration = 0.0;
|
||||
osj->period_size = sij->period_size;
|
||||
|
||||
jack_status_t status;
|
||||
|
@ -573,8 +572,6 @@ static int outstream_end_write_jack(struct SoundIoPrivate *si, struct SoundIoOut
|
|||
}
|
||||
|
||||
static int outstream_clear_buffer_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||
// JACK does not support `prebuf` which is the same as a `prebuf` value of 0,
|
||||
// which means that clearing the buffer is always successful and does nothing.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -637,7 +637,7 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
|||
|
||||
ospa->buffer_attr.maxlength = UINT32_MAX;
|
||||
ospa->buffer_attr.tlength = UINT32_MAX;
|
||||
ospa->buffer_attr.prebuf = UINT32_MAX;
|
||||
ospa->buffer_attr.prebuf = 0;
|
||||
ospa->buffer_attr.minreq = UINT32_MAX;
|
||||
ospa->buffer_attr.fragsize = UINT32_MAX;
|
||||
|
||||
|
@ -649,12 +649,6 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
|||
ospa->buffer_attr.maxlength = buffer_length;
|
||||
ospa->buffer_attr.tlength = buffer_length;
|
||||
}
|
||||
if (outstream->prebuf_duration >= 0.0) {
|
||||
int prebuf_length = outstream->bytes_per_frame *
|
||||
ceil(outstream->prebuf_duration * bytes_per_second / (double)outstream->bytes_per_frame);
|
||||
|
||||
ospa->buffer_attr.prebuf = prebuf_length;
|
||||
}
|
||||
|
||||
pa_threaded_mainloop_unlock(sipa->main_loop);
|
||||
|
||||
|
@ -684,8 +678,6 @@ static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
|||
const pa_buffer_attr *attr = pa_stream_get_buffer_attr(ospa->stream);
|
||||
outstream->buffer_duration = (attr->maxlength /
|
||||
(double)outstream->bytes_per_frame) / (double)outstream->sample_rate;
|
||||
outstream->prebuf_duration = (attr->prebuf /
|
||||
(double)outstream->bytes_per_frame) / (double)outstream->sample_rate;
|
||||
|
||||
pa_threaded_mainloop_unlock(sipa->main_loop);
|
||||
|
||||
|
@ -842,7 +834,7 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
|
|||
|
||||
ispa->buffer_attr.maxlength = UINT32_MAX;
|
||||
ispa->buffer_attr.tlength = UINT32_MAX;
|
||||
ispa->buffer_attr.prebuf = UINT32_MAX;
|
||||
ispa->buffer_attr.prebuf = 0;
|
||||
ispa->buffer_attr.minreq = UINT32_MAX;
|
||||
ispa->buffer_attr.fragsize = UINT32_MAX;
|
||||
|
||||
|
|
|
@ -359,8 +359,6 @@ struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device)
|
|||
outstream->error_callback = default_outstream_error_callback;
|
||||
outstream->underflow_callback = default_underflow_callback;
|
||||
|
||||
outstream->prebuf_duration = -1.0;
|
||||
|
||||
return outstream;
|
||||
}
|
||||
|
||||
|
|
|
@ -357,14 +357,6 @@ struct SoundIoOutStream {
|
|||
// sets `PA_STREAM_ADJUST_LATENCY` and is the value used for `fragsize`.
|
||||
double period_duration;
|
||||
|
||||
// How many seconds need to be in the buffer before playback will commence.
|
||||
// If a buffer underflow occurs, this prebuffering will be again enabled.
|
||||
// This value defaults to being the same as `buffer_duration`.
|
||||
// After you call `soundio_outstream_open` this value is replaced with the
|
||||
// actual `prebuf_duration`, as near to this value as possible.
|
||||
// JACK does not support prebuffering; `prebuf_duration` is effectively 0.
|
||||
double prebuf_duration;
|
||||
|
||||
// Defaults to NULL. Put whatever you want here.
|
||||
void *userdata;
|
||||
// In this callback, you call `soundio_outstream_begin_write` and
|
||||
|
@ -619,12 +611,15 @@ bool soundio_device_supports_layout(struct SoundIoDevice *device,
|
|||
// Allocates memory and sets defaults. Next you should fill out the struct fields
|
||||
// and then call `soundio_outstream_open`.
|
||||
struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device);
|
||||
|
||||
int soundio_outstream_open(struct SoundIoOutStream *outstream);
|
||||
|
||||
// You may not call this function from the `write_callback` thread context.
|
||||
void soundio_outstream_destroy(struct SoundIoOutStream *outstream);
|
||||
|
||||
// After you call this function, `buffer_duration` and `period_duration` are
|
||||
// set to the correct values, if available.
|
||||
// The next thing to do is call `soundio_instream_start`.
|
||||
int soundio_outstream_open(struct SoundIoOutStream *outstream);
|
||||
|
||||
// After you call this function, `write_callback` will be called.
|
||||
int soundio_outstream_start(struct SoundIoOutStream *outstream);
|
||||
|
||||
// Call this function when you are ready to begin writing to the device buffer.
|
||||
|
@ -646,7 +641,7 @@ int soundio_outstream_begin_write(struct SoundIoOutStream *outstream,
|
|||
// You must call this function only from the `write_callback` thread context.
|
||||
int soundio_outstream_end_write(struct SoundIoOutStream *outstream, int frame_count);
|
||||
|
||||
// Clears the output stream buffer and the stream goes into prebuffering mode.
|
||||
// Clears the output stream buffer.
|
||||
// You must call this function only from the `write_callback` thread context.
|
||||
int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream);
|
||||
|
||||
|
@ -663,11 +658,15 @@ int soundio_outstream_pause(struct SoundIoOutStream *outstream, bool pause);
|
|||
// Allocates memory and sets defaults. Next you should fill out the struct fields
|
||||
// and then call `soundio_instream_open`.
|
||||
struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device);
|
||||
// You must not call this function from `read_callback`.
|
||||
// You may not call this function from `read_callback`.
|
||||
void soundio_instream_destroy(struct SoundIoInStream *instream);
|
||||
|
||||
// After you call this function, `buffer_duration` and `period_duration` are
|
||||
// set to the correct values, if available.
|
||||
// The next thing to do is call `soundio_instream_start`.
|
||||
int soundio_instream_open(struct SoundIoInStream *instream);
|
||||
|
||||
// After you call this function, `read_callback` will be called.
|
||||
int soundio_instream_start(struct SoundIoInStream *instream);
|
||||
|
||||
// Call this function when you are ready to begin reading from the device
|
||||
|
|
Loading…
Reference in a new issue