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
-
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
-
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
-
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);
@