Hi,

This does indeed look like an oversight, where the behavior was perhaps modeled 
under the assumption the buffers were empty at the time of suspend().

I would expect the state to return back to the same state the sink had when 
calling suspend().

Cheers,
Tor Arne

> On 30 Jan 2023, at 16:38, Volker Hilsheimer via Development 
> <development@qt-project.org> wrote:
> 
> 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

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

Reply via email to