JACK: fix playback glitchfest

This commit is contained in:
Andrew Kelley 2015-07-28 23:20:30 -07:00
parent 754343bba6
commit 97ee72ce5f
3 changed files with 27 additions and 12 deletions

View file

@ -241,13 +241,12 @@ view `coverage/index.html` in a browser.
## Roadmap
0. JACK: input
0. JACK: implement prebuffering
0. why does pulseaudio microphone use up all the CPU?
0. merge in/out stream structures and functions?
0. Integrate into libgroove and test with Groove Basin
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
0. why does pulseaudio microphone use up all the CPU?
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
@ -282,7 +281,6 @@ view `coverage/index.html` in a browser.
0. use a documentation generator and host the docs somewhere
0. -fvisibility=hidden and then explicitly export stuff, or
explicitly make the unexported stuff private
0. Integrate into libgroove and test with Groove Basin
0. look at microphone example and determine if fewer memcpys can be done
with the audio data
- test that sending the frame count to begin read works with PulseAudio
@ -295,6 +293,7 @@ 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

View file

@ -81,8 +81,14 @@ static void wakeup_jack(struct SoundIoPrivate *si) {
static int outstream_process_callback(jack_nframes_t nframes, void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub;
outstream->write_callback(outstream, nframes);
osj->frames_left = nframes;
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
osj->buf_ptrs[ch] = (char*)jack_port_get_buffer(osjp->source_port, osj->frames_left);
}
outstream->write_callback(outstream, osj->frames_left);
return 0;
}
@ -268,14 +274,11 @@ static int outstream_begin_write_jack(struct SoundIoPrivate *si, struct SoundIoO
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoJack *sij = &si->backend_data.jack;
assert(*frame_count <= sij->period_size);
*frame_count = min(*frame_count, osj->frames_left);
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
if (!(osj->areas[ch].ptr = (char*)jack_port_get_buffer(osjp->source_port, *frame_count)))
return SoundIoErrorStreaming;
osj->areas[ch].ptr = osj->buf_ptrs[ch];
osj->areas[ch].step = outstream->bytes_per_sample;
}
@ -287,6 +290,17 @@ static int outstream_begin_write_jack(struct SoundIoPrivate *si, struct SoundIoO
static int outstream_end_write_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
int frame_count)
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
assert(frame_count <= osj->frames_left);
osj->frames_left -= frame_count;
if (osj->frames_left > 0) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
osj->buf_ptrs[ch] += frame_count * outstream->bytes_per_sample;
}
}
return 0;
}

View file

@ -48,8 +48,10 @@ struct SoundIoOutStreamJackPort {
struct SoundIoOutStreamJack {
jack_client_t *client;
int period_size;
int frames_left;
SoundIoOutStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
char *buf_ptrs[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamJackPort {