QAudioInput redirect to QAudioOutput



  • Hi all,

    we are trying to do some data processing between audio input and audio output.
    We have written a simple application that does redirect input to output:

    @AudioTest::AudioTest(QObject *parent) :
    QObject(parent)
    {
    QAudioFormat format;
    format.setSampleSize(16);
    format.setSampleRate(8000);
    format.setChannelCount(1);
    format.setCodec("audio/pcm");
    format.setSampleType(QAudioFormat::SignedInt);
    format.setByteOrder(QAudioFormat::LittleEndian);

    m_AudioInput = createAudioInput(format);
    m_AudioOutput = createAudioOutput(format);
    m_AudioOutput->start(m_AudioInput->start());
    

    }

    QAudioInput* AudioTest::createAudioInput(QAudioFormat &format)
    {
    QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
    if (!info.isFormatSupported(format))
    {
    qDebug() << "Format not supported";
    return NULL;
    }

    return new QAudioInput(format, this);
    

    }

    QAudioOutput* AudioTest::createAudioOutput(QAudioFormat &format)
    {
    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format))
    {
    qDebug() << "Format not supported";
    return NULL;
    }

    return new QAudioOutput(format, this);
    

    }@

    This works like a charm.
    The next step that we were planning was to implement our custom IODevice.
    So we tried to change the line:

    @m_AudioOutput->start(m_AudioInput->start());@

    with:

    @QBuffer* buffer = new QBuffer();
    buffer->open(QIODevice::ReadWrite);
    m_AudioInput->start(buffer);
    m_AudioOutput->start(buffer);@

    In this way nothing works!!
    Can anybody explain us what we are doing wrong??

    Thanks



  • Try seeking back to the beginning of the buffer before passing it to anything that reads from it
    @buffer->seek(0);@



  • Hi Terence,
    thanks for your reply. To solve the issue that you pointed out we have tried to implement a custom IODevice: IntermediateBuffer. Than we change the code like this:

    @IntermediateBuffer* buffer = new IntermediateBuffer();
    buffer->open(QIODevice::ReadWrite);
    m_AudioInput->start(buffer);
    m_AudioOutput->start(buffer);@

    Here the read and write implementation:

    @qint64 IntermediateBuffer::readData(char* data, qint64 maxlen)
    {
    int length = qMin(m_Buffer.length(), (int) maxlen);
    qstrncpy(data, m_Buffer.constData(), length);
    m_Buffer.remove(0, length);

    return length;
    }

    qint64 IntermediateBuffer::writeData(const char* data, qint64 maxlen)
    {
    m_Buffer.append(data, maxlen);
    return maxlen;
    }@

    As you can image nothing changed :( :(

    P.S.: m_Buffer is a QByteArray


  • Moderators

    I've encountered this issue before. If I'm not mistaken, the read() and write() functions share the same pos() tracker. This is what happens:
    @
    QBuffer buffer;

    buffer.open(QBuffer::ReadWrite); // buffer.pos() == 0
    buffer.write(someData, 5); // Writes in positions 0 -- 4, buffer.pos() == 5;
    buffer.write(someData, 5); // Writes in positions 5 -- 9, buffer.pos() == 10;
    buffer.read(otherBuffer.data(), 10); // Tries to read from position 10 onwards. No data found
    @

    So, when your QAudioOutput tries to read from your buffer, the buffer ignores the positions that your QAudioInput wrote to.

    I can think of 2 solutions:

    Implement your own, separate read-position and write-position trackers. Then, call seek() in readData() and writeData() to set pos() -- point to the end of the data before writing, but point to the middle of the data before reading

    Use 2 separate buffers, and copy bytes from the input buffer into the output buffer


  • Moderators

    P.S. You probably want to implement a Circular Buffer instead of a 'normal' buffer -- a QBuffer doesn't automatically remove old data, and will eventually run out of memory (and crash)

    P.P.S. Intead of
    @
    qstrncpy(data, m_Buffer.constData(), length);
    m_Buffer.remove(0, length);
    @

    You could write
    @
    memcpy(data, m_Buffer.constData(), length);
    @



  • Thanks.

    It was so simple that didn't come up in my mind ;)


Log in to reply
 

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