mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2025-01-03 19:15:30 +00:00
period_duration instead of period_count
This commit is contained in:
parent
7045cb3988
commit
454fab0ffb
53
src/alsa.cpp
53
src/alsa.cpp
|
@ -308,6 +308,20 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle,
|
|||
|
||||
snd_pcm_uframes_t min_frames;
|
||||
snd_pcm_uframes_t max_frames;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_period_size_integer(handle, hwparams)) < 0)
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_period_size_min(hwparams, &min_frames, nullptr)) < 0)
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_period_size_max(hwparams, &max_frames, nullptr)) < 0)
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
|
||||
|
||||
device->period_duration_min = ((double)min_frames) / (double)device->sample_rate_max;
|
||||
device->period_duration_max = ((double)max_frames) / (double)device->sample_rate_max;
|
||||
|
||||
if ((err = snd_pcm_hw_params_get_buffer_size_min(hwparams, &min_frames)) < 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
if ((err = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
|
||||
|
@ -317,26 +331,6 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle,
|
|||
device->buffer_duration_min = ((double)min_frames) / (double)device->sample_rate_max;
|
||||
device->buffer_duration_max = ((double)max_frames) / (double)device->sample_rate_max;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_periods_integer(handle, hwparams)) < 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
||||
dir = 0;
|
||||
if ((err = snd_pcm_hw_params_get_periods_min(hwparams, &num, &dir)) < 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
||||
if (dir != 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
||||
device->period_count_min = num;
|
||||
|
||||
dir = 0;
|
||||
if ((err = snd_pcm_hw_params_get_periods_max(hwparams, &num, &dir)) < 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
||||
if (dir != 0)
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
||||
device->period_count_max = num;
|
||||
|
||||
|
||||
snd_pcm_format_mask_t *fmt_mask;
|
||||
|
@ -438,8 +432,8 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
|
|||
if (device->buffer_duration_min == device->buffer_duration_max)
|
||||
device->buffer_duration_current = device->buffer_duration_min;
|
||||
|
||||
if (device->period_count_min == device->period_count_max)
|
||||
device->period_count_current = device->period_count_min;
|
||||
if (device->period_duration_min == device->period_duration_max)
|
||||
device->period_duration_current = device->period_duration_min;
|
||||
|
||||
// now say that resampling is OK and see what the real min and max is.
|
||||
if ((err = probe_open_device(device, handle, hwparams, 1)) < 0) {
|
||||
|
@ -993,20 +987,22 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t period_frames = ceil(outstream->period_duration * (double)outstream->sample_rate);
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near(osa->handle, hwparams, &period_frames, nullptr)) < 0) {
|
||||
outstream_destroy_alsa(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
outstream->period_duration = ((double)period_frames) / (double)outstream->sample_rate;
|
||||
|
||||
|
||||
snd_pcm_uframes_t buffer_size_frames = ceil(outstream->buffer_duration * (double)outstream->sample_rate);
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_buffer_size_near(osa->handle, hwparams, &buffer_size_frames)) < 0) {
|
||||
outstream_destroy_alsa(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
outstream->buffer_duration = ((double)buffer_size_frames) / (double)outstream->sample_rate;
|
||||
|
||||
unsigned int actual_periods_count = outstream->period_count;
|
||||
if ((err = snd_pcm_hw_params_set_periods_near(osa->handle, hwparams, &actual_periods_count, nullptr)) < 0) {
|
||||
outstream_destroy_alsa(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
outstream->period_count = actual_periods_count;
|
||||
|
||||
|
||||
snd_pcm_uframes_t period_size;
|
||||
|
@ -1017,6 +1013,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
|
||||
// write the hardware parameters to device
|
||||
if ((err = snd_pcm_hw_params(osa->handle, hwparams)) < 0) {
|
||||
//assert(err != -EINVAL);
|
||||
outstream_destroy_alsa(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ struct SoundIoOutStreamDummy {
|
|||
struct SoundIoOsCond *cond;
|
||||
atomic_flag abort_flag;
|
||||
int buffer_size;
|
||||
double period;
|
||||
struct SoundIoRingBuffer ring_buffer;
|
||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
@ -44,7 +43,7 @@ static void playback_thread_run(void *arg) {
|
|||
|
||||
double time_per_frame = 1.0 / (double)outstream->sample_rate;
|
||||
while (osd->abort_flag.test_and_set()) {
|
||||
soundio_os_cond_timed_wait(osd->cond, nullptr, osd->period);
|
||||
soundio_os_cond_timed_wait(osd->cond, nullptr, outstream->period_duration);
|
||||
|
||||
double now = soundio_os_get_time();
|
||||
double total_time = now - start_time;
|
||||
|
@ -142,7 +141,6 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
|
|||
os->backend_data = osd;
|
||||
|
||||
osd->buffer_size = outstream->bytes_per_frame * outstream->buffer_duration;
|
||||
osd->period = outstream->buffer_duration / (double)outstream->period_count;
|
||||
|
||||
soundio_ring_buffer_init(&osd->ring_buffer, osd->buffer_size);
|
||||
|
||||
|
@ -337,9 +335,9 @@ int soundio_dummy_init(SoundIoPrivate *si) {
|
|||
device->sample_rate_min = 2;
|
||||
device->sample_rate_max = 5644800;
|
||||
device->sample_rate_current = 48000;
|
||||
device->period_count_min = 1;
|
||||
device->period_count_max = 16;
|
||||
device->period_count_current = 2;
|
||||
device->period_duration_min = 0.01;
|
||||
device->period_duration_max = 2;
|
||||
device->period_duration_current = 0.05;
|
||||
device->purpose = SoundIoDevicePurposeOutput;
|
||||
|
||||
if (si->safe_devices_info->output_devices.append(device)) {
|
||||
|
@ -388,9 +386,9 @@ int soundio_dummy_init(SoundIoPrivate *si) {
|
|||
device->sample_rate_min = 2;
|
||||
device->sample_rate_max = 5644800;
|
||||
device->sample_rate_current = 48000;
|
||||
device->period_count_min = 1;
|
||||
device->period_count_max = 16;
|
||||
device->period_count_current = 2;
|
||||
device->period_duration_min = 0.01;
|
||||
device->period_duration_max = 2;
|
||||
device->period_duration_current = 0.05;
|
||||
device->purpose = SoundIoDevicePurposeInput;
|
||||
|
||||
if (si->safe_devices_info->input_devices.append(device)) {
|
||||
|
|
|
@ -296,6 +296,7 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
|
|||
//device->default_latency = usec_to_sec(info->configured_latency);
|
||||
// TODO set min, max, current sample rate
|
||||
//device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
// TODO set min, max, current period size
|
||||
device->purpose = SoundIoDevicePurposeOutput;
|
||||
|
||||
if (sipa->current_devices_info->output_devices.append(device))
|
||||
|
@ -330,6 +331,7 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
|
|||
//device->default_latency = usec_to_sec(info->configured_latency);
|
||||
// TODO set min, max, current sample rate
|
||||
//device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
|
||||
// TODO set min, max, current period size
|
||||
device->purpose = SoundIoDevicePurposeInput;
|
||||
|
||||
if (sipa->current_devices_info->input_devices.append(device))
|
||||
|
@ -623,6 +625,8 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
|||
sample_spec.channels = outstream->layout.channel_count;
|
||||
pa_channel_map channel_map = to_pulseaudio_channel_map(&outstream->layout);
|
||||
|
||||
// TODO handle period_duration
|
||||
|
||||
// TODO make this value ("SoundIo") configurable
|
||||
ospa->stream = pa_stream_new(sipa->pulse_context, "SoundIo", &sample_spec, &channel_map);
|
||||
if (!ospa->stream) {
|
||||
|
@ -796,6 +800,8 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
|
|||
|
||||
pa_channel_map channel_map = to_pulseaudio_channel_map(&instream->layout);
|
||||
|
||||
// TODO handle period_duration
|
||||
|
||||
// TODO make this value ("SoundIo") private
|
||||
ispa->stream = pa_stream_new(sipa->pulse_context, "SoundIo", &sample_spec, &channel_map);
|
||||
if (!ispa->stream) {
|
||||
|
|
|
@ -385,7 +385,7 @@ struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device)
|
|||
outstream->layout = soundio_device_supports_layout(device, stereo) ? *stereo : device->layouts[0];
|
||||
outstream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
|
||||
outstream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max);
|
||||
outstream->period_count = clamp(device->period_count_min, 2, device->period_count_max);
|
||||
outstream->period_duration = -1.0;
|
||||
|
||||
return outstream;
|
||||
}
|
||||
|
@ -394,6 +394,11 @@ int soundio_outstream_open(struct SoundIoOutStream *outstream) {
|
|||
if (outstream->format <= SoundIoFormatInvalid)
|
||||
return SoundIoErrorInvalid;
|
||||
|
||||
if (outstream->period_duration == -1.0) {
|
||||
outstream->period_duration = clamp(outstream->device->period_duration_min,
|
||||
outstream->buffer_duration / 2.0, outstream->device->period_duration_max);
|
||||
}
|
||||
|
||||
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
|
||||
outstream->bytes_per_frame = soundio_get_bytes_per_frame(outstream->format, outstream->layout.channel_count);
|
||||
outstream->bytes_per_sample = soundio_get_bytes_per_sample(outstream->format);
|
||||
|
@ -441,7 +446,7 @@ struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device) {
|
|||
instream->layout = soundio_device_supports_layout(device, stereo) ? *stereo : device->layouts[0];
|
||||
instream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
|
||||
instream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max);
|
||||
instream->period_count = clamp(device->period_count_min, 8, device->period_count_max);
|
||||
instream->period_duration = -1.0;
|
||||
|
||||
return instream;
|
||||
}
|
||||
|
@ -449,6 +454,12 @@ struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device) {
|
|||
int soundio_instream_open(struct SoundIoInStream *instream) {
|
||||
if (instream->format <= SoundIoFormatInvalid)
|
||||
return SoundIoErrorInvalid;
|
||||
|
||||
if (instream->period_duration == -1.0) {
|
||||
instream->period_duration = clamp(instream->device->period_duration_min,
|
||||
instream->buffer_duration / 8.0, instream->device->period_duration_max);
|
||||
}
|
||||
|
||||
instream->bytes_per_frame = soundio_get_bytes_per_frame(instream->format, instream->layout.channel_count);
|
||||
instream->bytes_per_sample = soundio_get_bytes_per_sample(instream->format);
|
||||
SoundIo *soundio = instream->device->soundio;
|
||||
|
|
|
@ -249,11 +249,11 @@ struct SoundIoDevice {
|
|||
double buffer_duration_max;
|
||||
double buffer_duration_current;
|
||||
|
||||
// How many slices it is possible to cut the buffer into.
|
||||
// TODO change this to duration units?
|
||||
int period_count_min;
|
||||
int period_count_max;
|
||||
int period_count_current;
|
||||
// Period duration in seconds. After this much time passes, write_callback
|
||||
// is called.
|
||||
double period_duration_min;
|
||||
double period_duration_max;
|
||||
double period_duration_current;
|
||||
|
||||
// Tells whether this device is an input device or an output device.
|
||||
enum SoundIoDevicePurpose purpose;
|
||||
|
@ -292,19 +292,17 @@ struct SoundIoOutStream {
|
|||
struct SoundIoChannelLayout layout;
|
||||
|
||||
// Buffer duration in seconds.
|
||||
// (buffer_duration / period_count) is the latency; how much time it takes
|
||||
// for a sample put in the buffer to get played.
|
||||
// After you call soundio_outstream_open this value is replaced with the
|
||||
// actual duration, as near to this value as possible.
|
||||
// Defaults to 1 second (and then clamped into range).
|
||||
double buffer_duration;
|
||||
|
||||
// How many slices the buffer is cut into. The IRQ will happen every
|
||||
// (buffer_frame_count / period_count) frames.
|
||||
// After you call soundio_outstream_open this value is replaced with the
|
||||
// actual period count, as near to this value as possible.
|
||||
// Defaults to 2 (and then clamped into range).
|
||||
int period_count;
|
||||
// `period_duration` is the latency; how much time it takes
|
||||
// for a sample put in the buffer to get played.
|
||||
// After you call `soundio_outstream_open` this value is replaced with the
|
||||
// actual period duration, as near to this value as possible.
|
||||
// Defaults to `buffer_duration / 2` (and then clamped into range).
|
||||
double period_duration;
|
||||
|
||||
// Defaults to NULL.
|
||||
void *userdata;
|
||||
|
@ -341,11 +339,10 @@ struct SoundIoInStream {
|
|||
// Defaults to 1 second (and then clamped into range).
|
||||
double buffer_duration;
|
||||
|
||||
// How many slices the buffer is cut into. The IRQ will happen every
|
||||
// (buffer_duration / period_count) seconds, and that is the latency of the
|
||||
// captured audio. This value must be a power of 2.
|
||||
// Defaults to 8.
|
||||
int period_count;
|
||||
// The latency of the captured audio. After this many seconds pass,
|
||||
// `read_callback` is called.
|
||||
// Defaults to `buffer_duration / 8`.
|
||||
double period_duration;
|
||||
|
||||
void *userdata;
|
||||
void (*read_callback)(struct SoundIoInStream *);
|
||||
|
|
Loading…
Reference in a new issue