QAudioInput notify signal not fired in pushMode



  • Hi all,

    i made some tests with the QAudioInput class and faced some problems with the notify signal.
    The test case is a quite simle application that opens a sound input stream and prints debug messages.
    This is the code:
    @#include "InputDev.h"
    #include <QDebug>
    #include <QBuffer>

    InputDev::InputDev(QObject *parent) :
    QObject(parent),
    m_input(nullptr),
    m_buffer(nullptr),
    m_format(),
    m_device(),
    m_pullMode(true)
    {
    m_device = QAudioDeviceInfo::defaultInputDevice();
    m_format.setByteOrder(QAudioFormat::LittleEndian);
    m_format.setChannelCount(1);
    m_format.setCodec("raw/pcm");
    m_format.setSampleRate(16000);
    m_format.setSampleSize(16);
    m_format.setSampleType(QAudioFormat::SignedInt);

    m_input = new QAudioInput(m_device, m_format, this);
    connect(m_input, &QAudioInput::notify, this, &InputDev::on_notify);
    connect(m_input, &QAudioInput::stateChanged, this, &InputDev::on_stateChanged);
    

    }

    void InputDev::start() {
    if ( m_pullMode ) {
    qDebug() << "opening in pullMode";
    m_buffer = new QBuffer();
    m_buffer->open(QIODevice::ReadWrite);
    m_input->start(m_buffer);
    } else {
    qDebug() << "opening in pushMode";
    m_buffer = m_input->start();
    connect(m_buffer, &QIODevice::readyRead, this, &InputDev::on_readyRead);

    }
    

    }

    void InputDev::stop() {
    if ( m_pullMode ) {
    m_input->stop();
    m_buffer->deleteLater();
    } else {
    m_input->stop();
    m_buffer->disconnect(this);
    }
    }

    void InputDev::on_stateChanged(QAudio::State st) {
    if ( st==QAudio::ActiveState ) {
    qDebug() << "went to activeState";
    if ( m_input->error() != QAudio::NoError ) {
    qDebug() << "AudioError: " << m_input->error();
    }
    } else if ( st == QAudio::SuspendedState ) {
    qDebug() << "went to suspendedState";
    if ( m_input->error() != QAudio::NoError ) {
    qDebug() << "AudioError: " << m_input->error();
    }
    } else if ( st == QAudio::StoppedState ) {
    qDebug() << "went to stoppedState";
    if ( m_input->error() != QAudio::NoError ) {
    qDebug() << "AudioError: " << m_input->error();
    }
    } else if ( st == QAudio::IdleState ) {
    qDebug() << "went to idleState";
    if ( m_input->error() != QAudio::NoError ) {
    qDebug() << "AudioError: " << m_input->error();
    }
    }
    }

    void InputDev::on_notify() {
    qDebug() << "on_notify";
    }

    void InputDev::on_readyRead() {
    qDebug() << "on_readyRead";
    }

    void InputDev::on_toggleMode() {
    qDebug() << "toggling";
    stop();
    m_pullMode = !m_pullMode;
    start();
    }
    @

    On my Ubuntu desktop i can observe that the notify signal is no longer fired (or at least the on_notify slot is not executed) when i toggle from pull to pushMode, I see the readyRead message, but never the on_notify. When it runs in pullmode on_notify is executed.
    The same code deployed to an S4Mini device also prints the on_notify messages in pushmode.

    The application is embedded in a QML application having one button to toggle the mode. The main.cpp is
    @#include <QApplication>
    #include <QQmlApplicationEngine>
    #include "InputDev.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    QObject* ro = engine.rootObjects().at(0);
    
    InputDev dev;
    QObject::connect(ro, SIGNAL(qmlToggle()), &dev, SLOT(on_toggleMode()));
    dev.start();
    
    return app.exec&#40;&#41;;
    

    }
    @

    I also tried the audioinput example that comes with Qt, this works fine, meaning the on_notify is executed regardless of the mode.
    Is there any error in my implementation? Right now i can't see any differences between the example and my test application.

    Thank you!

    Regards,
    Andreas


  • Lifetime Qt Champion

    Hi,

    The thing I see is that you only connect readyRead in pushMode, in pull mode you should connect the device returned by start



  • Hi,

    thanks for your reply. First: I made a mistake in my caption, the notify is not triggered in pushMode.
    I think it shouldn't be necessary to listen to the readyRead signal in pushMode since the device is normally a custom QIODevice with special semantics in the writeData method ( in this test is use QBuffer for simplicity).
    But I tried to connect to the signal, but it doesn't change the output.
    Whats pretty strange is that the device does not trigger a statechanged after i start the device again. Here is the console output from my linux machine:
    @QML debugging is enabled. Only use this in a safe environment.
    opening in pullMode
    went to activeState
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_notify
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    on_readyRead
    toggling
    went to stoppedState
    opening in pushMode
    went to idleState@

    I did not terminate the program after went to idleState, it just doesn't print any messages. When i connect to readyRead the on_readyRead are printed. But it seems as QAudioInput is emitting no signal, neither notify nor active. Why doesn't it go to ActiveState?

    For comparison output from the S4Mini with Android 4.4.2
    @
    opening in pullMode
    W/AudioRecord( 4069): AUDIO_INPUT_FLAG_FAST denied by client
    went to activeState
    on_readyRead
    ....
    on_readyRead
    on_notify
    on_readyRead
    ...
    on_readyRead
    on_notify
    .....
    on_readyRead
    on_readyRead
    toggling
    went to stoppedState
    opening in pushMode
    W/AudioRecord( 4069): AUDIO_INPUT_FLAG_FAST denied by client
    went to idleState
    on_readyRead
    went to activeState
    on_notify
    on_notify
    on_notify
    on_notify
    on_notify
    on_notify
    on_notify
    on_notify
    @



  • if I add a
    m_buffer->readAll(); statement in my on_readyRead the notify signal gets fired in push mode.
    You can reproduce this with the AudioInput example shipped with Qt. Comment out the content of readMore and the behaviour is exactly the same as in my test application.
    But Android exposes a different behaviour, there the on_notify signal is fired without any read operation in readMore().
    This seems to be a bug. I don't know what is the correct one, but it should be the same on different devices, or?
    That raises the question what exactly the notify signals indicates. Either the amount of data processed by QAudioInput and delivered to the buffer ( push mode buffer or pull mode buffer ) or the amount of data read from the buffer. But the latter one doesn't make any sense to me, hence I think the Android behaviour is correct and there is a bug in the Linux implementation.
    What do you think?


  • Lifetime Qt Champion

    To me it sounds that the Android port is behaving differently that the other platforms.

    To ensure whether it's intended or not. You should move that question to the interest mailing list. You'll find there Qt's developers/maintainers (this forum is more user oriented)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.