4
votes

I'm using Qt 4.8 with Qt Creator 2.4.1 on Windows 7 Ultimate x64.

I'm taking audio input using QAudioInput class and playing it using QAudioOutput. There is a 2 seconds timeout after which I stop taking input and then setup the output as follows:

class MainWindow
{
    // ...

    QByteArray output_data;
    QBuffer output_data_buffer;
    QAudioOutput *audio_out;

    // ...
};

MainWindow::MainWindow(QWidget *parent)
{
    // ...

    output_data_buffer.setBuffer(&output_data);

    // ...
}

void MainWindow::audioInputStopped(QByteArray data)
{
    output_data = data;
    output_data_buffer.open(QIODevice::ReadOnly);
    audio_out = new QAudioOutput(audio_format, this);
    connect(audio_out, SIGNAL(stateChanged(QAudio::State)), 
            SLOT(audioOutputStateChanged(QAudio::State)));
    audio_out->start(&output_data_buffer);
}

The audio format I'm using is supported by both input and output devices. I checked them using QAudioDeviceInfo::isFormatSupported(). The 2 seconds audio (data in audioInputStopped()) always plays fine.

In the slot audioOutputStateChanged, I'm always encountering QAudio::UnderrunError error from audio_out->error() after the buffer is finished playing. After audio_out->start() is called, the state (passed as parameter in audioOutputStateChanged()) and error goes as follows:

  1. No error. Active state.
  2. No error. Stopped state.
  3. Underrun error. Idle state.

Note that I'm stopping audio_out in idle state following this example. Why the code is encountering underrun error? Is this normal?

1

1 Answers

1
votes

This may seem kind of odd, but I've seen where the built-in arrays in Qt handle better when constructed on the heap, or at least when their elements are constructed on the heap (so they are just an array of pointers). The memory management is a little bit trickier, but items pushed into them don't go out of scope. The Qt Object Model also promotes putting most things on the heap and parenting them correctly. This might help.

After reading a little bit up on buffer underruns, it sounds like there is something still trying to read from the audio source while something else is writing to it or vice-versa. Check out some of the links below. You could try disconnecting the audio_in part from the buffer before reading the buffer. This is more likely to fix the error.

I would also construct your QAudioOutput pointer in the constructor for your main window (more as a style thing). Following some of how it is organized in the examples in Qt, it seems like a better organization. Here is the cpp for the QAudioInput example.

If you had a more complete example, I could try more with it to recreate the error and debug it.

Here is someone else to commiserate with:

http://qt-project.org/forums/viewthread/16729

And a wiki article:

http://en.wikipedia.org/wiki/Buffer_underrun

And the list of Multimedia examples on Qt:

http://doc.qt.nokia.com/4.7-snapshot/examples-multimedia.html

Hope that helps.