QAudioOutput on two devices(headphones)
-
Hello. There is way output sound on two devices simultaneously. Two headphones connected to the computer and i output sound on them. I hear intermittent sound . Expectation : AAAAAA". Reality: "A--A--A".
I get the sound from the microphone QAudioInput. I simulate a telephone connection . I receive sound from the microphone and transmit to the headphones
When i use one devices, one headphone, it work correctly!! When I add a second device, I get intermittent sound.
Could you help me? How can I get the sound right?
-
QAudioInput and QAudioOutput i use from Examples.
Input:void MainWindow::initializeAudio(const QAudioDeviceInfo &deviceInfo) { format.setSampleRate(8000); format.setChannelCount(1); format.setSampleSize(16); format.setSampleType(QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setCodec("audio/pcm"); if (!deviceInfo.isFormatSupported(format)) { qWarning("Default format not supported - trying to use nearest"); //qWarning() << "Default format not supported - trying to use nearest"; format = deviceInfo.nearestFormat(format); } m_audioInfo.reset(new AudioInfo(format)); connect(m_audioInfo.data(), &AudioInfo::update, [this]() { sliderAnim(m_audioInfo->level()); }); m_audioInfo->start(); m_audioInput.reset(new QAudioInput(deviceInfo, format)); qreal initialVolume = QAudio::convertVolume(m_audioInput->volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); int v = qRound(initialVolume * 100); ui->horizontalSlider->setValue(v); ui->horizontalSlider->setValue(0.f * 100.0f); m_audioInput->stop(); setResume(); m_audioInput->start(m_audioInfo.data()); _inputThread = new QThread(); m_audioInput->moveToThread(_inputThread); }
Output:
m_audioInput.reset(new QAudioInput(deviceInfo, format)); qreal initialVolume = QAudio::convertVolume(m_audioInput->volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); int v = qRound(initialVolume * 100); ui->horizontalSlider->setValue(v); ui->horizontalSlider->setValue(0.f * 100.0f); m_audioInput->stop(); setResume(); m_audioInput->start(m_audioInfo.data()); //_inputThread = new QThread(); //m_audioInput->moveToThread(_inputThread);
I try add Output on thread, it doesn't help:
_inputThread = new QThread(); m_audioInput->moveToThread(_inputThread);
-
AudioInfo class:
class AudioInfo: public QIODevice { Q_OBJECT public: AudioInfo(const QAudioFormat &format); void start(); void stop(); qreal level() const { return m_level; } qint64 readData(char *data, qint64 len) override; qint64 writeData(const char *data, qint64 len) override; qint64 bytesAvailable() const; private: const QAudioFormat m_format; quint32 m_maxAmplitude = 0; qreal m_level = 0.0; // 0.0 <= m_level <= 1.0 void generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate); QByteArray m_buffer_array; qint64 m_pos = 0; QBuffer m_buffer; // buffer to store received datagrams QByteArray m_buffer_test; signals: void update();
#include "AudioInfo.h" AudioInfo::AudioInfo(const QAudioFormat &format) : m_format(format) { switch (m_format.sampleSize()) { case 8: switch (m_format.sampleType()) { case QAudioFormat::UnSignedInt: m_maxAmplitude = 255; break; case QAudioFormat::SignedInt: m_maxAmplitude = 127; break; default: break; } break; case 16: switch (m_format.sampleType()) { case QAudioFormat::UnSignedInt: m_maxAmplitude = 65535; break; case QAudioFormat::SignedInt: m_maxAmplitude = 32767; break; default: break; } break; case 32: switch (m_format.sampleType()) { case QAudioFormat::UnSignedInt: m_maxAmplitude = 0xffffffff; break; case QAudioFormat::SignedInt: m_maxAmplitude = 0x7fffffff; break; case QAudioFormat::Float: m_maxAmplitude = 0x7fffffff; // Kind of default: break; } break; default: break; } if (format.isValid()) { //generateData(format, durationUs, sampleRate); } } void AudioInfo::start() { m_buffer.open(QIODevice::ReadWrite); open(QIODevice::ReadWrite); } void AudioInfo::stop() { close(); } qint64 AudioInfo::writeData(const char *data, qint64 len) { //qDebug() << "writeData" << m_buffer_test.length(); m_buffer_test.append(data, len); //qDebug() << "writeData finish" << m_buffer_test.length(); return len; } qint64 AudioInfo::bytesAvailable() const { return m_buffer.size() + QIODevice::bytesAvailable(); } qint64 AudioInfo::readData(char *data, qint64 len) { //qDebug() << "readData finish" << m_buffer_test.length(); if (!m_buffer_test.isEmpty()) { memset(data, 0, len); if (m_buffer_test.size() < len) { len = m_buffer_test.size(); } if (len > 0) { memcpy(data, m_buffer_test.left(len).data(), len); m_buffer_test.remove(0, len); } } else { memset(data, 0, len); } return len; }
-
I try add QThread for output. it doesn't help:
class SfxThread: public QThread { Q_OBJECT public: SfxThread(const QAudioDeviceInfo &deviceInfo, const QAudioFormat &format, QScopedPointer<AudioInfo> &m_audioInfo); ~SfxThread(); void run(); signals: public slots: void play(); void playerStateChanged(QAudio::State state); private: void playNext(); void play(QString& filename); QScopedPointer<AudioInfo> _ai; QScopedPointer<QAudioOutput> _ao; QAudioFormat _af; //QBuffer _buf; };
#include "SfxThread.h" SfxThread::SfxThread(const QAudioDeviceInfo &deviceInfo, const QAudioFormat &format, QScopedPointer<AudioInfo> &m_audioInfo) { _ai.reset(m_audioInfo.data()); //.do precaching etc of the sounds here _ao.reset(new QAudioOutput(deviceInfo, format)); start(); // Move event processing of SfxThread to this thread QObject::moveToThread(this); } SfxThread::~SfxThread() { quit(); wait(); } void SfxThread::play() { //playlist.append(...); playNext(); } // Plays the next file from queue void SfxThread::playNext() { //if (playlist.length() == 0 || _ao->state() == QAudio::ActiveState) { // return; //} _ao->stop(); //_buf.close(); //play(playlist.dequeue()); } void SfxThread::play(QString& filename) { //// load content here //QByteArray *ptr = ... // //_buf.setBuffer(ptr); //_buf.open(QIODevice::ReadOnly); // //_ao->setBufferSize(_buf.size()); _ao->start(_ai.data()); } void SfxThread::playerStateChanged(QAudio::State state) { // Play finished, play next clip if (state == QAudio::IdleState) { playNext(); } } void SfxThread::run() { //.set audio format here (_af.setCodec etc) _ao->start(_ai.data()); //connect(_ao, SIGNAL(stateChanged(QAudio::State)), this, SLOT(playerStateChanged(QAudio::State))); exec(); }
-
Hi,
Which version of Qt are you using ?
Why are you using threading ? -
@SGaist Hello. Qt 5.12.1 MinGW 64-bit.
At first I didn't use threads. It didn't work correctly. I hear intermittent sound .
I decided threads would help. Add each QAudioOutput on separate thread .m_audioOutput.reset(new QAudioOutput(deviceInfo, format)); m_audioOutput->start(m_audioInfo.data()); _outputThread = new QThread(); m_audioOutput->moveToThread(_outputThread); _outputThread->start();
It did not help too.
Two QAudioOutput don't work as with threads as without threads. (Two QAudioOutput work, but I hear intermittent sound. Wheh work one QAudioOutput I hear correctly sound )