0

is there a way to disable the microphone audio enhancements from C++ code?

We are doing some audio processing things on the incoming microphone signal, and the microphone enhancements cause all kinds of trouble. We know we can turn it off manually on Windows10 by going to the Control panel --> Sound --> Recording --> Microphone --> Properties --> advanced--> Enhancements, but we need a way to do this from code.

enter image description here

when I try to access it via C++ It comes back saying there is no AGC on the device.

void AudioDeviceWindowsCore::DisableHardwareAGC() {
  // get device topology object for that endpoint
  CComPtr<IDeviceTopology> pTopo = NULL;
  HRESULT ret = _ptrDeviceIn->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL,
                               (void**)&pTopo);
  if (FAILED(ret)) {
    RTC_LOG(LS_ERROR) << "Couldn't get device topology object: hr = 0x"
                      << rtc::ToHex(ret);
  } else {
    UINT count = 0;
    pTopo->GetConnectorCount(&count);

    CComPtr<IConnector> pConn = NULL;
    ret = pTopo->GetConnector(0, &pConn);
    if (FAILED(ret)) {
      RTC_LOG(LS_ERROR) << __FUNCTION__ << " GetConnector:" << rtc::ToHex(ret);
      return ;
    }
    CComPtr<IConnector> pConnNext = NULL;
    ret = pConn->GetConnectedTo(&pConnNext);
    if (FAILED(ret)) {
      RTC_LOG(LS_ERROR) << __FUNCTION__
                        << " GetConnectedTo:" << rtc::ToHex(ret);
      return ;
    }
    CComPtr<IPart> pPart = NULL;
    const IID IID_IPart = __uuidof(IPart);
    ret = pConnNext->QueryInterface(IID_IPart, (void**)&pPart);
    if (FAILED(ret)) {
      RTC_LOG(LS_ERROR) << __FUNCTION__
                        << " QueryInterface:" << rtc::ToHex(ret);
      return ;
    }

    // all the real work is done in this function
    ret = WalkTreeForwardsFromPart(pPart);

    if (SUCCEEDED(ret)) {
      RTC_LOG(INFO) << " now close hardware AGC ret:" << rtc::ToHex(ret);
    } else {
      RTC_LOG(INFO) << " Hardware not Supports Microphone AGC";
    }
  }
}

HRESULT WalkTreeForwardsFromPart(IPart* pPart) {
  HRESULT hr = S_OK;

  LPWSTR pwszPartName = NULL;
  hr = pPart->GetName(&pwszPartName);
  if (FAILED(hr)) {
    RTC_LOG(LS_ERROR) << "Could not get part name: hr = 0x"<<rtc::ToHex(hr);
    return hr;
  }
  RTC_LOG(INFO) << "Part name: " << *pwszPartName ? pwszPartName : L"Unnamed";
  CoTaskMemFree(pwszPartName);
  GUID type_id;
  hr = pPart->GetSubType(&type_id);
  if (hr == S_OK){
    if (IsEqualGUID(type_id,KSNODETYPE_LOUDNESS) ) {
      const IID IID_IAudioLoudness = __uuidof(IAudioLoudness);
      IAudioLoudness* loudness = NULL;
      hr = pPart->Activate(CLSCTX_ALL, IID_IAudioLoudness, (void**)&loudness);
      if (E_NOINTERFACE == hr) {
        RTC_LOG(LS_ERROR) << "NO AudioLoudness CONTROL";
        // not a Microphone node
      } else if (FAILED(hr)) {
        RTC_LOG(LS_ERROR) << "Unexpected failure trying to activate "
                             "IID_IAudioLoudness : hr = 0x"
                          << rtc::ToHex(hr);
      } else {
        // it's an AGC node...
        RTC_LOG(INFO) << "HAS IAudioLoudness CONTROL";
        hr = loudness->SetEnabled(0, NULL);

        if (FAILED(hr)) {
          RTC_LOG(LS_ERROR)
              << "AudioLoudness Failed: hr = 0x" << rtc::ToHex(hr);
          loudness->Release();
          return hr;
        }

        loudness->Release();
      }
    } else if (IsEqualGUID(type_id, KSNODETYPE_AGC)) {
      // Check AGC settings
      const IID IID_IAudioAutoGainControl = __uuidof(IAudioAutoGainControl);

      IAudioAutoGainControl* aGCcontrol = NULL;
      hr = pPart->Activate(CLSCTX_ALL, IID_IAudioAutoGainControl,
                           (void**)&aGCcontrol);
      if (E_NOINTERFACE == hr) {
        RTC_LOG(LS_ERROR) << "NO AGC CONTROL";
        // not a Microphone node
      } else if (FAILED(hr)) {
        RTC_LOG(LS_ERROR) << "Unexpected failure trying to activate "
                             "IAudioAutoGainControl : hr = 0x"
                          << rtc::ToHex(hr);
        return hr;
      } else {
        // it's an AGC node...
        RTC_LOG(INFO) << "HAS AGC CONTROL";
        aGCcontrol->SetEnabled(0, NULL);

        if (FAILED(hr)) {
          RTC_LOG(LS_ERROR) << "AGC Failed: hr = 0x" << rtc::ToHex(hr);
          aGCcontrol->Release();
          return hr;
        }
        aGCcontrol->Release();
      }
    }
  }

  // get the list of incoming parts
  IPartsList* pOutgoingParts = NULL;
  hr = pPart->EnumPartsOutgoing(&pOutgoingParts);

  if (E_NOTFOUND == hr) {
    // not an error... we've just reached the end of the path
    RTC_LOG(INFO) << "No incoming parts at this part";
    return hr;
  }
  if (FAILED(hr)) {
    RTC_LOG(LS_ERROR) << " Couldn't enum outgoing parts";
    return hr;
  }
  UINT nParts = 0;
  hr = pOutgoingParts->GetCount(&nParts);
  if (FAILED(hr)) {
    RTC_LOG(LS_ERROR) << "Couldn't get count of outgoing parts";
    pOutgoingParts->Release();
    return hr;
  }

  // walk the tree on each incoming part recursively
  for (UINT n = 0; n < nParts; n++) {
    IPart* pOutgoingPart = NULL;
    hr = pOutgoingParts->GetPart(n, &pOutgoingPart);
    if (FAILED(hr)) {
      RTC_LOG(LS_ERROR) << "Couldn't get part ";
      pOutgoingParts->Release();
      return hr;
    }

    hr = WalkTreeForwardsFromPart(pOutgoingPart);
    if (FAILED(hr)) {
      RTC_LOG(LS_ERROR) << " Couldn't walk tree on part";
      pOutgoingPart->Release();
      pOutgoingParts->Release();
      return hr;
    }
    pOutgoingPart->Release();
  }

  pOutgoingParts->Release();

  return S_OK;
}
Mark
  • 1
  • https://stackoverflow.com/questions/64035110/what-is-the-expected-effect-of-using-iaudioclient2setclientproperties-on-a-cap – Mark Jan 12 '23 at 10:20

0 Answers0