priming behavior of Pa_ReadStream and Pa_WriteStream is under specified
[This ticket directly blocks #117 and impacts the correctness of all blocking i/o implementations.]
When a new blocking i/o stream is created and started it is unspecified what state it is in, and how underflow and overflow recovery is to be implemented. This is probably OK when the native host API is a blocking API, but when we are implementing blocking i/o ourselves we need more detailed specs. I'm not sure if this should be part of the PortAudio public API specification, but we at least need to specify some guidelines for implementers so that there is consistency across implementations.
== Output ==
For output we should specify a combination of the following:
- Stream doesn't actually start sending data to DAC until a high watermark is reached (all buffers full?). The same should happen if the stream underflows: it should wait for high watermark before starting again.
- Stream buffers are primed with silence so that when start is called, data is sent immediately (or could be sent after first Write() call.
- User could prime stream buffers by calling Write() after Open() but before Start() (that implies that Stop() always flushes the buffers).
For output, the "high watermark/low watermark" model used in other OSes, eg:
From http://aeriebsd.org/man/man4/audio.html:
SGI irix does mostly the same thing, but also supports select() by exposing a semaphore for when the low water mark is reached:
http://cnmat.berkeley.edu/user/adrian_freed/blog/2009/10/07/audio_i_o_programming_sgi_irix
One consequence of this is that the paOutputUnderflow flag should only be returned once for each time the output queue underflows and stalls.
== Input ==
I am less clear how input should work. It may be sufficient to specify the following: when calling Pa_ReadStream() the client should block until new data is available from the host. The granularity of blocking is determined by host buffering requirements and the size of the buffer passed to Pa_ReadStream(). Pa_ReadStream() will never return synthetic silence
As yet it is unclear whether an input overflow should flush the input queue or leave it in a state where additional overflows are possible if the client doesn't empty the buffers.
An input underflow should always result in the oldest data in the input queue being discarded.
When a new blocking i/o stream is created and started it is unspecified what state it is in, and how underflow and overflow recovery is to be implemented. This is probably OK when the native host API is a blocking API, but when we are implementing blocking i/o ourselves we need more detailed specs. I'm not sure if this should be part of the PortAudio public API specification, but we at least need to specify some guidelines for implementers so that there is consistency across implementations.
== Output ==
For output we should specify a combination of the following:
- Stream doesn't actually start sending data to DAC until a high watermark is reached (all buffers full?). The same should happen if the stream underflows: it should wait for high watermark before starting again.
- Stream buffers are primed with silence so that when start is called, data is sent immediately (or could be sent after first Write() call.
- User could prime stream buffers by calling Write() after Open() but before Start() (that implies that Stop() always flushes the buffers).
For output, the "high watermark/low watermark" model used in other OSes, eg:
From http://aeriebsd.org/man/man4/audio.html:
Writes to the audio devices will queue up blocks until the high-water mark is reached, at which point any more write calls will block until the queue is drained to the low-water mark. hiwat and lowat set those high- and low-water marks (in audio blocks). The default for hiwat is the maximum value and for lowat 75% of hiwat.
SGI irix does mostly the same thing, but also supports select() by exposing a semaphore for when the low water mark is reached:
http://cnmat.berkeley.edu/user/adrian_freed/blog/2009/10/07/audio_i_o_programming_sgi_irix
One consequence of this is that the paOutputUnderflow flag should only be returned once for each time the output queue underflows and stalls.
== Input ==
I am less clear how input should work. It may be sufficient to specify the following: when calling Pa_ReadStream() the client should block until new data is available from the host. The granularity of blocking is determined by host buffering requirements and the size of the buffer passed to Pa_ReadStream(). Pa_ReadStream() will never return synthetic silence
As yet it is unclear whether an input overflow should flush the input queue or leave it in a state where additional overflows are possible if the client doesn't empty the buffers.
An input underflow should always result in the oldest data in the input queue being discarded.
Leave a comment