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.
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;
}