microphone example: no more glitches

This commit is contained in:
Andrew Kelley 2015-07-24 13:26:46 -07:00
parent efa7b7cbc0
commit 3d3f9f91a2
2 changed files with 23 additions and 25 deletions

View file

@ -233,13 +233,15 @@ view `coverage/index.html` in a browser.
## Roadmap ## Roadmap
0. pipe record to playback example working with ALSA linux 0. pipe record to playback example working with ALSA linux
0. expose prebuf
0. why does pulseaudio microphone use up all the CPU? 0. why does pulseaudio microphone use up all the CPU?
0. merge in/out stream structures and functions? 0. merge in/out stream structures and functions?
0. implement JACK backend, get examples working 0. implement JACK backend, get examples working
0. implement CoreAudio (OSX) backend, get examples working 0. implement CoreAudio (OSX) backend, get examples working
0. implement WASAPI (Windows) backend, get examples working 0. implement WASAPI (Windows) backend, get examples working
0. Avoid calling `panic` in PulseAudio. 0. Avoid calling `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. implement ASIO (Windows) backend, get examples working 0. implement ASIO (Windows) backend, get examples working
0. clean up API and improve documentation 0. clean up API and improve documentation
- make sure every function which can return an error documents which errors - make sure every function which can return an error documents which errors

View file

@ -87,21 +87,22 @@ static void read_callback(struct SoundIoInStream *instream, int available_frame_
break; break;
} }
int advance_frames = available_frame_count * instream->bytes_per_frame; int advance_bytes = available_frame_count * instream->bytes_per_frame;
soundio_ring_buffer_advance_write_ptr(ring_buffer, advance_frames); soundio_ring_buffer_advance_write_ptr(ring_buffer, advance_bytes);
}
static int min_int(int a, int b) {
return (a < b) ? a : b;
} }
static void write_callback(struct SoundIoOutStream *outstream, int requested_frame_count) { static void write_callback(struct SoundIoOutStream *outstream, int requested_frame_count) {
int err; int err;
struct SoundIoChannelArea *areas; struct SoundIoChannelArea *areas;
char *read_ptr = soundio_ring_buffer_read_ptr(ring_buffer); char *read_ptr = soundio_ring_buffer_read_ptr(ring_buffer);
int fill_bytes = soundio_ring_buffer_fill_count(ring_buffer);
int fill_count = soundio_ring_buffer_fill_count(ring_buffer) / outstream->bytes_per_frame; int fill_count = fill_bytes / outstream->bytes_per_frame;
int frames_left = requested_frame_count; int read_frames = min_int(requested_frame_count, fill_count);
int silence_count = frames_left - fill_count; int frames_left = read_frames;
if (silence_count < 0)
silence_count = 0;
int total_read_count = requested_frame_count - silence_count;
for (;;) { for (;;) {
int frame_count = frames_left; int frame_count = frames_left;
@ -112,17 +113,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int requested_fra
if (frame_count <= 0) if (frame_count <= 0)
break; break;
int silence_frame_count = (silence_count < frame_count) ? silence_count : frame_count; for (int frame = 0; frame < frame_count; frame += 1) {
int read_count = frame_count - silence_frame_count;
for (int frame = 0; frame < silence_frame_count; frame += 1) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
memset(areas[ch].ptr, 0, outstream->bytes_per_sample);
areas[ch].ptr += areas[ch].step;
}
}
for (int frame = 0; frame < read_count; frame += 1) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) { for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
memcpy(areas[ch].ptr, read_ptr, outstream->bytes_per_sample); memcpy(areas[ch].ptr, read_ptr, outstream->bytes_per_sample);
areas[ch].ptr += areas[ch].step; areas[ch].ptr += areas[ch].step;
@ -139,7 +130,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int requested_fra
break; break;
} }
soundio_ring_buffer_advance_read_ptr(ring_buffer, total_read_count * outstream->bytes_per_frame); soundio_ring_buffer_advance_read_ptr(ring_buffer, read_frames * outstream->bytes_per_frame);
} }
static void underflow_callback(struct SoundIoOutStream *outstream) { static void underflow_callback(struct SoundIoOutStream *outstream) {
@ -273,7 +264,8 @@ int main(int argc, char **argv) {
instream->format = *fmt; instream->format = *fmt;
instream->sample_rate = sample_rate; instream->sample_rate = sample_rate;
instream->layout = *layout; instream->layout = *layout;
instream->period_duration = 0.1; instream->buffer_duration = 1.0;
instream->period_duration = 0.05;
instream->read_callback = read_callback; instream->read_callback = read_callback;
if ((err = soundio_instream_open(instream))) if ((err = soundio_instream_open(instream)))
@ -286,17 +278,21 @@ int main(int argc, char **argv) {
outstream->sample_rate = sample_rate; outstream->sample_rate = sample_rate;
outstream->layout = *layout; outstream->layout = *layout;
outstream->buffer_duration = 0.1; outstream->buffer_duration = 0.1;
outstream->period_duration = out_device->period_duration_min; outstream->period_duration = 0.25;
outstream->write_callback = write_callback; outstream->write_callback = write_callback;
outstream->underflow_callback = underflow_callback; outstream->underflow_callback = underflow_callback;
if ((err = soundio_outstream_open(outstream))) if ((err = soundio_outstream_open(outstream)))
panic("unable to open output stream: %s", soundio_strerror(err)); panic("unable to open output stream: %s", soundio_strerror(err));
int capacity = outstream->buffer_duration * 2 * instream->sample_rate * instream->bytes_per_frame; int capacity = instream->buffer_duration * instream->sample_rate * instream->bytes_per_frame;
ring_buffer = soundio_ring_buffer_create(soundio, capacity); ring_buffer = soundio_ring_buffer_create(soundio, capacity);
if (!ring_buffer) if (!ring_buffer)
panic("unable to create ring buffer: out of memory"); panic("unable to create ring buffer: out of memory");
char *write_ptr = soundio_ring_buffer_write_ptr(ring_buffer);
int bytes_to_fill = outstream->buffer_duration * outstream->sample_rate * outstream->bytes_per_frame;
memset(write_ptr, 0, bytes_to_fill);
soundio_ring_buffer_advance_write_ptr(ring_buffer, bytes_to_fill);
if ((err = soundio_instream_start(instream))) if ((err = soundio_instream_start(instream)))
panic("unable to start input device: %s", soundio_strerror(err)); panic("unable to start input device: %s", soundio_strerror(err));