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
0. pipe record to playback example working with ALSA linux
0. expose prebuf
0. why does pulseaudio microphone use up all the CPU?
0. merge in/out stream structures and functions?
0. implement JACK backend, get examples working
0. implement CoreAudio (OSX) backend, get examples working
0. implement WASAPI (Windows) backend, get examples working
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. clean up API and improve documentation
- 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;
}
int advance_frames = available_frame_count * instream->bytes_per_frame;
soundio_ring_buffer_advance_write_ptr(ring_buffer, advance_frames);
int advance_bytes = available_frame_count * instream->bytes_per_frame;
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) {
int err;
struct SoundIoChannelArea *areas;
char *read_ptr = soundio_ring_buffer_read_ptr(ring_buffer);
int fill_count = soundio_ring_buffer_fill_count(ring_buffer) / outstream->bytes_per_frame;
int frames_left = requested_frame_count;
int silence_count = frames_left - fill_count;
if (silence_count < 0)
silence_count = 0;
int total_read_count = requested_frame_count - silence_count;
int fill_bytes = soundio_ring_buffer_fill_count(ring_buffer);
int fill_count = fill_bytes / outstream->bytes_per_frame;
int read_frames = min_int(requested_frame_count, fill_count);
int frames_left = read_frames;
for (;;) {
int frame_count = frames_left;
@ -112,17 +113,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int requested_fra
if (frame_count <= 0)
break;
int silence_frame_count = (silence_count < frame_count) ? silence_count : frame_count;
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 frame = 0; frame < frame_count; frame += 1) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
memcpy(areas[ch].ptr, read_ptr, outstream->bytes_per_sample);
areas[ch].ptr += areas[ch].step;
@ -139,7 +130,7 @@ static void write_callback(struct SoundIoOutStream *outstream, int requested_fra
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) {
@ -273,7 +264,8 @@ int main(int argc, char **argv) {
instream->format = *fmt;
instream->sample_rate = sample_rate;
instream->layout = *layout;
instream->period_duration = 0.1;
instream->buffer_duration = 1.0;
instream->period_duration = 0.05;
instream->read_callback = read_callback;
if ((err = soundio_instream_open(instream)))
@ -286,17 +278,21 @@ int main(int argc, char **argv) {
outstream->sample_rate = sample_rate;
outstream->layout = *layout;
outstream->buffer_duration = 0.1;
outstream->period_duration = out_device->period_duration_min;
outstream->period_duration = 0.25;
outstream->write_callback = write_callback;
outstream->underflow_callback = underflow_callback;
if ((err = soundio_outstream_open(outstream)))
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);
if (!ring_buffer)
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)))
panic("unable to start input device: %s", soundio_strerror(err));