On Fri, Jun 15, 2012 at 06:23:57PM -0700, Chris Robinson wrote: > The update_size is only relevant if mmdevapi updates in period-sized chunks. > If it doesn't, you can just remove it and the rounding. The tlength should be > kept updated using pa_stream_set_buffer_attr_callback, in case the server > tries to increase it more during runtime. >
We chatted a little on IRC this weekend, but thanks again for the advice. Mmdevapi sends it data to the lower systems in period-sized chunks, and the reported buffer fill level decreases in period-sized chunks. But the audio clock position is more accurate than that, returning some value between periods, and taking into account latency. Unfortunately, PulseAudio (and, apparently, every Linux audio API) refuses to make any guarantees at all with regard to things like buffer sizes, period sizes, callback regularity, and latencies. So in Wine we have to build an emulation layer, involving a buffer in the driver itself, and lie about buffer drain behavior and latencies. I really don't understand why the audio APIs refuse to do this heavy lifting, instead pushing it off to applications. What is the API for if I have to do all the hard work anyway? It'd be handy if there was some page explaining how PulseAudio's data model works. Stuff like where the data is stored, when and how it's transfered, when callbacks are triggered, what the members of pa_buffer_attr actually mean (their documentation is useless), how the stream flags affect stream operation and the callbacks, when the buffer attributes might change and how applications should deal with those changes. This stuff is all unclear to me, and I think it's a big source of my frustration with the API. > When creating the stream, I set minreq to the period size, and tlength to the > requested buffer size. I also set the flags PA_STREAM_INTERPOLATE_TIMING, > PA_STREAM_AUTO_TIMING_UPDATE, and PA_STREAM_ADJUST_LATENCY. > > The most important part is to not rely on PA_STREAM_EARLY_REQUESTS or the > write callback to tell you when some space is free for writing, since as > noted > above, PulseAudio can set unreasonably large values. > Yeah, I experimented with ADJUST_LATENCY, as it seems to be the trick to getting lower latencies. Then we have to maintain our own buffer, which is why I switched to using the write callback, to have Pulse tell us when it's ready for more data from our internal buffer. But then I couldn't get the callbacks to actually trigger without supplying EARLY_REQUESTS, which invalidates our latency request, causing the high latency problem... wonderful API, isn't it? Your mail makes me think I should go back to the pulse-independent timer setup. That is, write to Pulse during the CreateTimerQueueTimer() callback. I have a strong feeling I've been down that path before, but I could give it another shot. Thanks again, Andrew