diff options
| author | Roxie Linden <roxie@lindenlab.com> | 2024-04-01 21:39:17 -0700 | 
|---|---|---|
| committer | Roxie Linden <roxie@lindenlab.com> | 2024-04-01 21:39:17 -0700 | 
| commit | c826aea079c59950a4064a94825534884fed8bf8 (patch) | |
| tree | 3267543b3ee11002e6862388135327171917b782 | |
| parent | c6e673cda139f5faaa52ccd03a372e7ffa9f5716 (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.
| -rw-r--r-- | indra/llwebrtc/llwebrtc.cpp | 230 | ||||
| -rw-r--r-- | indra/llwebrtc/llwebrtc_impl.h | 6 | ||||
| -rw-r--r-- | indra/newview/llvoicewebrtc.cpp | 66 | 
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;  | 
