Hi,

TL;DR: I’d like to change QAudioSink::resume() to always change the sink to 
Active state, no matter how the sink was start()’ed.


QAudioSink provides low-level access to an audio device, allowing applications 
to provide PCM data.

The class operates in one of two modes: in pull mode, the application provides 
a QIODevice when calling QAudioSink::start(QIODevice *), and the sink will pull 
data from that devices as needed. In push mode, the QAudioSink creates and 
returns a QIODevice from the other QAudioSink::start() overload. Applications 
write PCM data into that device.

The problem is with QAudioSink::resume. The function is documented to behavior 
differently depending on how start() was called:

/*!
    Resumes processing audio data after a suspend().

    Sets error() to QAudio::NoError.
    Sets state() to QAudio::ActiveState if you previously called 
start(QIODevice*).
    Sets state() to QAudio::IdleState if you previously called start().
    emits stateChanged() signal.
*/

QAudioSink::suspend() behaves the same way in both modes: audio stops 
immediately, already buffered data is preserved.

This means that on a sink that has 10 seconds worth of data, calling suspend() 
after 1 second, and then resume()’ing changes the state of a push-mode audio 
sink to Idle, audio will play for 9 seconds while the sink reports to be idle, 
and the sink doesn’t change to “really idle” when all the audio data has been 
played.

This means also that applications have no way of knowing when it’s time to 
write more data, as an underflow error is never reported - the sink is already 
idle, there are no state changes. This is pretty broken IMHO making the 
push-style API practically useless if suspend/resume are used. However, the 
behavior is documented, and verified in tests.

A sane behavior would be to move the sink to Active after resume (and to handle 
buffer under-runs as usual, resulting in Idle state with error).

I’m not sure yet that we can implement the sane behavior on all platforms. 
Pull-mode evidently implements it, but I don’t know yet if we can inspect the 
amount of data buffered by the underlying audio system. Before we start 
investigating that - can anyone think of any particular reason why the existing 
behavior is a good idea?


Volker

-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to