summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRoxie Linden <roxie@lindenlab.com>2024-04-01 21:39:17 -0700
committerRoxie Linden <roxie@lindenlab.com>2024-04-01 21:39:17 -0700
commitc826aea079c59950a4064a94825534884fed8bf8 (patch)
tree3267543b3ee11002e6862388135327171917b782 /indra
parentc6e673cda139f5faaa52ccd03a372e7ffa9f5716 (diff)
Fix "default" audio device handling.
Windows and Mac/Linux behave slightly differently with respect to Default devices, in that mac/linux (I think) simply assumes the device at index 0 is the default one, and windows has a separate API for enabling the default device.
Diffstat (limited to 'indra')
-rw-r--r--indra/llwebrtc/llwebrtc.cpp230
-rw-r--r--indra/llwebrtc/llwebrtc_impl.h6
-rw-r--r--indra/newview/llvoicewebrtc.cpp66
3 files changed, 173 insertions, 129 deletions
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index 074b037529..75b2332bed 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -40,6 +40,11 @@
namespace llwebrtc
{
+static int16_t PLAYOUT_DEVICE_DEFAULT = -1;
+static int16_t PLAYOUT_DEVICE_BAD = -2;
+static int16_t RECORD_DEVICE_DEFAULT = -1;
+static int16_t RECORD_DEVICE_BAD = -2;
+
LLAudioDeviceObserver::LLAudioDeviceObserver() : mSumVector {0}, mMicrophoneEnergy(0.0) {}
float LLAudioDeviceObserver::getMicrophoneEnergy() { return mMicrophoneEnergy; }
@@ -189,10 +194,16 @@ void LLWebRTCImpl::init()
std::unique_ptr<webrtc::AudioDeviceDataObserver>(mTuningAudioDeviceObserver));
mTuningDeviceModule->Init();
- mTuningDeviceModule->SetStereoRecording(true);
- mTuningDeviceModule->SetStereoPlayout(true);
+ mTuningDeviceModule->SetPlayoutDevice(mPlayoutDevice);
+ mTuningDeviceModule->SetRecordingDevice(mRecordingDevice);
mTuningDeviceModule->EnableBuiltInAEC(false);
mTuningDeviceModule->SetAudioDeviceSink(this);
+ mTuningDeviceModule->InitMicrophone();
+ mTuningDeviceModule->InitSpeaker();
+ mTuningDeviceModule->InitRecording();
+ mTuningDeviceModule->InitPlayout();
+ mTuningDeviceModule->SetStereoRecording(true);
+ mTuningDeviceModule->SetStereoPlayout(true);
updateDevices();
});
@@ -207,13 +218,13 @@ void LLWebRTCImpl::init()
mPeerDeviceModule->Init();
mPeerDeviceModule->SetPlayoutDevice(mPlayoutDevice);
mPeerDeviceModule->SetRecordingDevice(mRecordingDevice);
- mPeerDeviceModule->SetStereoRecording(true);
- mPeerDeviceModule->SetStereoPlayout(true);
mPeerDeviceModule->EnableBuiltInAEC(false);
mPeerDeviceModule->InitMicrophone();
mPeerDeviceModule->InitSpeaker();
mPeerDeviceModule->InitRecording();
mPeerDeviceModule->InitPlayout();
+ mPeerDeviceModule->SetStereoRecording(true);
+ mPeerDeviceModule->SetStereoPlayout(true);
});
// The custom processor allows us to retrieve audio data (and levels)
@@ -375,145 +386,169 @@ void LLWebRTCImpl::unsetDevicesObserver(LLWebRTCDevicesObserver *observer)
}
}
-static int16_t ll_get_device_module_capture_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, const std::string &id)
-{
- int16_t recordingDevice = 0;
- int16_t captureDeviceCount = device_module->RecordingDevices();
- for (int16_t i = 0; i < captureDeviceCount; i++)
- {
- char name[webrtc::kAdmMaxDeviceNameSize];
- char guid[webrtc::kAdmMaxGuidSize];
- device_module->RecordingDeviceName(i, name, guid);
- if (id == guid || id == "Default") // first one in list is default
- {
- RTC_LOG(LS_INFO) << __FUNCTION__ << "Set recording device to " << name << " " << guid << " " << i;
- recordingDevice = i;
- break;
- }
- }
- return recordingDevice;
-}
-
void ll_set_device_module_capture_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, int16_t device)
{
device_module->StopRecording();
- device_module->SetRecordingDevice(device);
+#if LL_WINDOWS
+ if (device < 0)
+ {
+ device_module->SetRecordingDevice(webrtc::AudioDeviceModule::kDefaultDevice);
+ }
+ else
+ {
+ device_module->SetRecordingDevice(device);
+ }
+#else
+ // passed in default is -1, but the device list
+ // has it at 0
+ device_module->SetPlayoutDevice(device + 1);
+#endif
device_module->InitMicrophone();
- device_module->SetStereoRecording(false);
device_module->InitRecording();
+ device_module->SetStereoRecording(false);
device_module->StartRecording();
}
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
{
-
- mWorkerThread->PostTask(
- [this, id]()
+ int16_t recordingDevice = RECORD_DEVICE_DEFAULT;
+ if (id != "Default")
+ {
+ for (int16_t i = 0; i < mRecordingDeviceList.size(); i++)
{
- int16_t recordingDevice = ll_get_device_module_capture_device(mTuningDeviceModule, id);
- if (recordingDevice != mRecordingDevice)
+ if (mRecordingDeviceList[i].mID == id)
{
- mRecordingDevice = recordingDevice;
- if (mTuningMode)
- {
- ll_set_device_module_capture_device(mTuningDeviceModule, recordingDevice);
- }
- else
- {
- ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice);
- }
+ recordingDevice = i;
+ break;
}
- });
-}
-
-static int16_t ll_get_device_module_render_device(
- rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module,
- const std::string &id)
-{
- int16_t playoutDevice = 0;
- int16_t playoutDeviceCount = device_module->PlayoutDevices();
- for (int16_t i = 0; i < playoutDeviceCount; i++)
- {
- char name[webrtc::kAdmMaxDeviceNameSize];
- char guid[webrtc::kAdmMaxGuidSize];
- device_module->PlayoutDeviceName(i, name, guid);
- if (id == guid || id == "Default") // first one in list is default
- {
- RTC_LOG(LS_INFO) << __FUNCTION__ << "Set recording device to " << name << " " << guid << " " << i;
- playoutDevice = i;
- break;
}
}
- return playoutDevice;
+ if (recordingDevice == mRecordingDevice)
+ {
+ return;
+ }
+ mRecordingDevice = recordingDevice;
+ if (mTuningMode)
+ {
+ mWorkerThread->PostTask([this, recordingDevice]() { ll_set_device_module_capture_device(mTuningDeviceModule, recordingDevice); });
+ }
+ else
+ {
+ mWorkerThread->PostTask([this, recordingDevice]() { ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice); });
+ }
}
void ll_set_device_module_render_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, int16_t device)
{
device_module->StopPlayout();
- device_module->SetPlayoutDevice(device);
+#if LL_WINDOWS
+ if (device < 0)
+ {
+ device_module->SetPlayoutDevice(webrtc::AudioDeviceModule::kDefaultDevice);
+ }
+ else
+ {
+ device_module->SetPlayoutDevice(device);
+ }
+#else
+ device_module->SetPlayoutDevice(device + 1);
+#endif
device_module->InitSpeaker();
- device_module->SetStereoPlayout(false);
device_module->InitPlayout();
- device_module->StartPlayout();
+ device_module->SetStereoPlayout(true);
}
void LLWebRTCImpl::setRenderDevice(const std::string &id)
{
- mWorkerThread->PostTask(
- [this, id]()
- {
- int16_t playoutDevice = ll_get_device_module_render_device(mTuningDeviceModule, id);
- if (playoutDevice != mPlayoutDevice)
+ int16_t playoutDevice = PLAYOUT_DEVICE_DEFAULT;
+ if (id != "Default")
+ {
+ for (int16_t i = 0; i < mPlayoutDeviceList.size(); i++)
+ {
+ if (mPlayoutDeviceList[i].mID == id)
{
- mPlayoutDevice = playoutDevice;
- if (mTuningMode)
- {
- ll_set_device_module_render_device(mTuningDeviceModule, playoutDevice);
- }
- else
- {
- ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
- }
+ playoutDevice = i;
+ break;
}
- });
+ }
+ }
+ if (playoutDevice == mPlayoutDevice)
+ {
+ return;
+ }
+ mPlayoutDevice = playoutDevice;
+
+ if (mTuningMode)
+ {
+ mWorkerThread->PostTask(
+ [this, playoutDevice]()
+ {
+ ll_set_device_module_render_device(mTuningDeviceModule, playoutDevice);
+ });
+ }
+ else
+ {
+ mWorkerThread->PostTask(
+ [this, playoutDevice]()
+ {
+ ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
+ mPeerDeviceModule->StartPlayout();
+ });
+ }
}
// updateDevices needs to happen on the worker thread.
void LLWebRTCImpl::updateDevices()
{
- int16_t renderDeviceCount = mTuningDeviceModule->PlayoutDevices();
- int16_t currentRenderDeviceIndex = mTuningDeviceModule->GetPlayoutDevice();
-
- LLWebRTCVoiceDeviceList renderDeviceList;
- for (int16_t index = 0; index < renderDeviceCount; index++)
+ int16_t renderDeviceCount = mTuningDeviceModule->PlayoutDevices();
+
+ mPlayoutDeviceList.clear();
+#if LL_WINDOWS
+ int16_t index = 0;
+#else
+ // index zero is always "Default" for darwin/linux,
+ // which is a special case, so skip it.
+ int16_t index = 1;
+#endif
+ for (; index < renderDeviceCount; index++)
{
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mTuningDeviceModule->PlayoutDeviceName(index, name, guid);
- renderDeviceList.emplace_back(name, guid);
+ mPlayoutDeviceList.emplace_back(name, guid);
}
- int16_t captureDeviceCount = mTuningDeviceModule->RecordingDevices();
- int16_t currentCaptureDeviceIndex = mTuningDeviceModule->GetRecordingDevice();
-
- LLWebRTCVoiceDeviceList captureDeviceList;
- for (int16_t index = 0; index < captureDeviceCount; index++)
+ int16_t captureDeviceCount = mTuningDeviceModule->RecordingDevices();
+
+ mRecordingDeviceList.clear();
+#if LL_WINDOWS
+ index = 0;
+#else
+ // index zero is always "Default" for darwin/linux,
+ // which is a special case, so skip it.
+ index = 1;
+#endif
+ for (; index < captureDeviceCount; index++)
{
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mTuningDeviceModule->RecordingDeviceName(index, name, guid);
- captureDeviceList.emplace_back(name, guid);
+ mRecordingDeviceList.emplace_back(name, guid);
}
+
for (auto &observer : mVoiceDevicesObserverList)
{
- observer->OnDevicesChanged(renderDeviceList,
- captureDeviceList);
+ observer->OnDevicesChanged(mPlayoutDeviceList, mRecordingDeviceList);
}
}
void LLWebRTCImpl::OnDevicesUpdated()
{
+ // reset these to a bad value so an update is forced
+ mRecordingDevice = RECORD_DEVICE_BAD;
+ mPlayoutDevice = PLAYOUT_DEVICE_BAD;
+
updateDevices();
}
@@ -529,17 +564,24 @@ void LLWebRTCImpl::setTuningMode(bool enable)
mPeerDeviceModule->StopPlayout();
ll_set_device_module_render_device(mTuningDeviceModule, mPlayoutDevice);
ll_set_device_module_capture_device(mTuningDeviceModule, mRecordingDevice);
+ mTuningDeviceModule->InitPlayout();
+ mTuningDeviceModule->InitRecording();
mTuningDeviceModule->StartRecording();
- mTuningDeviceModule->StartPlayout();
+ // TODO: Starting Playout on the TDM appears to create an audio artifact (click)
+ // in this case, so disabling it for now. We may have to do something different
+ // if we enable 'echo playback' via the TDM when tuning.
+ //mTuningDeviceModule->StartPlayout();
}
else
{
mTuningDeviceModule->StopRecording();
- mTuningDeviceModule->StopPlayout();
+ //mTuningDeviceModule->StopPlayout();
ll_set_device_module_render_device(mPeerDeviceModule, mPlayoutDevice);
ll_set_device_module_capture_device(mPeerDeviceModule, mRecordingDevice);
- mPeerDeviceModule->StartRecording();
+ mPeerDeviceModule->InitPlayout();
+ mPeerDeviceModule->InitRecording();
mPeerDeviceModule->StartPlayout();
+ mPeerDeviceModule->StartRecording();
}
}
);
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index 328e962c50..78ae6b4444 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -244,8 +244,12 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceS
// accessors in native webrtc for devices aren't apparently implemented yet.
bool mTuningMode;
- int32_t mPlayoutDevice;
int32_t mRecordingDevice;
+ LLWebRTCVoiceDeviceList mRecordingDeviceList;
+
+ int32_t mPlayoutDevice;
+ LLWebRTCVoiceDeviceList mPlayoutDeviceList;
+
bool mMute;
LLAudioDeviceObserver * mTuningAudioDeviceObserver;
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index f3d3460022..3cc4aa113c 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -294,19 +294,31 @@ void LLWebRTCVoiceClient::updateSettings()
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE
setVoiceEnabled(LLVoiceClient::getInstance()->voiceEnabled());
- setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
+ static LLCachedControl<S32> sVoiceEarLocation(gSavedSettings, "VoiceEarLocation");
+ setEarLocation(sVoiceEarLocation);
+
+ static LLCachedControl<std::string> sInputDevice(gSavedSettings, "VoiceInputAudioDevice");
+ setCaptureDevice(sInputDevice);
+
+ static LLCachedControl<std::string> sOutputDevice(gSavedSettings, "VoiceOutputAudioDevice");
+ setRenderDevice(sOutputDevice);
+
+ static LLCachedControl<F32> sMicLevel(gSavedSettings, "AudioLevelMic");
+ setMicGain(sMicLevel);
- std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
- setCaptureDevice(inputDevice);
- std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
- setRenderDevice(outputDevice);
- F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
- setMicGain(mic_level);
-
llwebrtc::LLWebRTCDeviceInterface::AudioConfig config;
- config.mEchoCancellation = gSavedSettings.getBOOL("VoiceEchoCancellation");
- config.mAGC = gSavedSettings.getBOOL("VoiceAutomaticGainControl");
- config.mNoiseSuppressionLevel = (llwebrtc::LLWebRTCDeviceInterface::AudioConfig::ENoiseSuppressionLevel)gSavedSettings.getU32("VoiceNoiseSuppressionLevel");
+
+ static LLCachedControl<bool> sEchoCancellation(gSavedSettings, "VoiceEchoCancellation", true);
+ config.mEchoCancellation = sEchoCancellation;
+
+ static LLCachedControl<bool> sAGC(gSavedSettings, "VoiceAutomaticGainControl", true);
+ config.mAGC = sAGC;
+
+ static LLCachedControl<U32> sNoiseSuppressionLevel(gSavedSettings,
+ "VoiceNoiseSuppressionLevel",
+ llwebrtc::LLWebRTCDeviceInterface::AudioConfig::ENoiseSuppressionLevel::NOISE_SUPPRESSION_LEVEL_VERY_HIGH);
+ config.mNoiseSuppressionLevel = (llwebrtc::LLWebRTCDeviceInterface::AudioConfig::ENoiseSuppressionLevel) (U32)sNoiseSuppressionLevel;
+
mWebRTCDeviceInterface->setAudioConfig(config);
}
@@ -607,6 +619,7 @@ void LLWebRTCVoiceClient::setDevicesListUpdated(bool state)
void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList& render_devices,
const llwebrtc::LLWebRTCVoiceDeviceList& capture_devices)
{
+
LL::WorkQueue::postMaybe(mMainQueue,
[=]
{
@@ -618,43 +631,25 @@ void LLWebRTCVoiceClient::OnDevicesChangedImpl(const llwebrtc::LLWebRTCVoiceDevi
const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE
-
std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
LL_DEBUGS("Voice") << "Setting devices to-input: '" << inputDevice << "' output: '" << outputDevice << "'" << LL_ENDL;
clearRenderDevices();
- bool renderDeviceSet = false;
for (auto &device : render_devices)
{
addRenderDevice(LLVoiceDevice(device.mDisplayName, device.mID));
- LL_DEBUGS("Voice") << "Checking render device" << "'" << device.mID << "'" << LL_ENDL;
- if (outputDevice == device.mID)
- {
- renderDeviceSet = true;
- }
- }
- if (!renderDeviceSet)
- {
- setRenderDevice("Default");
}
+ setRenderDevice(outputDevice);
clearCaptureDevices();
- bool captureDeviceSet = false;
for (auto &device : capture_devices)
{
LL_DEBUGS("Voice") << "Checking capture device:'" << device.mID << "'" << LL_ENDL;
addCaptureDevice(LLVoiceDevice(device.mDisplayName, device.mID));
- if (inputDevice == device.mID)
- {
- captureDeviceSet = true;
- }
- }
- if (!captureDeviceSet)
- {
- setCaptureDevice("Default");
}
+ setCaptureDevice(inputDevice);
setDevicesListUpdated(true);
}
@@ -1559,10 +1554,13 @@ F32 LLWebRTCVoiceClient::getUserVolume(const LLUUID& id)
// Minimum volume will be returned for users with voice disabled
F32 result = LLVoiceClient::VOLUME_MIN;
- participantStatePtr_t participant(mSession->findParticipantByID(id));
- if(participant)
+ if (mSession)
{
- result = participant->mVolume;
+ participantStatePtr_t participant(mSession->findParticipantByID(id));
+ if (participant)
+ {
+ result = participant->mVolume;
+ }
}
return result;