[Interest] Qt 5.2.1 on Linux: QAudioInput::bytesReady() behaviour

Dmitriy Purgin dpurgin at gmail.com
Sun Jul 6 17:24:21 CEST 2014


Hi there,

I'm writing an application capturing raw audio from two mono inputs
simultaneously and then encoding it with 3rd party library into one
stereo data stream (one channel per input). Since each pass of the
encoder should be fed with equal number of samples of each channel, at
some point in my program I have to know how many samples are available
from both inputs. Unfortunately, neither QAudioInput::bytesReady() nor
QIODevice::bytesAvailable() seem to do the solid job for me.

I've reduced my program down to simple mono channel audio capture to
illustrate the problem. So the code is pretty straight-forward (using
push mode):

class Application : public QCoreApplication
{
   // ...
   QAudioInput* mAudioInput;
   QIODevice* mIoDevice;
};

Application::Application(/* ... */): QCoreApplication(/* ... */)
{
    QAudioFormat audioFormat;
    // audio format initialization skipped

    mAudioInput = new
QAudioInput(QAudioDeviceInfo::defaultInputDevice(), audioFormat);

    mIoDevice = mAudioInput->start();
    connect(mIoDevice, SIGNAL(readyRead()),
            this, SLOT(onIoDeviceReadyRead()));
}

void Application::onIoDeviceReadyRead()
{
    qDebug() << "mAudioInput->state(): " << mAudioInput->state() <<
                ", mAudioInput->bytesReady(): " << mAudioInput->bytesReady();

    // this always returns 0
    qDebug() << "mIoDevice->bytesAvailable(): " << mIoDevice->bytesAvailable();

    // this always shows some data
    qDebug() << "mIoDevice->readAll().size(): " << mIoDevice->readAll().size();
}

The problem is, I don't know how to check reliably how much data is
available before reading. QAudioInput::bytesReady() always shows zero
on first call of onIoDeviceReadyRead(), although some data is always
read with QIODevice::readAll(). If I do not actually read the data
then QAudioInput::bytesReady() increases on subsequent calls, although
actually read data is naturally bigger than the values shown by
QAudioInput::bytesReady(). If I call QIODevice::readAll() on every
pass of onIoDeviceReadyRead(), there is a rare occurrence of non-zero
value in QAudioInput::bytesRead() which is always smaller than
actually read data.

I worked this around using a supplementary buffer of QByteArray being
appended by QIODevice::readAll() whenever QIODevice::readyRead() is
emitted, although it doesn't seem to be efficient due to repeated
remove() calls after the samples are processed by the encoder.

Could someone please tell if there is a way of "peeking" available
bytes in QIODevice without actually reading from it? If yes, would
unread bytes persist in QIODevice until next readyRead(), just like it
does in QTcpSocket?

Thanks in advance.

Cheers
Dmitriy Purgin



More information about the Interest mailing list