[Android-development] QAudioOutput on Android device (latency and idle problem)

Got gotleg at gmail.com
Thu May 14 12:33:18 CEST 2020


Hello,

I'm working on a music creation app that target embedded devices.
It consist of 8 channels (each with its own QAudioOutput and buffer)
playing wav samples.
Samples can be played pressing a button on UI or auto launched by the
internal sequencer.
My test device is a Xiaomi phone running on Android 8.1 and I run Qt 5.14.2.

I face a problem on this platform as QAudioOutput->start() can take from
500 microseconds at best (wich is ok for my purpose) to more than 5000
microseconds : /

To workaround this problem, I'm now trying to avoid calling start each time
I need to play the sample. Instead I just seek the buffer to position 0 and
resume() QAudioOutput.

This method appears to be less time consuming as I measure between 50 and
80 microseconds to do this.

Here comes the problem. If my understanding is correct, when
QAudioOutput has reached the end of the buffer, it is supposed to go idle
so I can resume it (after seeking the buffer).
But it looks like QAudioOutput is stopped as soon as the buffer reach the
end.

Here is an example log of what is going on after loading and playing a
sample. I played sample multiple times but if I let it reach the end before
playing again it Output stops :

D MiaouZik: qml: Select category /HiHat
D         : PlayerBase::PlayerBase()
D         : TrackPlayerBase::TrackPlayerBase()
I libOpenSLES: Emulating old channel mask behavior (ignoring positional
mask 0x3, using default mask 0x3 based on channel count of 2)
I AudioTrack: AUDIO_OUTPUT_FLAG_FAST successful; frameCount 384 -> 384
D AudioTrack: Client defaulted notificationFrames to 192 for frameCount 384
D MiaouZik: Play  1 :  46
I zygote  : Do partial code cache collection, code=30KB, data=29KB
I zygote  : After code cache collection, code=30KB, data=29KB
I zygote  : Increasing code cache capacity to 128KB
D MiaouZik: Play  1 :  62
D MiaouZik: Play  1 :  92
D MiaouZik: Play  1 :  91
D MiaouZik: Play  1 :  69
D MiaouZik: Play  1 :  57
D MiaouZik: Play  1 :  62
D         : PlayerBase::stop() from IPlayer
D AudioTrack: stop() called with 86211 frames delivered
D MiaouZik: Idle state

As you can see the log show a "PlayerBase::stop() from IPlayer" just before
receiving the Idle state, so I cannot resume QAudioOutput.

Here is the code :

    std::chrono::high_resolution_clock::time_point before =
std::chrono::high_resolution_clock::now();


    if (m_buffer.isOpen()) {

        m_buffer.close();

    }


    m_buffer.setData(m_noteBuffer[value]);

    m_buffer.open(QIODevice::ReadOnly);


    m_buffer.seek(0);

    m_audioOutput->resume();


//    m_audioOutput->start(&m_buffer);

    qDebug() << "Play " << m_index << ": " <<
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()
- before).count();



Is it supposed to work the way I think (going idle when buffer is empty and
not stopping QAudioOutput) ?

Is there a way to prevent QAudioOutput from stopping ?

Any advice on how to workaround this problem ?


Many thanks for your help,
Best regards
-- 
Gauthier Legrand
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/android-development/attachments/20200514/85547720/attachment.html>


More information about the Android-development mailing list