QAudio (both, either output and input) was something I've been fed up very quickly on desktop. I prefer RtAudio and Nootka works with it pretty good.
But I gave a once more try of it under Android, to keep hands away from Jni.
The start was painful.
QIODevice *outDev = audioOutput-<start();
Returned QIODvice outDev was very "unresponsive". audioOutput->bytesFree() returned only declared buffer size but not real amount of free data. outDev device didn't emit any signals to inform about need of a new audio data,
even audioOutput device didn't emit notify() signal.
The only way to feed device with data was a QTimer event loop and invoking outDev->write().
Another way is tricky.
Instead of starting output with QIODevice *outDev = audioOutput->start ();
we may start it like this:
audioOutput->start(ourDevice);where ourDevice is an instance of tricky QIODevice subclass.
When "real device" will want a data, it will call
ourDevice->read(char* data, qint64 maxLen);As Qt doc says: http://doc.qt.io/qt-5/qiodevice.html
by re-implementation of readData(char* data, qint64 maxLen) we get access to it.
Moreover, this call is performed in different thread - "the real device" one.
We may feed char* data just in readData() method, but I prefer to emit signal
and write data in more suitable place.
Important thing! Such signal has to be connected with any slot with
Qt::DirectConnection flag:
connect(ourDevice, &ProxyDevice::feedAudio, someObject, &SomeObject::feedAudioSlot, Qt::DirectConnection);
class ProxyDevice : public QIODevice { Q_OBJECT public: /** Constructor does almost nothing, just initializes size of fake buffer. */ ProxyDevice(QObject* parent = 0) : QIODevice(parent), m_bufferSize(2048) {} /** In fact, there is no any buffer! * That value controls size of data to get by feedAudio() * instead of maxlen value sending in readData(data, maxlen) */ void setBufferSize(qint64 s) { m_bufferSize = s; } qint64 bufferSize() const { return m_bufferSize; } signals: /** char* is pointer to data, qint64 is its size * and qint64& is reference where connected slot will return size of data has been written. */ void feedAudio(char*, qint64, qint64&); protected: /** This is heart of the class: * feedAudio(data, m_bufferSize, wasRead) signal is emitted * to get m_bufferSize bytes into data * and into reference of wasRead connected slot * returns amout of bytes were put. */ virtual qint64 readData(char *data, qint64 maxlen) { Q_UNUSED(maxlen) qint64 wasRead = 0; emit feedAudio(data, m_bufferSize, wasRead); return wasRead; } /** Dummy - does nothing */ virtual qint64 writeData(const char *data, qint64 len) { return 0; } private: qint64 m_bufferSize; };
When connected slot will not write any data and returns 0 in reference - device will go into Idle state.
Brak komentarzy:
Prześlij komentarz