mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge pull request #16196 from amerhifi/dev469
DEV-469: Default Audio device
This commit is contained in:
commit
1e94a82ee6
9 changed files with 301 additions and 155 deletions
|
@ -440,13 +440,13 @@ void Audio::handlePushedToTalk(bool enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
void Audio::setInputDevice(const QAudioDeviceInfo& device, bool isHMD) {
|
||||
void Audio::setInputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
|
||||
withWriteLock([&] {
|
||||
_devices.chooseInputDevice(device, isHMD);
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::setOutputDevice(const QAudioDeviceInfo& device, bool isHMD) {
|
||||
void Audio::setOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
|
||||
withWriteLock([&] {
|
||||
_devices.chooseOutputDevice(device, isHMD);
|
||||
});
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "SettingHandle.h"
|
||||
#include "AudioFileWav.h"
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
#include <HifiAudioDeviceInfo.h>
|
||||
|
||||
using MutedGetter = std::function<bool()>;
|
||||
using MutedSetter = std::function<void(bool)>;
|
||||
|
@ -158,7 +159,7 @@ public:
|
|||
* @param {boolean} isHMD - Is HMD.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
Q_INVOKABLE void setInputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setOutputDevice
|
||||
|
@ -166,7 +167,7 @@ public:
|
|||
* @param {boolean} isHMD - Is HMD.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
Q_INVOKABLE void setOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables reverberation. Reverberation is done by the client on the post-mix audio. The reverberation options
|
||||
|
|
|
@ -29,6 +29,8 @@ static Setting::Handle<QString> desktopOutputDeviceSetting { QStringList { Audio
|
|||
static Setting::Handle<QString> hmdInputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "INPUT" }};
|
||||
static Setting::Handle<QString> hmdOutputDeviceSetting { QStringList { Audio::AUDIO, Audio::HMD, "OUTPUT" }};
|
||||
|
||||
Q_DECLARE_METATYPE(HifiAudioDeviceInfo);
|
||||
|
||||
Setting::Handle<QString>& getSetting(bool contextIsHMD, QAudio::Mode mode) {
|
||||
if (mode == QAudio::AudioInput) {
|
||||
return contextIsHMD ? hmdInputDeviceSetting : desktopInputDeviceSetting;
|
||||
|
@ -64,6 +66,8 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
|
|||
} else { // if (_mode == QAudio::AudioOutput)
|
||||
deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
|
||||
}
|
||||
} else {
|
||||
deviceName = HifiAudioDeviceInfo::DEFAULT_DEVICE_NAME;
|
||||
}
|
||||
return deviceName;
|
||||
}
|
||||
|
@ -139,7 +143,7 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
|
|||
} else if (role == SelectedHMDRole) {
|
||||
return _devices.at(index.row())->selectedHMD;
|
||||
} else if (role == InfoRole) {
|
||||
return QVariant::fromValue<QAudioDeviceInfo>(_devices.at(index.row())->info);
|
||||
return QVariant::fromValue<HifiAudioDeviceInfo>(_devices.at(index.row())->info);
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -191,18 +195,13 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD) {
|
||||
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
void AudioDeviceList::onDeviceChanged(const HifiAudioDeviceInfo& device, bool isHMD) {
|
||||
HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
selectedDevice = device;
|
||||
|
||||
for (auto i = 0; i < _devices.size(); ++i) {
|
||||
std::shared_ptr<AudioDevice> device = _devices[i];
|
||||
bool& isSelected = isHMD ? device->selectedHMD : device->selectedDesktop;
|
||||
if (isSelected && device->info != selectedDevice) {
|
||||
isSelected = false;
|
||||
} else if (device->info == selectedDevice) {
|
||||
isSelected = true;
|
||||
}
|
||||
isSelected = device->info == selectedDevice;
|
||||
}
|
||||
|
||||
emit deviceChanged(selectedDevice);
|
||||
|
@ -259,37 +258,46 @@ std::shared_ptr<scripting::AudioDevice> getSimilarDevice(const QString& deviceNa
|
|||
return devices[minDistanceIndex];
|
||||
}
|
||||
|
||||
void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
|
||||
void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices) {
|
||||
beginResetModel();
|
||||
|
||||
QList<std::shared_ptr<AudioDevice>> newDevices;
|
||||
bool hmdIsSelected = false;
|
||||
bool desktopIsSelected = false;
|
||||
|
||||
foreach(const QAudioDeviceInfo& deviceInfo, devices) {
|
||||
foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
|
||||
for (bool isHMD : {false, true}) {
|
||||
auto& backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName;
|
||||
if (deviceInfo.deviceName() == backupSelectedDeviceName) {
|
||||
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
selectedDevice = deviceInfo;
|
||||
backupSelectedDeviceName.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(const QAudioDeviceInfo& deviceInfo, devices) {
|
||||
foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
|
||||
AudioDevice device;
|
||||
device.info = deviceInfo;
|
||||
device.display = device.info.deviceName()
|
||||
.replace("High Definition", "HD")
|
||||
.remove("Device")
|
||||
.replace(" )", ")");
|
||||
|
||||
if (deviceInfo.isDefault()) {
|
||||
if (deviceInfo.getMode() == QAudio::AudioInput) {
|
||||
device.display = "Default microphone (recommended)";
|
||||
} else {
|
||||
device.display = "Default audio (recommended)";
|
||||
}
|
||||
} else {
|
||||
device.display = device.info.deviceName()
|
||||
.replace("High Definition", "HD")
|
||||
.remove("Device")
|
||||
.replace(" )", ")");
|
||||
}
|
||||
|
||||
for (bool isHMD : {false, true}) {
|
||||
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
|
||||
bool& isSelected = isHMD ? device.selectedHMD : device.selectedDesktop;
|
||||
|
||||
if (!selectedDevice.isNull()) {
|
||||
if (!selectedDevice.getDevice().isNull()) {
|
||||
isSelected = (device.info == selectedDevice);
|
||||
}
|
||||
else {
|
||||
|
@ -325,13 +333,13 @@ void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
|
|||
|
||||
if (!newDevices.isEmpty()) {
|
||||
if (!hmdIsSelected) {
|
||||
_backupSelectedHMDDeviceName = !_selectedHMDDevice.isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName;
|
||||
_backupSelectedHMDDeviceName = !_selectedHMDDevice.getDevice().isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName;
|
||||
auto device = getSimilarDevice(_backupSelectedHMDDeviceName, newDevices);
|
||||
device->selectedHMD = true;
|
||||
emit selectedDevicePlugged(device->info, true);
|
||||
}
|
||||
if (!desktopIsSelected) {
|
||||
_backupSelectedDesktopDeviceName = !_selectedDesktopDevice.isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName;
|
||||
_backupSelectedDesktopDeviceName = !_selectedDesktopDevice.getDevice().isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName;
|
||||
auto device = getSimilarDevice(_backupSelectedDesktopDeviceName, newDevices);
|
||||
device->selectedDesktop = true;
|
||||
emit selectedDevicePlugged(device->info, false);
|
||||
|
@ -382,8 +390,8 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
|
|||
_outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD);
|
||||
|
||||
// connections are made after client is initialized, so we must also fetch the devices
|
||||
const QList<QAudioDeviceInfo>& devicesInput = client->getAudioDevices(QAudio::AudioInput);
|
||||
const QList<QAudioDeviceInfo>& devicesOutput = client->getAudioDevices(QAudio::AudioOutput);
|
||||
const QList<HifiAudioDeviceInfo>& devicesInput = client->getAudioDevices(QAudio::AudioInput);
|
||||
const QList<HifiAudioDeviceInfo>& devicesOutput = client->getAudioDevices(QAudio::AudioOutput);
|
||||
|
||||
//setup devices
|
||||
_inputs.onDevicesChanged(devicesInput);
|
||||
|
@ -397,9 +405,9 @@ void AudioDevices::onContextChanged(const QString& context) {
|
|||
_outputs.resetDevice(_contextIsHMD);
|
||||
}
|
||||
|
||||
void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device,
|
||||
const QAudioDeviceInfo& previousDevice, bool isHMD) {
|
||||
QString deviceName = device.isNull() ? QString() : device.deviceName();
|
||||
void AudioDevices::onDeviceSelected(QAudio::Mode mode, const HifiAudioDeviceInfo& device,
|
||||
const HifiAudioDeviceInfo& previousDevice, bool isHMD) {
|
||||
QString deviceName = device.deviceName();
|
||||
|
||||
auto& setting = getSetting(isHMD, mode);
|
||||
|
||||
|
@ -410,7 +418,7 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d
|
|||
setting.set(deviceName);
|
||||
|
||||
// log the selected device
|
||||
if (!device.isNull()) {
|
||||
if (!device.getDevice().isNull()) {
|
||||
QJsonObject data;
|
||||
|
||||
const QString MODE = "audio_mode";
|
||||
|
@ -434,13 +442,13 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d
|
|||
}
|
||||
}
|
||||
|
||||
void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device) {
|
||||
void AudioDevices::onDeviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device) {
|
||||
if (mode == QAudio::AudioInput) {
|
||||
if (_requestedInputDevice == device) {
|
||||
onDeviceSelected(QAudio::AudioInput, device,
|
||||
_contextIsHMD ? _inputs._selectedHMDDevice : _inputs._selectedDesktopDevice,
|
||||
_contextIsHMD);
|
||||
_requestedInputDevice = QAudioDeviceInfo();
|
||||
_requestedInputDevice = HifiAudioDeviceInfo();
|
||||
}
|
||||
_inputs.onDeviceChanged(device, _contextIsHMD);
|
||||
} else { // if (mode == QAudio::AudioOutput)
|
||||
|
@ -448,13 +456,13 @@ void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& de
|
|||
onDeviceSelected(QAudio::AudioOutput, device,
|
||||
_contextIsHMD ? _outputs._selectedHMDDevice : _outputs._selectedDesktopDevice,
|
||||
_contextIsHMD);
|
||||
_requestedOutputDevice = QAudioDeviceInfo();
|
||||
_requestedOutputDevice = HifiAudioDeviceInfo();
|
||||
}
|
||||
_outputs.onDeviceChanged(device, _contextIsHMD);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices) {
|
||||
void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
//readout settings
|
||||
|
@ -503,14 +511,14 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceI
|
|||
}
|
||||
|
||||
|
||||
void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD) {
|
||||
void AudioDevices::chooseInputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
|
||||
//check if current context equals device to change
|
||||
if (_contextIsHMD == isHMD) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
_requestedInputDevice = device;
|
||||
QMetaObject::invokeMethod(client, "switchAudioDevice",
|
||||
Q_ARG(QAudio::Mode, QAudio::AudioInput),
|
||||
Q_ARG(const QAudioDeviceInfo&, device));
|
||||
Q_ARG(const HifiAudioDeviceInfo&, device));
|
||||
} else {
|
||||
//context is different. just save device in settings
|
||||
onDeviceSelected(QAudio::AudioInput, device,
|
||||
|
@ -520,14 +528,14 @@ void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD)
|
|||
}
|
||||
}
|
||||
|
||||
void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD) {
|
||||
void AudioDevices::chooseOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD) {
|
||||
//check if current context equals device to change
|
||||
if (_contextIsHMD == isHMD) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
_requestedOutputDevice = device;
|
||||
QMetaObject::invokeMethod(client, "switchAudioDevice",
|
||||
Q_ARG(QAudio::Mode, QAudio::AudioOutput),
|
||||
Q_ARG(const QAudioDeviceInfo&, device));
|
||||
Q_ARG(const HifiAudioDeviceInfo&, device));
|
||||
} else {
|
||||
//context is different. just save device in settings
|
||||
onDeviceSelected(QAudio::AudioOutput, device,
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
#include <QAbstractListModel>
|
||||
#include <QAudioDeviceInfo>
|
||||
|
||||
#include <HifiAudioDeviceInfo.h>
|
||||
|
||||
namespace scripting {
|
||||
|
||||
class AudioDevice {
|
||||
public:
|
||||
QAudioDeviceInfo info;
|
||||
HifiAudioDeviceInfo info;
|
||||
QString display;
|
||||
bool selectedDesktop { false };
|
||||
bool selectedHMD { false };
|
||||
|
@ -50,12 +52,12 @@ public:
|
|||
void resetDevice(bool contextIsHMD);
|
||||
|
||||
signals:
|
||||
void deviceChanged(const QAudioDeviceInfo& device);
|
||||
void selectedDevicePlugged(const QAudioDeviceInfo& device, bool isHMD);
|
||||
void deviceChanged(const HifiAudioDeviceInfo& device);
|
||||
void selectedDevicePlugged(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
protected slots:
|
||||
void onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD);
|
||||
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices);
|
||||
void onDeviceChanged(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
void onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices);
|
||||
|
||||
protected:
|
||||
friend class AudioDevices;
|
||||
|
@ -63,8 +65,8 @@ protected:
|
|||
static QHash<int, QByteArray> _roles;
|
||||
static Qt::ItemFlags _flags;
|
||||
const QAudio::Mode _mode;
|
||||
QAudioDeviceInfo _selectedDesktopDevice;
|
||||
QAudioDeviceInfo _selectedHMDDevice;
|
||||
HifiAudioDeviceInfo _selectedDesktopDevice;
|
||||
HifiAudioDeviceInfo _selectedHMDDevice;
|
||||
QString _backupSelectedDesktopDeviceName;
|
||||
QString _backupSelectedHMDDeviceName;
|
||||
QList<std::shared_ptr<AudioDevice>> _devices;
|
||||
|
@ -124,14 +126,14 @@ signals:
|
|||
void nop();
|
||||
|
||||
private slots:
|
||||
void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
void chooseInputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
void chooseOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
void onContextChanged(const QString& context);
|
||||
void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device,
|
||||
const QAudioDeviceInfo& previousDevice, bool isHMD);
|
||||
void onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device);
|
||||
void onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices);
|
||||
void onDeviceSelected(QAudio::Mode mode, const HifiAudioDeviceInfo& device,
|
||||
const HifiAudioDeviceInfo& previousDevice, bool isHMD);
|
||||
void onDeviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device);
|
||||
void onDevicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices);
|
||||
|
||||
private:
|
||||
friend class Audio;
|
||||
|
@ -141,8 +143,8 @@ private:
|
|||
|
||||
AudioInputDeviceList _inputs;
|
||||
AudioDeviceList _outputs { QAudio::AudioOutput };
|
||||
QAudioDeviceInfo _requestedOutputDevice;
|
||||
QAudioDeviceInfo _requestedInputDevice;
|
||||
HifiAudioDeviceInfo _requestedOutputDevice;
|
||||
HifiAudioDeviceInfo _requestedInputDevice;
|
||||
|
||||
const bool& _contextIsHMD;
|
||||
};
|
||||
|
|
|
@ -91,11 +91,23 @@ using Lock = std::unique_lock<Mutex>;
|
|||
Mutex _deviceMutex;
|
||||
Mutex _recordMutex;
|
||||
|
||||
HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode);
|
||||
|
||||
// thread-safe
|
||||
QList<QAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
|
||||
QList<HifiAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
|
||||
// NOTE: availableDevices() clobbers the Qt internal device list
|
||||
Lock lock(_deviceMutex);
|
||||
return QAudioDeviceInfo::availableDevices(mode);
|
||||
auto devices = QAudioDeviceInfo::availableDevices(mode);
|
||||
|
||||
QList<HifiAudioDeviceInfo> newDevices;
|
||||
|
||||
for (auto& device : devices) {
|
||||
newDevices.push_back(HifiAudioDeviceInfo(device, false, mode));
|
||||
}
|
||||
|
||||
newDevices.push_front(defaultAudioDeviceForMode(mode));
|
||||
|
||||
return newDevices;
|
||||
}
|
||||
|
||||
// now called from a background thread, to keep blocking operations off the audio thread
|
||||
|
@ -109,6 +121,9 @@ void AudioClient::checkDevices() {
|
|||
|
||||
auto inputDevices = getAvailableDevices(QAudio::AudioInput);
|
||||
auto outputDevices = getAvailableDevices(QAudio::AudioOutput);
|
||||
|
||||
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, inputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioInput));
|
||||
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, outputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioOutput));
|
||||
|
||||
Lock lock(_deviceMutex);
|
||||
if (inputDevices != _inputDevices) {
|
||||
|
@ -122,22 +137,22 @@ void AudioClient::checkDevices() {
|
|||
}
|
||||
}
|
||||
|
||||
QAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {
|
||||
HifiAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {
|
||||
Lock lock(_deviceMutex);
|
||||
|
||||
if (mode == QAudio::AudioInput) {
|
||||
return _inputDeviceInfo;
|
||||
} else { // if (mode == QAudio::AudioOutput)
|
||||
} else {
|
||||
return _outputDeviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAudioDeviceInfo> AudioClient::getAudioDevices(QAudio::Mode mode) const {
|
||||
QList<HifiAudioDeviceInfo> AudioClient::getAudioDevices(QAudio::Mode mode) const {
|
||||
Lock lock(_deviceMutex);
|
||||
|
||||
if (mode == QAudio::AudioInput) {
|
||||
return _inputDevices;
|
||||
} else { // if (mode == QAudio::AudioOutput)
|
||||
} else {
|
||||
return _outputDevices;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +241,7 @@ static float computeLoudness(int16_t* samples, int numSamples) {
|
|||
|
||||
template <int NUM_CHANNELS>
|
||||
static void applyGainSmoothing(float* buffer, int numFrames, float gain0, float gain1) {
|
||||
|
||||
|
||||
// fast path for unity gain
|
||||
if (gain0 == 1.0f && gain1 == 1.0f) {
|
||||
return;
|
||||
|
@ -241,7 +256,7 @@ static void applyGainSmoothing(float* buffer, int numFrames, float gain0, float
|
|||
float tStep = 1.0f / numFrames;
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
|
||||
|
||||
// evaluate poly over t=[0,1)
|
||||
float gain = (c3 * t + c2) * t * t + c0;
|
||||
t += tStep;
|
||||
|
@ -321,9 +336,9 @@ AudioClient::AudioClient() :
|
|||
}
|
||||
|
||||
connect(&_receivedAudioStream, &MixedProcessedAudioStream::processSamples,
|
||||
this, &AudioClient::processReceivedSamples, Qt::DirectConnection);
|
||||
connect(this, &AudioClient::changeDevice, this, [=](const QAudioDeviceInfo& outputDeviceInfo) {
|
||||
qCDebug(audioclient) << "got AudioClient::changeDevice signal, about to call switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
|
||||
this, &AudioClient::processReceivedSamples, Qt::DirectConnection);
|
||||
connect(this, &AudioClient::changeDevice, this, [=](const HifiAudioDeviceInfo& outputDeviceInfo) {
|
||||
qCDebug(audioclient)<< "got AudioClient::changeDevice signal, about to call switchOutputToAudioDevice() outputDeviceInfo: ["<< outputDeviceInfo.deviceName() << "]";
|
||||
switchOutputToAudioDevice(outputDeviceInfo);
|
||||
});
|
||||
|
||||
|
@ -373,7 +388,7 @@ AudioClient::AudioClient() :
|
|||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||
|
||||
auto& domainHandler = nodeList->getDomainHandler();
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this] {
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this] {
|
||||
_solo.reset();
|
||||
});
|
||||
connect(nodeList.data(), &NodeList::nodeActivated, this, [this](SharedNodePointer node) {
|
||||
|
@ -431,15 +446,14 @@ void AudioClient::setAudioPaused(bool pause) {
|
|||
}
|
||||
}
|
||||
|
||||
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
|
||||
QAudioDeviceInfo result;
|
||||
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
||||
HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
|
||||
HifiAudioDeviceInfo result;
|
||||
foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
||||
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
|
||||
result = audioDevice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -487,9 +501,11 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) {
|
|||
|
||||
#endif
|
||||
|
||||
QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
||||
HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
||||
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(mode);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (getAvailableDevices(mode).size() > 1) {
|
||||
if (devices.size() > 1) {
|
||||
AudioDeviceID defaultDeviceID = 0;
|
||||
uint32_t propertySize = sizeof(AudioDeviceID);
|
||||
AudioObjectPropertyAddress propertyAddress = {
|
||||
|
@ -519,9 +535,9 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
|||
|
||||
if (!getPropertyError && propertySize) {
|
||||
// find a device in the list that matches the name we have and return it
|
||||
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
||||
foreach(QAudioDeviceInfo audioDevice, devices){
|
||||
if (audioDevice.deviceName() == CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman)) {
|
||||
return audioDevice;
|
||||
return HifiAudioDeviceInfo(audioDevice, true, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -569,10 +585,18 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
qCDebug(audioclient) << "defaultAudioDeviceForMode mode: " << (mode == QAudio::AudioOutput ? "Output" : "Input")
|
||||
<< " [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]";
|
||||
HifiAudioDeviceInfo foundDevice;
|
||||
foreach(QAudioDeviceInfo audioDevice, devices) {
|
||||
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
|
||||
foundDevice=HifiAudioDeviceInfo(audioDevice,true,mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(audioclient) << "defaultAudioDeviceForMode mode: " << (mode == QAudio::AudioOutput ? "Output" : "Input")
|
||||
<< " [" << deviceName << "] [" << foundDevice.deviceName() << "]";
|
||||
|
||||
return getNamedAudioDeviceForMode(mode, deviceName);
|
||||
return foundDevice;
|
||||
#endif
|
||||
|
||||
#if defined (Q_OS_ANDROID)
|
||||
|
@ -580,18 +604,18 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
|||
Setting::Handle<bool> enableAEC(SETTING_AEC_KEY, DEFAULT_AEC_ENABLED);
|
||||
bool aecEnabled = enableAEC.get();
|
||||
auto audioClient = DependencyManager::get<AudioClient>();
|
||||
bool headsetOn = audioClient? audioClient->isHeadsetPluggedIn() : false;
|
||||
auto inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
|
||||
for (auto inputDevice : inputDevices) {
|
||||
bool headsetOn = audioClient ? audioClient->isHeadsetPluggedIn() : false;
|
||||
for (QAudioDeviceInfo inputDevice : devices) {
|
||||
if (((headsetOn || !aecEnabled) && inputDevice.deviceName() == VOICE_RECOGNITION) ||
|
||||
((!headsetOn && aecEnabled) && inputDevice.deviceName() == VOICE_COMMUNICATION)) {
|
||||
return inputDevice;
|
||||
((!headsetOn && aecEnabled) && inputDevice.deviceName() == VOICE_COMMUNICATION)) {
|
||||
return HifiAudioDeviceInfo(inputDevice, false, QAudio::AudioInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// fallback for failed lookup is the default device
|
||||
return (mode == QAudio::AudioInput) ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice();
|
||||
return (mode == QAudio::AudioInput) ? HifiAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice(), true,mode) :
|
||||
HifiAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice(), true, mode);
|
||||
}
|
||||
|
||||
bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) {
|
||||
|
@ -643,29 +667,29 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
|
|||
if (IsWindows8OrGreater()) {
|
||||
// On Windows using WASAPI shared-mode, returns the internal mix format
|
||||
return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat);
|
||||
} // else enumerate formats
|
||||
} // else enumerate formats
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
// Mac OSX returns the preferred CoreAudio format
|
||||
return nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
// As of Qt5.6, Android returns the native OpenSLES sample rate when possible, else 48000
|
||||
if (nativeFormatForAudioDevice(audioDevice, adjustedAudioFormat)) {
|
||||
return true;
|
||||
} // else enumerate formats
|
||||
} // else enumerate formats
|
||||
#endif
|
||||
|
||||
|
||||
adjustedAudioFormat = desiredAudioFormat;
|
||||
|
||||
//
|
||||
// Attempt the device sample rate and channel count in decreasing order of preference.
|
||||
//
|
||||
const int sampleRates[] = { 48000, 44100, 32000, 24000, 16000, 96000, 192000, 88200, 176400 };
|
||||
const int inputChannels[] = { 1, 2, 4, 6, 8 }; // prefer mono
|
||||
const int outputChannels[] = { 2, 4, 6, 8, 1 }; // prefer stereo, downmix as last resort
|
||||
const int inputChannels[] = { 1, 2, 4, 6, 8 }; // prefer mono
|
||||
const int outputChannels[] = { 2, 4, 6, 8, 1 }; // prefer stereo, downmix as last resort
|
||||
|
||||
for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) {
|
||||
for (int sampleRate : sampleRates) {
|
||||
|
@ -758,22 +782,22 @@ void AudioClient::start() {
|
|||
_desiredOutputFormat = _desiredInputFormat;
|
||||
_desiredOutputFormat.setChannelCount(OUTPUT_CHANNEL_COUNT);
|
||||
|
||||
QAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput);
|
||||
HifiAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput);
|
||||
qCDebug(audioclient) << "The default audio input device is" << inputDeviceInfo.deviceName();
|
||||
bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo);
|
||||
|
||||
QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput);
|
||||
HifiAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput);
|
||||
qCDebug(audioclient) << "The default audio output device is" << outputDeviceInfo.deviceName();
|
||||
bool outputFormatSupported = switchOutputToAudioDevice(outputDeviceInfo);
|
||||
|
||||
if (!inputFormatSupported) {
|
||||
qCDebug(audioclient) << "Unable to set up audio input because of a problem with input format.";
|
||||
qCDebug(audioclient) << "The closest format available is" << inputDeviceInfo.nearestFormat(_desiredInputFormat);
|
||||
qCDebug(audioclient) << "The closest format available is" << inputDeviceInfo.getDevice().nearestFormat(_desiredInputFormat);
|
||||
}
|
||||
|
||||
if (!outputFormatSupported) {
|
||||
qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format.";
|
||||
qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat);
|
||||
qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.getDevice().nearestFormat(_desiredOutputFormat);
|
||||
}
|
||||
#if defined(Q_OS_ANDROID)
|
||||
connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout);
|
||||
|
@ -783,10 +807,10 @@ void AudioClient::start() {
|
|||
|
||||
void AudioClient::stop() {
|
||||
qCDebug(audioclient) << "AudioClient::stop(), requesting switchInputToAudioDevice() to shut down";
|
||||
switchInputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
switchInputToAudioDevice(HifiAudioDeviceInfo(), true);
|
||||
|
||||
qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down";
|
||||
switchOutputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
switchOutputToAudioDevice(HifiAudioDeviceInfo(), true);
|
||||
|
||||
// Stop triggering the checks
|
||||
QObject::disconnect(_checkPeakValuesTimer, &QTimer::timeout, nullptr, nullptr);
|
||||
|
@ -978,16 +1002,18 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
|
|||
|
||||
}
|
||||
|
||||
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo) {
|
||||
auto device = deviceInfo;
|
||||
|
||||
if (device.isNull()) {
|
||||
device = defaultAudioDeviceForMode(mode);
|
||||
void AudioClient::changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode) {
|
||||
HifiAudioDeviceInfo currentDevice = mode == QAudio::AudioInput ? _inputDeviceInfo : _outputDeviceInfo;
|
||||
if (currentDevice.isDefault() && currentDevice.getDevice() != newDefault.getDevice()) {
|
||||
switchAudioDevice(mode, newDefault);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo) {
|
||||
auto device = deviceInfo;
|
||||
if (mode == QAudio::AudioInput) {
|
||||
return switchInputToAudioDevice(device);
|
||||
} else { // if (mode == QAudio::AudioOutput)
|
||||
} else {
|
||||
return switchOutputToAudioDevice(device);
|
||||
}
|
||||
}
|
||||
|
@ -1030,7 +1056,7 @@ void AudioClient::configureReverb() {
|
|||
p.wetDryMix = 100.0f;
|
||||
p.preDelay = 0.0f;
|
||||
p.earlyGain = -96.0f; // disable ER
|
||||
p.lateGain += _reverbOptions->getWetDryMix() * (24.0f/100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix
|
||||
p.lateGain += _reverbOptions->getWetDryMix() * (24.0f / 100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix
|
||||
p.lateMixLeft = 0.0f;
|
||||
p.lateMixRight = 0.0f;
|
||||
|
||||
|
@ -1414,7 +1440,7 @@ void AudioClient::handleMicAudioInput() {
|
|||
} else if (_timeSinceLastClip >= 0.0f) {
|
||||
_timeSinceLastClip += AudioConstants::NETWORK_FRAME_SECS;
|
||||
}
|
||||
isClipping = (_timeSinceLastClip >= 0.0f) && (_timeSinceLastClip < 2.0f); // 2 second hold time
|
||||
isClipping = (_timeSinceLastClip >= 0.0f) && (_timeSinceLastClip < 2.0f); // 2 second hold time
|
||||
|
||||
#if defined(WEBRTC_ENABLED)
|
||||
if (_isAECEnabled) {
|
||||
|
@ -1453,7 +1479,7 @@ void AudioClient::handleDummyAudioInput() {
|
|||
? AudioConstants::NETWORK_FRAME_BYTES_STEREO
|
||||
: AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
|
||||
|
||||
QByteArray audioBuffer(numNetworkBytes, 0); // silent
|
||||
QByteArray audioBuffer(numNetworkBytes, 0); // silent
|
||||
handleAudioInput(audioBuffer);
|
||||
}
|
||||
|
||||
|
@ -1598,7 +1624,7 @@ bool AudioClient::mixLocalAudioInjectors(float* mixBuffer) {
|
|||
// direct mix into mixBuffer
|
||||
injector->getLocalHRTF().mixStereo(_localScratchBuffer, mixBuffer, gain,
|
||||
AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
} else { // injector is mono
|
||||
} else { // injector is mono
|
||||
|
||||
if (options.positionSet) {
|
||||
|
||||
|
@ -1736,7 +1762,7 @@ void AudioClient::setAcousticEchoCancellation(bool enable, bool emitSignal) {
|
|||
|
||||
bool AudioClient::setIsStereoInput(bool isStereoInput) {
|
||||
bool stereoInputChanged = false;
|
||||
if (isStereoInput != _isStereoInput && _inputDeviceInfo.supportedChannelCounts().contains(2)) {
|
||||
if (isStereoInput != _isStereoInput && _inputDeviceInfo.getDevice().supportedChannelCounts().contains(2)) {
|
||||
_isStereoInput = isStereoInput;
|
||||
stereoInputChanged = true;
|
||||
|
||||
|
@ -1798,17 +1824,17 @@ void AudioClient::outputFormatChanged() {
|
|||
_receivedAudioStream.outputFormatChanged(_outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT);
|
||||
}
|
||||
|
||||
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) {
|
||||
bool AudioClient::switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) {
|
||||
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
|
||||
|
||||
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]";
|
||||
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << _inputDeviceInfo.deviceName() <<"----"<<inputDeviceInfo.getDevice().deviceName() << "]";
|
||||
bool supportedFormat = false;
|
||||
|
||||
// NOTE: device start() uses the Qt internal device list
|
||||
Lock lock(_deviceMutex);
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
_shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged
|
||||
_shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged
|
||||
#endif
|
||||
|
||||
// cleanup any previously initialized device
|
||||
|
@ -1822,8 +1848,6 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
_audioInput->deleteLater();
|
||||
_audioInput = NULL;
|
||||
_numInputCallbackBytes = 0;
|
||||
|
||||
_inputDeviceInfo = QAudioDeviceInfo();
|
||||
}
|
||||
|
||||
if (_dummyAudioInput) {
|
||||
|
@ -1854,12 +1878,16 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!inputDeviceInfo.isNull()) {
|
||||
if (!inputDeviceInfo.getDevice().isNull()) {
|
||||
qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available.";
|
||||
|
||||
bool doEmit = _inputDeviceInfo.deviceName() != inputDeviceInfo.deviceName();
|
||||
_inputDeviceInfo = inputDeviceInfo;
|
||||
emit deviceChanged(QAudio::AudioInput, inputDeviceInfo);
|
||||
if (doEmit) {
|
||||
emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo);
|
||||
}
|
||||
|
||||
if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) {
|
||||
if (adjustedFormatForAudioDevice(_inputDeviceInfo.getDevice(), _desiredInputFormat, _inputFormat)) {
|
||||
qCDebug(audioclient) << "The format to be used for audio input is" << _inputFormat;
|
||||
|
||||
// we've got the best we can get for input
|
||||
|
@ -1884,7 +1912,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
|
||||
// if the user wants stereo but this device can't provide then bail
|
||||
if (!_isStereoInput || _inputFormat.channelCount() == 2) {
|
||||
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this);
|
||||
_audioInput = new QAudioInput(_inputDeviceInfo.getDevice(), _inputFormat, this);
|
||||
_numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat);
|
||||
_audioInput->setBufferSize(_numInputCallbackBytes);
|
||||
// different audio input devices may have different volumes
|
||||
|
@ -1906,7 +1934,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleMicAudioInput()));
|
||||
supportedFormat = true;
|
||||
} else {
|
||||
qCDebug(audioclient) << "Error starting audio input -" << _audioInput->error();
|
||||
qCDebug(audioclient) << "Error starting audio input -" << _audioInput->error();
|
||||
_audioInput->deleteLater();
|
||||
_audioInput = NULL;
|
||||
}
|
||||
|
@ -1919,7 +1947,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
// This enables clients without a mic to still receive an audio stream from the mixer.
|
||||
if (!_audioInput) {
|
||||
qCDebug(audioclient) << "Audio input device is not available, using dummy input.";
|
||||
_inputDeviceInfo = QAudioDeviceInfo();
|
||||
_inputDeviceInfo.setDevice(QAudioDeviceInfo());
|
||||
emit deviceChanged(QAudio::AudioInput, _inputDeviceInfo);
|
||||
|
||||
_inputFormat = _desiredInputFormat;
|
||||
|
@ -1975,11 +2003,11 @@ void AudioClient::checkInputTimeout() {
|
|||
|
||||
void AudioClient::setHeadsetPluggedIn(bool pluggedIn) {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
if (pluggedIn == !_isHeadsetPluggedIn && !_inputDeviceInfo.isNull()) {
|
||||
QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField<jstring>("android/os/Build", "BRAND");
|
||||
if (pluggedIn == !_isHeadsetPluggedIn && !_inputDeviceInfo.getDevice().isNull()) {
|
||||
QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField<jstring>("android/os/Build", "BRAND");
|
||||
// some samsung phones needs more time to shutdown the previous input device
|
||||
if (brand.toString().contains("samsung", Qt::CaseInsensitive)) {
|
||||
switchInputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
switchInputToAudioDevice(HifiAudioDeviceInfo(), true);
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
|
@ -2026,7 +2054,7 @@ void AudioClient::outputNotify() {
|
|||
}
|
||||
}
|
||||
|
||||
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
|
||||
bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
|
||||
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
|
||||
|
||||
qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
|
||||
|
@ -2061,8 +2089,6 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
|
||||
delete[] _localOutputMixBuffer;
|
||||
_localOutputMixBuffer = NULL;
|
||||
|
||||
_outputDeviceInfo = QAudioDeviceInfo();
|
||||
}
|
||||
|
||||
// cleanup any resamplers
|
||||
|
@ -2086,12 +2112,15 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!outputDeviceInfo.isNull()) {
|
||||
if (!outputDeviceInfo.getDevice().isNull()) {
|
||||
qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available.";
|
||||
bool doEmit = _outputDeviceInfo.deviceName() != outputDeviceInfo.deviceName();
|
||||
_outputDeviceInfo = outputDeviceInfo;
|
||||
emit deviceChanged(QAudio::AudioOutput, outputDeviceInfo);
|
||||
if (doEmit) {
|
||||
emit deviceChanged(QAudio::AudioOutput, _outputDeviceInfo);
|
||||
}
|
||||
|
||||
if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) {
|
||||
if (adjustedFormatForAudioDevice(_outputDeviceInfo.getDevice(), _desiredOutputFormat, _outputFormat)) {
|
||||
qCDebug(audioclient) << "The format to be used for audio output is" << _outputFormat;
|
||||
|
||||
// we've got the best we can get for input
|
||||
|
@ -2113,7 +2142,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
outputFormatChanged();
|
||||
|
||||
// setup our general output device for audio-mixer audio
|
||||
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
_audioOutput = new QAudioOutput(_outputDeviceInfo.getDevice(), _outputFormat, this);
|
||||
|
||||
int deviceChannelCount = _outputFormat.channelCount();
|
||||
int frameSize = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * deviceChannelCount * _outputFormat.sampleRate()) / _desiredOutputFormat.sampleRate();
|
||||
|
@ -2165,7 +2194,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
localAudioLock.unlock();
|
||||
|
||||
// setup a loopback audio output device
|
||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo.getDevice(), _outputFormat, this);
|
||||
|
||||
_timeSinceLastReceived.start();
|
||||
|
||||
|
@ -2239,7 +2268,7 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) {
|
|||
|
||||
// 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 {
|
||||
|
@ -2423,4 +2452,4 @@ void AudioClient::setInputVolume(float volume, bool emitSignal) {
|
|||
emit inputVolumeChanged(_audioInput->volume());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include "AudioIOStats.h"
|
||||
#include "AudioFileWav.h"
|
||||
#include "HifiAudioDeviceInfo.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning( push )
|
||||
|
@ -102,8 +103,8 @@ public:
|
|||
_audio(audio), _unfulfilledReads(0) {}
|
||||
|
||||
void start() { open(QIODevice::ReadOnly | QIODevice::Unbuffered); }
|
||||
qint64 readData(char * data, qint64 maxSize) override;
|
||||
qint64 writeData(const char * data, qint64 maxSize) override { return 0; }
|
||||
qint64 readData(char* data, qint64 maxSize) override;
|
||||
qint64 writeData(const char* data, qint64 maxSize) override { return 0; }
|
||||
int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; }
|
||||
private:
|
||||
LocalInjectorsStream& _localInjectorsStream;
|
||||
|
@ -111,7 +112,7 @@ public:
|
|||
AudioClient* _audio;
|
||||
int _unfulfilledReads;
|
||||
};
|
||||
|
||||
|
||||
void startThread();
|
||||
void negotiateAudioFormat();
|
||||
void selectAudioFormat(const QString& selectedCodecName);
|
||||
|
@ -152,12 +153,12 @@ public:
|
|||
void setIsPlayingBackRecording(bool isPlayingBackRecording) { _isPlayingBackRecording = isPlayingBackRecording; }
|
||||
|
||||
Q_INVOKABLE void setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 scale);
|
||||
|
||||
|
||||
bool outputLocalInjector(const AudioInjectorPointer& injector) override;
|
||||
|
||||
QAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const;
|
||||
QList<QAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const;
|
||||
|
||||
HifiAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const;
|
||||
QList<HifiAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const;
|
||||
|
||||
void enablePeakValues(bool enable) { _enablePeakValues = enable; }
|
||||
bool peakValuesAvailable() const;
|
||||
|
||||
|
@ -233,11 +234,11 @@ public slots:
|
|||
int setOutputBufferSize(int numFrames, bool persist = true);
|
||||
|
||||
bool shouldLoopbackInjectors() override { return _shouldEchoToServer; }
|
||||
Q_INVOKABLE void changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode);
|
||||
|
||||
// calling with a null QAudioDevice will use the system default
|
||||
bool switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo = QAudioDeviceInfo());
|
||||
bool switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo = HifiAudioDeviceInfo());
|
||||
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
|
||||
|
||||
// Qt opensles plugin is not able to detect when the headset is plugged in
|
||||
void setHeadsetPluggedIn(bool pluggedIn);
|
||||
|
||||
|
@ -269,10 +270,10 @@ signals:
|
|||
void noiseGateOpened();
|
||||
void noiseGateClosed();
|
||||
|
||||
void changeDevice(const QAudioDeviceInfo& outputDeviceInfo);
|
||||
void changeDevice(const HifiAudioDeviceInfo& outputDeviceInfo);
|
||||
|
||||
void deviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device);
|
||||
void devicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices);
|
||||
void deviceChanged(QAudio::Mode mode, const HifiAudioDeviceInfo& device);
|
||||
void devicesChanged(QAudio::Mode mode, const QList<HifiAudioDeviceInfo>& devices);
|
||||
void peakValueListChanged(const QList<float> peakValueList);
|
||||
|
||||
void receivedFirstPacket();
|
||||
|
@ -416,7 +417,7 @@ private:
|
|||
float* _localOutputMixBuffer { NULL };
|
||||
Mutex _localAudioMutex;
|
||||
AudioLimiter _audioLimiter;
|
||||
|
||||
|
||||
// Adds Reverb
|
||||
void configureReverb();
|
||||
void updateReverbOptions();
|
||||
|
@ -437,8 +438,8 @@ private:
|
|||
void processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate);
|
||||
#endif
|
||||
|
||||
bool switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false);
|
||||
|
||||
// Callback acceleration dependent calculations
|
||||
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
|
||||
|
@ -459,11 +460,11 @@ private:
|
|||
glm::vec3 avatarBoundingBoxCorner;
|
||||
glm::vec3 avatarBoundingBoxScale;
|
||||
|
||||
QAudioDeviceInfo _inputDeviceInfo;
|
||||
QAudioDeviceInfo _outputDeviceInfo;
|
||||
HifiAudioDeviceInfo _inputDeviceInfo;
|
||||
HifiAudioDeviceInfo _outputDeviceInfo;
|
||||
|
||||
QList<QAudioDeviceInfo> _inputDevices;
|
||||
QList<QAudioDeviceInfo> _outputDevices;
|
||||
QList<HifiAudioDeviceInfo> _inputDevices;
|
||||
QList<HifiAudioDeviceInfo> _outputDevices;
|
||||
|
||||
AudioFileWav _audioFileWav;
|
||||
|
||||
|
@ -476,7 +477,7 @@ private:
|
|||
|
||||
CodecPluginPointer _codec;
|
||||
QString _selectedCodecName;
|
||||
Encoder* _encoder { nullptr }; // for outbound mic stream
|
||||
Encoder* _encoder { nullptr }; // for outbound mic stream
|
||||
|
||||
RateCounter<> _silentOutbound;
|
||||
RateCounter<> _audioOutbound;
|
||||
|
@ -484,11 +485,11 @@ private:
|
|||
RateCounter<> _audioInbound;
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
bool _shouldRestartInputSetup { true }; // Should we restart the input device because of an unintended stop?
|
||||
bool _shouldRestartInputSetup { true }; // Should we restart the input device because of an unintended stop?
|
||||
#endif
|
||||
|
||||
AudioSolo _solo;
|
||||
|
||||
|
||||
Mutex _checkDevicesMutex;
|
||||
QTimer* _checkDevicesTimer { nullptr };
|
||||
Mutex _checkPeakValuesMutex;
|
||||
|
@ -498,4 +499,4 @@ private:
|
|||
};
|
||||
|
||||
|
||||
#endif // hifi_AudioClient_h
|
||||
#endif // hifi_AudioClient_h
|
36
libraries/audio-client/src/HifiAudioDeviceInfo.cpp
Normal file
36
libraries/audio-client/src/HifiAudioDeviceInfo.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// HifiAudioDeviceInfo.cpp
|
||||
// libraries/audio-client/src
|
||||
//
|
||||
// Created by Amer Cerkic on 9/14/19.
|
||||
// Copyright 2019 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 "HifiAudioDeviceInfo.h"
|
||||
|
||||
const QString HifiAudioDeviceInfo::DEFAULT_DEVICE_NAME = "default ";
|
||||
|
||||
void HifiAudioDeviceInfo::setDevice(QAudioDeviceInfo devInfo) {
|
||||
_audioDeviceInfo = devInfo;
|
||||
}
|
||||
|
||||
HifiAudioDeviceInfo& HifiAudioDeviceInfo::operator=(const HifiAudioDeviceInfo& other) {
|
||||
_audioDeviceInfo = other.getDevice();
|
||||
_mode = other.getMode();
|
||||
_isDefault = other.isDefault();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool HifiAudioDeviceInfo::operator==(const HifiAudioDeviceInfo& rhs) const {
|
||||
//Does the QAudioDeviceinfo match as well as is this the default device or
|
||||
return getDevice() == rhs.getDevice() && isDefault() == rhs.isDefault();
|
||||
}
|
||||
bool HifiAudioDeviceInfo::operator!=(const HifiAudioDeviceInfo& rhs) const {
|
||||
return getDevice() != rhs.getDevice() || isDefault() != rhs.isDefault();
|
||||
}
|
||||
|
69
libraries/audio-client/src/HifiAudioDeviceInfo.h
Normal file
69
libraries/audio-client/src/HifiAudioDeviceInfo.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// HifiAudioDeviceInfo.h
|
||||
// libraries/audio-client/src
|
||||
//
|
||||
// Created by Amer Cerkic on 9/14/19.
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_audiodeviceinfo_h
|
||||
#define hifi_audiodeviceinfo_h
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QAudioDeviceInfo>
|
||||
#include <QAudio>
|
||||
#include <QString>
|
||||
|
||||
class HifiAudioDeviceInfo : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HifiAudioDeviceInfo() : QObject() {}
|
||||
HifiAudioDeviceInfo(const HifiAudioDeviceInfo &deviceInfo) : QObject(){
|
||||
_audioDeviceInfo = deviceInfo.getDevice();
|
||||
_mode = deviceInfo.getMode();
|
||||
_isDefault = deviceInfo.isDefault();
|
||||
}
|
||||
|
||||
HifiAudioDeviceInfo(QAudioDeviceInfo deviceInfo, bool isDefault, QAudio::Mode mode) :
|
||||
_audioDeviceInfo(deviceInfo),
|
||||
_isDefault(isDefault),
|
||||
_mode(mode){
|
||||
}
|
||||
|
||||
void setMode(QAudio::Mode mode) { _mode = mode; }
|
||||
void setIsDefault() { _isDefault = true; }
|
||||
void setDevice(QAudioDeviceInfo devInfo);
|
||||
QString deviceName() const {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
return _audioDeviceInfo.deviceName();
|
||||
#endif
|
||||
if (_isDefault) {
|
||||
return DEFAULT_DEVICE_NAME;
|
||||
} else {
|
||||
return _audioDeviceInfo.deviceName();
|
||||
}
|
||||
}
|
||||
QAudioDeviceInfo getDevice() const { return _audioDeviceInfo; }
|
||||
bool isDefault() const { return _isDefault; }
|
||||
QAudio::Mode getMode() const { return _mode; }
|
||||
|
||||
HifiAudioDeviceInfo& operator=(const HifiAudioDeviceInfo& other);
|
||||
bool operator==(const HifiAudioDeviceInfo& rhs) const;
|
||||
bool operator!=(const HifiAudioDeviceInfo& rhs) const;
|
||||
|
||||
private:
|
||||
QAudioDeviceInfo _audioDeviceInfo;
|
||||
bool _isDefault { false };
|
||||
QAudio::Mode _mode { QAudio::AudioInput };
|
||||
|
||||
public:
|
||||
static const QString DEFAULT_DEVICE_NAME;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -356,7 +356,7 @@ void OffscreenQmlSurface::onRootCreated() {
|
|||
getSurfaceContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||
|
||||
// Connect with the audio client and listen for audio device changes
|
||||
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const QAudioDeviceInfo& device) {
|
||||
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const HifiAudioDeviceInfo& device) {
|
||||
if (mode == QAudio::Mode::AudioOutput) {
|
||||
QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, Q_ARG(QString, device.deviceName()));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue