From b46219241ce428b82e0252081b00af69969308be Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 26 Jun 2017 22:44:31 -0400 Subject: [PATCH 01/78] add peakValueListChanged scaffolding --- libraries/audio-client/src/AudioClient.cpp | 12 +++++++++--- libraries/audio-client/src/AudioClient.h | 10 +++++++++- libraries/audio-client/src/AudioPeakValues.cpp | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 libraries/audio-client/src/AudioPeakValues.cpp diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index fc54a04a5e..7a1d8edccd 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -224,13 +224,18 @@ AudioClient::AudioClient() : // start a thread to detect any device changes _checkDevicesTimer = new QTimer(this); connect(_checkDevicesTimer, &QTimer::timeout, [this] { - QtConcurrent::run(QThreadPool::globalInstance(), [this] { - checkDevices(); - }); + QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkDevices(); }); }); const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; _checkDevicesTimer->start(DEVICE_CHECK_INTERVAL_MSECS); + // start a thread to detect peak value changes + _checkPeakValuesTimer = new QTimer(this); + connect(_checkPeakValuesTimer, &QTimer::timeout, [this] { + QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkPeakValues(); }); + }); + const unsigned long PEAK_VALUES_CHECK_INTERVAL_SECS = 50; + configureReverb(); @@ -262,6 +267,7 @@ void AudioClient::cleanupBeforeQuit() { stop(); _checkDevicesTimer->stop(); + _checkPeakValuesTimer->stop(); } void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 54ce3aa6c2..79e82526c6 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -148,6 +148,8 @@ public: QAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const; QList getAudioDevices(QAudio::Mode mode) const; + void enablePeakValues(bool enable) { _enablePeakValues = enable; } + static const float CALLBACK_ACCELERATOR_RATIO; bool getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName); @@ -220,6 +222,7 @@ signals: void deviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device); void devicesChanged(QAudio::Mode mode, const QList& devices); + void peakValueListChanged(const QList peakValueList); void receivedFirstPacket(); void disconnected(); @@ -238,9 +241,12 @@ private: friend class CheckDevicesThread; friend class LocalInjectorsThread; + // background tasks + void checkDevices(); + void checkPeakValues(); + void outputFormatChanged(); void handleAudioInput(QByteArray& audioBuffer); - void checkDevices(); void prepareLocalAudioInjectors(std::unique_ptr localAudioLock = nullptr); bool mixLocalAudioInjectors(float* mixBuffer); float azimuthForSource(const glm::vec3& relativePosition); @@ -293,6 +299,7 @@ private: std::atomic _localInjectorsAvailable { false }; MixedProcessedAudioStream _receivedAudioStream; bool _isStereoInput; + std::atomic _enablePeakValues { false }; quint64 _outputStarveDetectionStartTimeMsec; int _outputStarveDetectionCount; @@ -391,6 +398,7 @@ private: RateCounter<> _audioInbound; QTimer* _checkDevicesTimer { nullptr }; + QTimer* _checkPeakValuesTimer { nullptr }; }; diff --git a/libraries/audio-client/src/AudioPeakValues.cpp b/libraries/audio-client/src/AudioPeakValues.cpp new file mode 100644 index 0000000000..021f23b907 --- /dev/null +++ b/libraries/audio-client/src/AudioPeakValues.cpp @@ -0,0 +1,16 @@ +// +// AudioPeakValues.cpp +// interface/src +// +// Created by Zach Pomerantz on 6/26/2017 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AudioClient.h" + +void AudioClient::checkPeakValues() { + // TODO +} From 3f57e5eb4d9cc145915948b2c91860c994cac344 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 27 Jun 2017 14:04:52 -0400 Subject: [PATCH 02/78] implement peakValueListChanged --- libraries/audio-client/src/AudioClient.cpp | 10 +- libraries/audio-client/src/AudioClient.h | 1 + .../audio-client/src/AudioPeakValues.cpp | 164 +++++++++++++++++- 3 files changed, 169 insertions(+), 6 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 7a1d8edccd..7f872443be 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -77,7 +77,7 @@ Setting::Handle staticJitterBufferFrames("staticJitterBufferFrames", // protect the Qt internal device list using Mutex = std::mutex; using Lock = std::unique_lock; -static Mutex _deviceMutex; +Mutex _deviceMutex; // thread-safe QList getAvailableDevices(QAudio::Mode mode) { @@ -235,7 +235,7 @@ AudioClient::AudioClient() : QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkPeakValues(); }); }); const unsigned long PEAK_VALUES_CHECK_INTERVAL_SECS = 50; - + _checkPeakValuesTimer->start(PEAK_VALUES_CHECK_INTERVAL_SECS); configureReverb(); @@ -308,8 +308,6 @@ QString getWinDeviceName(IMMDevice* pEndpoint) { QString deviceName; IPropertyStore* pPropertyStore; pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore); - pEndpoint->Release(); - pEndpoint = nullptr; PROPVARIANT pv; PropVariantInit(&pv); HRESULT hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); @@ -338,6 +336,8 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) { deviceName = QString("NONE"); } else { deviceName = ::getWinDeviceName(pEndpoint); + pEndpoint->Release(); + pEndpoint = nullptr; } pMMDeviceEnumerator->Release(); pMMDeviceEnumerator = nullptr; @@ -421,6 +421,8 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { deviceName = QString("NONE"); } else { deviceName = getWinDeviceName(pEndpoint); + pEndpoint->Release(); + pEndpoint = nullptr; } pMMDeviceEnumerator->Release(); pMMDeviceEnumerator = NULL; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 79e82526c6..63b1398d09 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -149,6 +149,7 @@ public: QList getAudioDevices(QAudio::Mode mode) const; void enablePeakValues(bool enable) { _enablePeakValues = enable; } + bool peakValuesAvailable() const; static const float CALLBACK_ACCELERATOR_RATIO; diff --git a/libraries/audio-client/src/AudioPeakValues.cpp b/libraries/audio-client/src/AudioPeakValues.cpp index 021f23b907..3df469b830 100644 --- a/libraries/audio-client/src/AudioPeakValues.cpp +++ b/libraries/audio-client/src/AudioPeakValues.cpp @@ -11,6 +11,166 @@ #include "AudioClient.h" -void AudioClient::checkPeakValues() { - // TODO +#ifdef Q_OS_WIN + +#include +#include +#include +#include + +#include + +#define RETURN_ON_FAIL(result) if (FAILED(result)) { return; } +#define CONTINUE_ON_FAIL(result) if (FAILED(result)) { continue; } + +extern QString getWinDeviceName(IMMDevice* pEndpoint); +extern std::mutex _deviceMutex; + +std::map> activeClients; + +template +void release(T* t) { + t->Release(); } + +template <> +void release(IAudioClient* audioClient) { + audioClient->Stop(); + audioClient->Release(); +} + +void AudioClient::checkPeakValues() { + // prepare the windows environment + CoInitialize(NULL); + + // if disabled, clean up active clients + if (!_enablePeakValues) { + activeClients.clear(); + return; + } + + // lock the devices so the _inputDevices list is static + std::unique_lock lock(_deviceMutex); + HRESULT result; + + // initialize the payload + QList peakValueList; + for (int i = 0; i < _inputDevices.size(); ++i) { + peakValueList.push_back(0.0f); + } + + std::shared_ptr enumerator; + { + IMMDeviceEnumerator* pEnumerator; + result = CoCreateInstance( + __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, + __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); + RETURN_ON_FAIL(result); + enumerator = std::shared_ptr(pEnumerator, &release); + } + + std::shared_ptr endpoints; + { + IMMDeviceCollection* pEndpoints; + result = enumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &pEndpoints); + RETURN_ON_FAIL(result); + endpoints = std::shared_ptr(pEndpoints, &release); + } + + UINT count; + { + result = endpoints->GetCount(&count); + RETURN_ON_FAIL(result); + } + + IMMDevice* pDevice; + std::shared_ptr device; + IAudioMeterInformation* pMeterInfo; + std::shared_ptr meterInfo; + IAudioClient* pAudioClient; + std::shared_ptr audioClient; + DWORD hardwareSupport; + LPWSTR pDeviceId = NULL; + LPWAVEFORMATEX format; + float peakValue; + QString deviceName; + int deviceIndex; + for (UINT i = 0; i < count; ++i) { + result = endpoints->Item(i, &pDevice); + CONTINUE_ON_FAIL(result); + device = std::shared_ptr(pDevice, &release); + + // if the device isn't listed through Qt, skip it + deviceName = ::getWinDeviceName(pDevice); + deviceIndex = 0; + for (; deviceIndex < _inputDevices.size(); ++deviceIndex) { + if (deviceName == _inputDevices[deviceIndex].deviceName()) { + break; + } + } + if (deviceIndex >= _inputDevices.size()) { + continue; + } + + //continue; + + result = device->Activate(__uuidof(IAudioMeterInformation), CLSCTX_ALL, NULL, (void**)&pMeterInfo); + CONTINUE_ON_FAIL(result); + meterInfo = std::shared_ptr(pMeterInfo, &release); + + //continue; + + hardwareSupport; + result = meterInfo->QueryHardwareSupport(&hardwareSupport); + CONTINUE_ON_FAIL(result); + + //continue; + + // if the device has no hardware support (USB)... + if (!(hardwareSupport & ENDPOINT_HARDWARE_SUPPORT_METER)) { + result = device->GetId(&pDeviceId); + CONTINUE_ON_FAIL(result); + std::wstring deviceId(pDeviceId); + CoTaskMemFree(pDeviceId); + + //continue; + + // ...and no active client... + if (activeClients.find(deviceId) == activeClients.end()) { + result = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient); + CONTINUE_ON_FAIL(result); + audioClient = std::shared_ptr(pAudioClient, &release); + + //continue; + + // ...activate a client + audioClient->GetMixFormat(&format); + audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, format, NULL); + audioClient->Start(); + + //continue; + + activeClients[deviceId] = audioClient; + } + } + + // get the peak value and put it in the payload + meterInfo->GetPeakValue(&peakValue); + peakValueList[deviceIndex] = peakValue; + } + + emit peakValueListChanged(peakValueList); +} + +bool AudioClient::peakValuesAvailable() const { + return true; +} + +#else +void AudioClient::checkPeakValues() { +} + +bool AudioClient::peakValuesAvailable() const { + return false; +} +#endif \ No newline at end of file From 5353437f5915b9c88ab276a81dfdd95276a8df8d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 27 Jun 2017 17:37:13 -0400 Subject: [PATCH 03/78] add peakValues to scripting API --- interface/src/scripting/AudioDevices.cpp | 82 ++++++++++++++++++------ interface/src/scripting/AudioDevices.h | 63 +++++++++++++++--- 2 files changed, 118 insertions(+), 27 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index b0ea8226e8..1c31d7aa5a 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -34,28 +34,44 @@ Setting::Handle& getSetting(bool contextIsHMD, QAudio::Mode mode) { } } -QHash AudioDeviceList::_roles { - { Qt::DisplayRole, "display" }, - { Qt::CheckStateRole, "selected" } +enum AudioDeviceRole { + DisplayRole = Qt::DisplayRole, + CheckStateRole = Qt::CheckStateRole, + PeakRole = Qt::UserRole }; + +QHash AudioDeviceList::_roles { + { DisplayRole, "display" }, + { CheckStateRole, "selected" }, + { PeakRole, "peak" } +}; + Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled }; QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { - if (!index.isValid() || index.row() >= _devices.size()) { + if (!index.isValid() || index.row() >= rowCount()) { return QVariant(); } - if (role == Qt::DisplayRole) { - return _devices.at(index.row()).display; - } else if (role == Qt::CheckStateRole) { - return _devices.at(index.row()).selected; + if (role == DisplayRole) { + return _devices.at(index.row())->display; + } else if (role == CheckStateRole) { + return _devices.at(index.row())->selected; } else { return QVariant(); } } +QVariant AudioInputDeviceList::data(const QModelIndex& index, int role) const { + if (index.isValid() && index.row() < rowCount() && role == PeakRole) { + return std::static_pointer_cast(_devices.at(index.row()))->peak; + } else { + return AudioDeviceList::data(index, role); + } +} + bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.row() >= _devices.size() || role != Qt::CheckStateRole) { + if (!index.isValid() || index.row() >= rowCount() || role != CheckStateRole) { return false; } @@ -73,19 +89,19 @@ bool AudioDeviceList::setDevice(int row, bool fromUser) { auto& device = _devices[row]; // skip if already selected - if (!device.selected) { + if (!device->selected) { auto client = DependencyManager::get(); QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, success), Q_ARG(QAudio::Mode, _mode), - Q_ARG(const QAudioDeviceInfo&, device.info)); + Q_ARG(const QAudioDeviceInfo&, device->info)); if (success) { - device.selected = true; + device->selected = true; if (fromUser) { - emit deviceSelected(device.info, _selectedDevice); + emit deviceSelected(device->info, _selectedDevice); } - emit deviceChanged(device.info); + emit deviceChanged(device->info); } } @@ -100,7 +116,7 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { if (!device.isNull()) { auto i = 0; for (; i < rowCount(); ++i) { - if (device == _devices[i].info.deviceName()) { + if (device == _devices[i]->info.deviceName()) { break; } } @@ -138,8 +154,8 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { _selectedDevice = device; QModelIndex index; - for (auto i = 0; i < _devices.size(); ++i) { - AudioDevice& device = _devices[i]; + for (auto i = 0; i < rowCount(); ++i) { + AudioDevice& device = *_devices[i]; if (device.selected && device.info != _selectedDevice) { device.selected = false; @@ -166,17 +182,47 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) { .remove("Device") .replace(" )", ")"); device.selected = (device.info == _selectedDevice); - _devices.push_back(device); + _devices.push_back(newDevice(device)); } endResetModel(); } +bool AudioInputDeviceList::peakValuesAvailable() { + std::call_once(_peakFlag, [&] { + _peakValuesAvailable = DependencyManager::get()->peakValuesAvailable(); + }); + return _peakValuesAvailable; +} + +void AudioInputDeviceList::setPeakValuesEnabled(bool enable) { + if (peakValuesAvailable() && (enable != _peakValuesEnabled)) { + DependencyManager::get()->enablePeakValues(enable); + _peakValuesEnabled = enable; + emit peakValuesEnabledChanged(_peakValuesEnabled); + } +} + +void AudioInputDeviceList::onPeakValueListChanged(const QList& peakValueList) { + assert(_mode == QAudio::AudioInput); + + if (peakValueList.length() != rowCount()) { + qWarning() << "AudioDeviceList" << __FUNCTION__ << "length mismatch"; + } + + for (auto i = 0; i < rowCount(); ++i) { + std::static_pointer_cast(_devices[i])->peak = peakValueList[i]; + } + + emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0), { PeakRole }); +} + AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { auto client = DependencyManager::get(); connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection); connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection); + connect(client.data(), &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection); // connections are made after client is initialized, so we must also fetch the devices _inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput)); diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index cd47ab4191..bdf03820f4 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -12,6 +12,9 @@ #ifndef hifi_scripting_AudioDevices_h #define hifi_scripting_AudioDevices_h +#include +#include + #include #include #include @@ -29,7 +32,11 @@ class AudioDeviceList : public QAbstractListModel { Q_OBJECT public: - AudioDeviceList(QAudio::Mode mode) : _mode(mode) {} + AudioDeviceList(QAudio::Mode mode = QAudio::AudioOutput) : _mode(mode) {} + ~AudioDeviceList() = default; + + virtual std::shared_ptr newDevice(const AudioDevice& device) + { return std::make_shared(device); } int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return _devices.size(); } QHash roleNames() const override { return _roles; } @@ -47,11 +54,11 @@ signals: const QAudioDeviceInfo& previousDevice = QAudioDeviceInfo()); void deviceChanged(const QAudioDeviceInfo& device); -private slots: +protected slots: void onDeviceChanged(const QAudioDeviceInfo& device); void onDevicesChanged(const QList& devices); -private: +protected: friend class AudioDevices; bool setDevice(int index, bool fromUser); @@ -59,16 +66,54 @@ private: static QHash _roles; static Qt::ItemFlags _flags; - QAudio::Mode _mode; + QAudio::Mode _mode { QAudio::AudioOutput }; QAudioDeviceInfo _selectedDevice; - QList _devices; + QList> _devices; +}; + +class AudioInputDevice : public AudioDevice { +public: + AudioInputDevice(const AudioDevice& device) : AudioDevice(device) {} + float peak { 0.0f }; +}; + +class AudioInputDeviceList : public AudioDeviceList { + Q_OBJECT + Q_PROPERTY(bool peakValuesAvailable READ peakValuesAvailable) + Q_PROPERTY(bool peakValuesEnabled READ peakValuesEnabled WRITE setPeakValuesEnabled NOTIFY peakValuesEnabledChanged) + +public: + AudioInputDeviceList() : AudioDeviceList(QAudio::AudioInput) {} + virtual ~AudioInputDeviceList() = default; + + virtual std::shared_ptr newDevice(const AudioDevice& device) + { return std::make_shared(device); } + + QVariant data(const QModelIndex& index, int role) const override; + +signals: + void peakValuesEnabledChanged(bool enabled); + +protected slots: + void onPeakValueListChanged(const QList& peakValueList); + +protected: + friend class AudioDevices; + + bool peakValuesAvailable(); + std::once_flag _peakFlag; + bool _peakValuesAvailable; + + bool peakValuesEnabled() const { return _peakValuesEnabled; } + void setPeakValuesEnabled(bool enable); + bool _peakValuesEnabled { false }; }; class Audio; class AudioDevices : public QObject { Q_OBJECT - Q_PROPERTY(AudioDeviceList* input READ getInputList NOTIFY nop) + Q_PROPERTY(AudioInputDeviceList* input READ getInputList NOTIFY nop) Q_PROPERTY(AudioDeviceList* output READ getOutputList NOTIFY nop) public: @@ -86,11 +131,11 @@ private slots: private: friend class Audio; - AudioDeviceList* getInputList() { return &_inputs; } + AudioInputDeviceList* getInputList() { return &_inputs; } AudioDeviceList* getOutputList() { return &_outputs; } - AudioDeviceList _inputs { QAudio::AudioInput }; - AudioDeviceList _outputs { QAudio::AudioOutput }; + AudioInputDeviceList _inputs; + AudioDeviceList _outputs; bool& _contextIsHMD; }; From 9b72ab96ff5a019d20b7a030a48c20af1bf84023 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 27 Jun 2017 17:37:24 -0400 Subject: [PATCH 04/78] add peak values to qml --- interface/resources/qml/hifi/audio/Audio.qml | 26 ++++++++++++++++--- .../audio/{InputLevel.qml => InputPeak.qml} | 6 ++--- 2 files changed, 25 insertions(+), 7 deletions(-) rename interface/resources/qml/hifi/audio/{InputLevel.qml => InputPeak.qml} (95%) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index c13bd3281a..9ebde8b61f 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -36,6 +36,23 @@ Rectangle { return root.parent.objectName == "loader"; } + property bool showPeaks: true; + function enablePeakValues() { + Audio.devices.input.peakValuesEnabled = true; + Audio.devices.input.peakValuesEnabledChanged.connect(function(enabled) { + if (!enabled && root.showPeaks) { + Audio.devices.input.peakValuesEnabled = true; + } + }); + } + function disablePeakValues() { + root.showPeaks = false; + Audio.devices.input.peakValuesEnabled = false; + } + + Component.onCompleted: enablePeakValues(); + Component.onDestruction: disablePeakValues(); + Column { y: 16; // padding does not work spacing: 16; @@ -122,7 +139,7 @@ Rectangle { width: parent.width; AudioControls.CheckBox { - Layout.maximumWidth: parent.width - level.width - 40; + Layout.maximumWidth: parent.width - inputPeak.width - 40; text: display; wrap: false; checked: selected; @@ -131,11 +148,12 @@ Rectangle { checked = Qt.binding(function() { return selected; }); // restore binding } } - InputLevel { - id: level; + InputPeak { + id: inputPeak; + visible: Audio.devices.input.peakValuesAvailable; + peak: model.peak; Layout.alignment: Qt.AlignRight; Layout.rightMargin: 30; - visible: selected; } } } diff --git a/interface/resources/qml/hifi/audio/InputLevel.qml b/interface/resources/qml/hifi/audio/InputPeak.qml similarity index 95% rename from interface/resources/qml/hifi/audio/InputLevel.qml rename to interface/resources/qml/hifi/audio/InputPeak.qml index 58ce3a1ec7..4ff49091b1 100644 --- a/interface/resources/qml/hifi/audio/InputLevel.qml +++ b/interface/resources/qml/hifi/audio/InputPeak.qml @@ -1,5 +1,5 @@ // -// InputLevel.qml +// InputPeak.qml // qml/hifi/audio // // Created by Zach Pomerantz on 6/20/2017 @@ -15,7 +15,7 @@ import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 Rectangle { - readonly property var level: Audio.inputLevel; + property var peak; width: 70; height: 8; @@ -65,7 +65,7 @@ Rectangle { Rectangle { // mask id: mask; - width: parent.width * level; + width: parent.width * peak; radius: 5; anchors { bottom: parent.bottom; From ed49f80322377e7d5e40f4229889eed13345504f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 29 Jun 2017 17:32:52 -0400 Subject: [PATCH 05/78] fix peak check secs->msecs --- libraries/audio-client/src/AudioClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 7f872443be..88f34d60f1 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -234,8 +234,8 @@ AudioClient::AudioClient() : connect(_checkPeakValuesTimer, &QTimer::timeout, [this] { QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkPeakValues(); }); }); - const unsigned long PEAK_VALUES_CHECK_INTERVAL_SECS = 50; - _checkPeakValuesTimer->start(PEAK_VALUES_CHECK_INTERVAL_SECS); + const unsigned long PEAK_VALUES_CHECK_INTERVAL_MSECS = 50; + _checkPeakValuesTimer->start(PEAK_VALUES_CHECK_INTERVAL_MSECS); configureReverb(); From 631e5a7b0433c100b457428a6e53bc0cf9ac575a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 29 Jun 2017 17:34:01 -0400 Subject: [PATCH 06/78] add override to AudioInputDeviceList::newDevice --- interface/src/scripting/AudioDevices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index bdf03820f4..60d547f58f 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -86,7 +86,7 @@ public: AudioInputDeviceList() : AudioDeviceList(QAudio::AudioInput) {} virtual ~AudioInputDeviceList() = default; - virtual std::shared_ptr newDevice(const AudioDevice& device) + virtual std::shared_ptr newDevice(const AudioDevice& device) override { return std::make_shared(device); } QVariant data(const QModelIndex& index, int role) const override; From 0da19af6f32c274f42a0fc08b18a6bb2cb220280 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 11 Jul 2017 10:06:38 -0700 Subject: [PATCH 07/78] Stop all capture devices when Audio.qml is not visible. Otherwise, Windows will continue to capture audio from all attached devices (possibly causing mic audio glitches) until Interface shutdown. --- interface/resources/qml/hifi/audio/Audio.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index aea0f0501d..4e0b4cebe2 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -52,6 +52,7 @@ Rectangle { Component.onCompleted: enablePeakValues(); Component.onDestruction: disablePeakValues(); + onVisibleChanged: visible ? enablePeakValues() : disablePeakValues(); Column { y: 16; // padding does not work From 50deee1d38fd9f66d94bd8b3731f29342e43b411 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 12 Jul 2017 12:29:25 -0700 Subject: [PATCH 08/78] Replace tabs with spaces --- interface/src/scripting/AudioDevices.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 574ec00ad6..c3958f2ad9 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -73,7 +73,7 @@ QVariant AudioInputDeviceList::data(const QModelIndex& index, int role) const { } bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.row() >= rowCount() || role != CheckStateRole) { + if (!index.isValid() || index.row() >= rowCount() || role != CheckStateRole) { return false; } From cf6c1ae4a54391d4d096c5e76805534fbfc60f31 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 12 Jul 2017 12:30:02 -0700 Subject: [PATCH 09/78] Replace tabs with spaces --- assignment-client/src/audio/AudioMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index ed63bbc298..a131e266d2 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -558,7 +558,7 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio // produce an oriented angle about the y-axis glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); - float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" return (direction.x < 0.0f) ? -angle : angle; } else { From 93ad1b6cbf8c1f3fe1a979ef21d8419b5a634f08 Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Thu, 3 Aug 2017 01:53:26 +0530 Subject: [PATCH 10/78] Add link in help page to report a problem --- interface/resources/html/tabletHelp.html | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/interface/resources/html/tabletHelp.html b/interface/resources/html/tabletHelp.html index cbd7ffcfe7..a6588be083 100644 --- a/interface/resources/html/tabletHelp.html +++ b/interface/resources/html/tabletHelp.html @@ -6,7 +6,14 @@ Welcome to Interface