output/jack: synchronize all channels

Always use the same number of samples from each channel's ring
buffer.  This ensures that all channels are kept in sync.
This commit is contained in:
Max Kellermann 2010-03-10 19:18:51 +01:00
parent 5842015b90
commit 41a4662c8c

View File

@ -88,12 +88,31 @@ jack_output_quark(void)
return g_quark_from_static_string("jack_output"); return g_quark_from_static_string("jack_output");
} }
/**
* Determine the number of frames guaranteed to be available on all
* channels.
*/
static jack_nframes_t
mpd_jack_available(const struct jack_data *jd)
{
size_t min = jack_ringbuffer_read_space(jd->ringbuffer[0]);
for (unsigned i = 1; i < jd->audio_format.channels; ++i) {
size_t current = jack_ringbuffer_read_space(jd->ringbuffer[i]);
if (current < min)
min = current;
}
assert(min % sample_size == 0);
return min / sample_size;
}
static int static int
mpd_jack_process(jack_nframes_t nframes, void *arg) mpd_jack_process(jack_nframes_t nframes, void *arg)
{ {
struct jack_data *jd = (struct jack_data *) arg; struct jack_data *jd = (struct jack_data *) arg;
jack_default_audio_sample_t *out; jack_default_audio_sample_t *out;
size_t available;
if (nframes <= 0) if (nframes <= 0)
return 0; return 0;
@ -111,20 +130,18 @@ mpd_jack_process(jack_nframes_t nframes, void *arg)
return 0; return 0;
} }
for (unsigned i = 0; i < jd->audio_format.channels; ++i) { jack_nframes_t available = mpd_jack_available(jd);
available = jack_ringbuffer_read_space(jd->ringbuffer[i]); if (available > nframes)
assert(available % sample_size == 0); available = nframes;
available /= sample_size;
if (available > nframes)
available = nframes;
for (unsigned i = 0; i < jd->audio_format.channels; ++i) {
out = jack_port_get_buffer(jd->ports[i], nframes); out = jack_port_get_buffer(jd->ports[i], nframes);
jack_ringbuffer_read(jd->ringbuffer[i], jack_ringbuffer_read(jd->ringbuffer[i],
(char *)out, available * sample_size); (char *)out, available * sample_size);
while (available < nframes) for (jack_nframes_t f = available; f < nframes; ++f)
/* ringbuffer underrun, fill with silence */ /* ringbuffer underrun, fill with silence */
out[available++] = 0.0; out[f] = 0.0;
} }
/* generate silence for the unused source ports */ /* generate silence for the unused source ports */