I agree. Let’s change behaviour and move it to active after a call to resume(). 
It also behaves the same in push and pull mode in that case.

Cheers,
Lars

> On 31 Jan 2023, at 13:11, Tor Arne Vestbø via Development 
> <development@qt-project.org> wrote:
> 
> 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

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

Reply via email to