On 2015-06-04 03:06, Andrew Kelley wrote: > I open the audio playback device like this: > > pa_threaded_mainloop_lock(audio_hardware->main_loop); > > pa_sample_spec sample_spec; > sample_spec.format = to_pulseaudio_sample_format(sample_format); > sample_spec.rate = audio_device->default_sample_rate; > sample_spec.channels = audio_device->channel_layout.channel_count; > pa_channel_map channel_map = > to_pulseaudio_channel_map(&audio_device->channel_layout); > > open_playback_device->stream = > pa_stream_new(audio_hardware->pulse_context, > "Genesis", &sample_spec, &channel_map); > // error handling omitted > pa_stream_set_state_callback(open_playback_device->stream, > playback_stream_state_callback, > open_playback_device); > pa_stream_set_write_callback(open_playback_device->stream, > playback_stream_write_callback, > open_playback_device); > pa_stream_set_underflow_callback(open_playback_device->stream, > playback_stream_underflow_callback, > open_playback_device); > > open_playback_device->bytes_per_frame = > genesis_get_bytes_per_frame(sample_format, > audio_device->channel_layout.channel_count); > int bytes_per_second = open_playback_device->bytes_per_frame * > audio_device->default_sample_rate; > int buffer_length = open_playback_device->bytes_per_frame * > ceil(latency * bytes_per_second / > (double)open_playback_device->bytes_per_frame); > > open_playback_device->buffer_attr.maxlength = buffer_length; > open_playback_device->buffer_attr.tlength = buffer_length; > open_playback_device->buffer_attr.prebuf = 0; > open_playback_device->buffer_attr.minreq = UINT32_MAX; > open_playback_device->buffer_attr.fragsize = UINT32_MAX; > > > pa_stream_connect_playback(open_playback_device->stream, > open_playback_device->audio_device->name, > &open_playback_device->buffer_attr, > PA_STREAM_ADJUST_LATENCY, nullptr, nullptr); > // error handling omitted > > while (!open_playback_device->stream_ready) > pa_threaded_mainloop_wait(audio_hardware->main_loop); > > pa_threaded_mainloop_unlock(audio_hardware->main_loop); > > > Here is some output from my program. When it prints UNDERRUN that means > the underflow callback was called. The number is the number of seconds > that the write callback took to fill the playback buffer. In this > example the audio device is opened with latency set to 10ms, e.g. 0.01 > seconds. The percent is how long the callback took out of how long the > buffer size is. So that first UNDERRUN makes sense, because the callback > took 2x as long as it was supposed to. When an underrun occurs, the > playback buffer is filled completely with silence. So why am I getting > all these other underflow callbacks when the callback was well within > the range of time which should have been fine? Any ideas of things I can > do to troubleshoot? If you set your total latency to 10 ms, minreq to -1, and include the PA_STREAM_ADJUST_LATENCY flag, then the *total* latency is below 10 ms, i e, including latency within PulseAudio itself. PulseAudio will, for so small latency values, try to divide the 10 ms into four periods of 2.5 ms each by default. After that these values might be adjusted for various reasons. If you want a *period* size of 10 ms, then you need to set minreq to 10 ms and tlength to something larger than 20 ms. But then again, PA is free to change these values as it see fits (e g due to hardware constraints). Anyhow, if your callback is between 2.5 ms and (something less than) 10 ms, it's possible you get an underflow callback without there actually being an audio glitch. There was a debate a while ago about whether it would make sense to skip this underflow callback for this reason, but IIRC, there was no consensus and thus the behaviour was not changed. -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic