mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 18:55:38 +00:00
parent
adb3cd88ee
commit
e444b8823b
|
@ -1004,9 +1004,12 @@ 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.
|
||||
/// Obtain the total number of seconds that the next frame written after the
|
||||
/// last frame written with ::soundio_outstream_end_write will take to become
|
||||
/// audible. This includes both software and hardware latency. In other words,
|
||||
/// if you call this function directly after calling ::soundio_outstream_end_write,
|
||||
/// this gives you the number of seconds that the next frame written will take
|
||||
/// to become audible.
|
||||
///
|
||||
/// This function must be called only from within SoundIoOutStream::write_callback.
|
||||
SOUNDIO_EXPORT int soundio_outstream_get_latency(struct SoundIoOutStream *outstream,
|
||||
|
|
23
src/jack.cpp
23
src/jack.cpp
|
@ -214,6 +214,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
|
|||
djp->full_name = soundio_str_dupe(port->full_name, port->full_name_len);
|
||||
djp->full_name_len = port->full_name_len;
|
||||
djp->channel_id = port->channel_id;
|
||||
djp->latency_range = port->latency_range;
|
||||
|
||||
if (!djp->full_name) {
|
||||
jack_free(port_names);
|
||||
|
@ -469,6 +470,8 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
|
|||
jack_on_shutdown(osj->client, outstream_shutdown_callback, os);
|
||||
|
||||
|
||||
jack_nframes_t max_port_latency = 0;
|
||||
|
||||
// register ports and map channels
|
||||
int connected_count = 0;
|
||||
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
|
||||
|
@ -490,11 +493,13 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
|
|||
osjp->dest_port_name = djp->full_name;
|
||||
osjp->dest_port_name_len = djp->full_name_len;
|
||||
connected_count += 1;
|
||||
max_port_latency = max(max_port_latency, djp->latency_range.max);
|
||||
}
|
||||
}
|
||||
// If nothing got connected, channel layouts aren't working. Just send the
|
||||
// data in the order of the ports.
|
||||
if (connected_count == 0) {
|
||||
max_port_latency = 0;
|
||||
outstream->layout_error = SoundIoErrorIncompatibleDevice;
|
||||
|
||||
int ch_count = min(outstream->layout.channel_count, dj->port_count);
|
||||
|
@ -503,9 +508,12 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
|
|||
SoundIoDeviceJackPort *djp = &dj->ports[ch];
|
||||
osjp->dest_port_name = djp->full_name;
|
||||
osjp->dest_port_name_len = djp->full_name_len;
|
||||
max_port_latency = max(max_port_latency, djp->latency_range.max);
|
||||
}
|
||||
}
|
||||
|
||||
osj->hardware_latency = max_port_latency / (double)outstream->sample_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -575,7 +583,9 @@ static int outstream_clear_buffer_jack(struct SoundIoPrivate *si, struct SoundIo
|
|||
static int outstream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
|
||||
double *out_latency)
|
||||
{
|
||||
soundio_panic("TODO");
|
||||
SoundIoOutStreamJack *osj = &os->backend_data.jack;
|
||||
*out_latency = osj->hardware_latency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -684,6 +694,8 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
|
|||
}
|
||||
jack_on_shutdown(isj->client, instream_shutdown_callback, is);
|
||||
|
||||
jack_nframes_t max_port_latency = 0;
|
||||
|
||||
// register ports and map channels
|
||||
int connected_count = 0;
|
||||
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
|
||||
|
@ -705,11 +717,13 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
|
|||
isjp->source_port_name = djp->full_name;
|
||||
isjp->source_port_name_len = djp->full_name_len;
|
||||
connected_count += 1;
|
||||
max_port_latency = max(max_port_latency, djp->latency_range.max);
|
||||
}
|
||||
}
|
||||
// If nothing got connected, channel layouts aren't working. Just send the
|
||||
// data in the order of the ports.
|
||||
if (connected_count == 0) {
|
||||
max_port_latency = 0;
|
||||
instream->layout_error = SoundIoErrorIncompatibleDevice;
|
||||
|
||||
int ch_count = min(instream->layout.channel_count, dj->port_count);
|
||||
|
@ -718,9 +732,12 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
|
|||
SoundIoDeviceJackPort *djp = &dj->ports[ch];
|
||||
isjp->source_port_name = djp->full_name;
|
||||
isjp->source_port_name_len = djp->full_name_len;
|
||||
max_port_latency = max(max_port_latency, djp->latency_range.max);
|
||||
}
|
||||
}
|
||||
|
||||
isj->hardware_latency = max_port_latency / (double)instream->sample_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -780,7 +797,9 @@ static int instream_end_read_jack(struct SoundIoPrivate *si, struct SoundIoInStr
|
|||
static int instream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
|
||||
double *out_latency)
|
||||
{
|
||||
soundio_panic("TODO");
|
||||
SoundIoInStreamJack *isj = &is->backend_data.jack;
|
||||
*out_latency = isj->hardware_latency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void notify_devices_change(SoundIoPrivate *si) {
|
||||
|
|
|
@ -20,6 +20,7 @@ struct SoundIoDeviceJackPort {
|
|||
char *full_name;
|
||||
int full_name_len;
|
||||
SoundIoChannelId channel_id;
|
||||
jack_latency_range_t latency_range;
|
||||
};
|
||||
|
||||
struct SoundIoDeviceJack {
|
||||
|
@ -49,6 +50,7 @@ struct SoundIoOutStreamJack {
|
|||
int period_size;
|
||||
int frames_left;
|
||||
bool is_paused;
|
||||
double hardware_latency;
|
||||
SoundIoOutStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
|
||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
@ -63,6 +65,7 @@ struct SoundIoInStreamJack {
|
|||
jack_client_t *client;
|
||||
int period_size;
|
||||
int frames_left;
|
||||
double hardware_latency;
|
||||
SoundIoInStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
|
||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
char *buf_ptrs[SOUNDIO_MAX_CHANNELS];
|
||||
|
|
|
@ -53,14 +53,14 @@ static double seconds_offset = 0.0;
|
|||
|
||||
static SoundIoRingBuffer pulse_rb;
|
||||
|
||||
static void write_time(SoundIoOutStream *outstream) {
|
||||
static void write_time(SoundIoOutStream *outstream, double extra) {
|
||||
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 audible_time = now + latency + extra;
|
||||
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));
|
||||
|
@ -92,7 +92,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m
|
|||
if (frames_until_pulse <= 0) {
|
||||
if (pulse_frames_left == -1) {
|
||||
pulse_frames_left = 0.25 * float_sample_rate;
|
||||
write_time(outstream); // announce beep start
|
||||
write_time(outstream, seconds_per_frame * frame); // announce beep start
|
||||
}
|
||||
if (pulse_frames_left > 0) {
|
||||
pulse_frames_left -= 1;
|
||||
|
@ -101,7 +101,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m
|
|||
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
|
||||
write_time(outstream, seconds_per_frame * frame); // announce beep end
|
||||
}
|
||||
} else {
|
||||
frames_until_pulse -= 1;
|
||||
|
|
Loading…
Reference in a new issue