diff options
Diffstat (limited to 'src/plugins/wasapi')
-rw-r--r-- | src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp | 2 | ||||
-rw-r--r-- | src/plugins/wasapi/qwasapiaudioinput.cpp | 121 | ||||
-rw-r--r-- | src/plugins/wasapi/qwasapiaudioinput.h | 3 | ||||
-rw-r--r-- | src/plugins/wasapi/qwasapiaudiooutput.cpp | 86 | ||||
-rw-r--r-- | src/plugins/wasapi/qwasapiaudiooutput.h | 3 |
5 files changed, 114 insertions, 101 deletions
diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp index 0fa618fe4..e1a46841d 100644 --- a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp +++ b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp @@ -54,7 +54,7 @@ QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode QAudioFormat referenceFormat = m_interface->m_mixFormat; - const int rates[] = {8000, 11025, 160000, 22050, 32000, 44100, 48000, 88200, 96000, 192000}; + const int rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000}; for (int rate : rates) { QAudioFormat f = referenceFormat; f.setSampleRate(rate); diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp index 3bcf50367..22a77df38 100644 --- a/src/plugins/wasapi/qwasapiaudioinput.cpp +++ b/src/plugins/wasapi/qwasapiaudioinput.cpp @@ -120,7 +120,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len) qFatal("Could not release buffer"); if (m_input->m_interval && m_input->m_openTime.elapsed() - m_input->m_openTimeOffset > m_input->m_interval) { - QMetaObject::invokeMethod(m_input, "notify", Qt::QueuedConnection); + emit m_input->notify(); m_input->m_openTimeOffset = m_input->m_openTime.elapsed(); } @@ -128,8 +128,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len) if (m_input->m_currentState != QAudio::ActiveState) { m_input->m_currentState = QAudio::ActiveState; - QMetaObject::invokeMethod(m_input, "stateChanged", Qt::QueuedConnection, - Q_ARG(QAudio::State, QAudio::ActiveState)); + emit m_input->stateChanged(m_input->m_currentState); } return readBytes; } @@ -192,13 +191,9 @@ qreal QWasapiAudioInput::volume() const void QWasapiAudioInput::process() { qCDebug(lcMmAudioInput) << __FUNCTION__; - const quint32 channelCount = m_currentFormat.channelCount(); - const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; - BYTE* buffer; - HRESULT hr; DWORD waitRet; - bool processing = true; + m_processing = true; do { waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE); if (waitRet != WAIT_OBJECT_0) { @@ -210,67 +205,75 @@ void QWasapiAudioInput::process() if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) break; + QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection); + } while (m_processing); +} - if (!m_pullMode) { - QMetaObject::invokeMethod(m_eventDevice, "readyRead", Qt::QueuedConnection); - ResetEvent(m_event); - continue; - } +void QWasapiAudioInput::processBuffer() +{ + if (!m_pullMode) { + emit m_eventDevice->readyRead(); + ResetEvent(m_event); + return; + } - quint32 packetFrames; - hr = m_capture->GetNextPacketSize(&packetFrames); + QMutexLocker locker(&m_mutex); + const quint32 channelCount = m_currentFormat.channelCount(); + const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; + BYTE* buffer; + HRESULT hr; - while (packetFrames != 0 && m_currentState == QAudio::ActiveState) { - DWORD flags; - quint64 devicePosition; - hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL); - if (hr != S_OK) { - m_currentError = QAudio::FatalError; - QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, - Q_ARG(QAudio::Error, QAudio::UnderrunError)); - // Also Error Buffers need to be released - hr = m_capture->ReleaseBuffer(packetFrames); - qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer."; - return; - } - const quint32 writeBytes = packetFrames * channelCount * sampleBytes; - if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) { - // In case this flag is set, user is supposed to ignore the content - // of the buffer and manually write silence - qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: " - << "Ignoring buffer and writing silence."; - buffer = new BYTE[writeBytes]; - memset(buffer, 0, writeBytes); - } + quint32 packetFrames; + hr = m_capture->GetNextPacketSize(&packetFrames); + + while (packetFrames != 0 && m_currentState == QAudio::ActiveState) { + DWORD flags; + quint64 devicePosition; + hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL); + if (hr != S_OK) { + m_currentError = QAudio::FatalError; + emit errorChanged(m_currentError); + // Also Error Buffers need to be released + hr = m_capture->ReleaseBuffer(packetFrames); + qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer."; + return; + } + const quint32 writeBytes = packetFrames * channelCount * sampleBytes; + if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) { + // In case this flag is set, user is supposed to ignore the content + // of the buffer and manually write silence + qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: " + << "Ignoring buffer and writing silence."; + buffer = new BYTE[writeBytes]; + memset(buffer, 0, writeBytes); + } - qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes); + const qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes); - if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) - delete [] buffer; + if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) + delete [] buffer; - if (written < static_cast<qint64>(writeBytes)) { - if (m_currentError != QAudio::UnderrunError) { - m_currentError = QAudio::UnderrunError; - QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, - Q_ARG(QAudio::Error, QAudio::UnderrunError)); - } + if (written < static_cast<qint64>(writeBytes)) { + if (m_currentError != QAudio::UnderrunError) { + m_currentError = QAudio::UnderrunError; + emit errorChanged(m_currentError); } - hr = m_capture->ReleaseBuffer(packetFrames); - if (hr != S_OK) - qFatal("Could not release buffer"); + } + hr = m_capture->ReleaseBuffer(packetFrames); + if (hr != S_OK) + qFatal("Could not release buffer"); - m_bytesProcessed += writeBytes; + m_bytesProcessed += writeBytes; - hr = m_capture->GetNextPacketSize(&packetFrames); - } - ResetEvent(m_event); + hr = m_capture->GetNextPacketSize(&packetFrames); + } + ResetEvent(m_event); - if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { - QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection); - m_openTimeOffset = m_openTime.elapsed(); - } - processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; - } while (processing); + if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { + emit notify(); + m_openTimeOffset = m_openTime.elapsed(); + } + m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; } bool QWasapiAudioInput::initStart(bool pull) diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h index cb2f46436..3fd7315c1 100644 --- a/src/plugins/wasapi/qwasapiaudioinput.h +++ b/src/plugins/wasapi/qwasapiaudioinput.h @@ -88,6 +88,8 @@ public: qreal volume() const Q_DECL_OVERRIDE; void process(); +public slots: + void processBuffer(); private: bool initStart(bool pull); friend class WasapiInputDevicePrivate; @@ -112,6 +114,7 @@ private: quint32 m_bufferBytes; HANDLE m_event; QWasapiProcessThread *m_eventThread; + QAtomicInt m_processing; QIODevice *m_eventDevice; }; diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp index 53f4f2710..1b0f64451 100644 --- a/src/plugins/wasapi/qwasapiaudiooutput.cpp +++ b/src/plugins/wasapi/qwasapiaudiooutput.cpp @@ -206,13 +206,9 @@ qreal QWasapiAudioOutput::volume() const void QWasapiAudioOutput::process() { qCDebug(lcMmAudioOutput) << __FUNCTION__; - const quint32 channelCount = m_currentFormat.channelCount(); - const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; - BYTE* buffer; - HRESULT hr; DWORD waitRet; - bool processing = true; + m_processing = true; do { waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE); if (waitRet != WAIT_OBJECT_0) { @@ -224,51 +220,59 @@ void QWasapiAudioOutput::process() if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) break; + QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection); + } while (m_processing); +} - quint32 paddingFrames; - hr = m_interface->m_client->GetCurrentPadding(&paddingFrames); +void QWasapiAudioOutput::processBuffer() +{ + QMutexLocker locker(&m_mutex); - quint32 availableFrames = m_bufferFrames - paddingFrames; - hr = m_renderer->GetBuffer(availableFrames, &buffer); - if (hr != S_OK) { - m_currentError = QAudio::UnderrunError; - QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, - Q_ARG(QAudio::Error, QAudio::UnderrunError)); - // Also Error Buffers need to be released - hr = m_renderer->ReleaseBuffer(availableFrames, 0); - ResetEvent(m_event); - continue; // We will continue trying - } + const quint32 channelCount = m_currentFormat.channelCount(); + const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; + BYTE* buffer; + HRESULT hr; - const quint32 readBytes = availableFrames * channelCount * sampleBytes; - qint64 read = m_eventDevice->read((char*)buffer, readBytes); - if (read < static_cast<qint64>(readBytes)) { - // Fill the rest of the buffer with zero to avoid audio glitches - if (m_currentError != QAudio::UnderrunError) { - m_currentError = QAudio::UnderrunError; - QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, - Q_ARG(QAudio::Error, QAudio::UnderrunError)); - } - if (m_currentState != QAudio::IdleState) { - m_currentState = QAudio::IdleState; - QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, - Q_ARG(QAudio::State, QAudio::IdleState)); - } - } + quint32 paddingFrames; + hr = m_interface->m_client->GetCurrentPadding(&paddingFrames); + const quint32 availableFrames = m_bufferFrames - paddingFrames; + hr = m_renderer->GetBuffer(availableFrames, &buffer); + if (hr != S_OK) { + m_currentError = QAudio::UnderrunError; + emit errorChanged(m_currentError); + // Also Error Buffers need to be released hr = m_renderer->ReleaseBuffer(availableFrames, 0); - if (hr != S_OK) - qFatal("Could not release buffer"); ResetEvent(m_event); + return; + } - if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { - QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection); - m_openTimeOffset = m_openTime.elapsed(); + const quint32 readBytes = availableFrames * channelCount * sampleBytes; + const qint64 read = m_eventDevice->read((char*)buffer, readBytes); + if (read < static_cast<qint64>(readBytes)) { + // Fill the rest of the buffer with zero to avoid audio glitches + if (m_currentError != QAudio::UnderrunError) { + m_currentError = QAudio::UnderrunError; + emit errorChanged(m_currentError); } + if (m_currentState != QAudio::IdleState) { + m_currentState = QAudio::IdleState; + emit stateChanged(m_currentState); + } + } + + hr = m_renderer->ReleaseBuffer(availableFrames, 0); + if (hr != S_OK) + qFatal("Could not release buffer"); + ResetEvent(m_event); + + if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { + emit notify(); + m_openTimeOffset = m_openTime.elapsed(); + } - m_bytesProcessed += read; - processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; - } while (processing); + m_bytesProcessed += read; + m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; } bool QWasapiAudioOutput::initStart(bool pull) diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h index 247a07160..118731af9 100644 --- a/src/plugins/wasapi/qwasapiaudiooutput.h +++ b/src/plugins/wasapi/qwasapiaudiooutput.h @@ -89,6 +89,8 @@ public: qreal volume() const Q_DECL_OVERRIDE; void process(); +public slots: + void processBuffer(); private: bool initStart(bool pull); friend class WasapiOutputDevicePrivate; @@ -113,6 +115,7 @@ private: quint32 m_bufferBytes; HANDLE m_event; QWasapiProcessThread *m_eventThread; + QAtomicInt m_processing; QIODevice *m_eventDevice; }; |