Reputation: 539
https://learn.microsoft.com/en-us/windows/desktop/api/devicetopology/nf-devicetopology-iaudioautogaincontrol-setenabled
I'm trying to do a C# wrapper/call to set this low level device setting value. It basically disables/enables AGC microphone setting. I've found this link but i'm not sure how to wire it up to look like this:
// http://msdn.microsoft.com/en-us/library/dd757304%28VS.85%29.aspx
[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
public static extern Int32 mixerGetNumDevs();
Essentially, I want to disable (uncheck) this enhancement
Upvotes: 6
Views: 1354
Reputation: 139256
Here is a pure C# console app sample, equivalent of @Drake's C/C++ code. I've written it using code from an open source project called DirectN that defines thousands of c# Windows interop types (DirectX, etc.), including Code Audio API, etc.
class Program
{
static void Main(string[] args)
{
// using DirectN
var enumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
// or call GetDevice(...) with an id
enumerator.GetDefaultAudioEndpoint(
__MIDL___MIDL_itf_mmdeviceapi_0000_0000_0001.eCapture,
__MIDL___MIDL_itf_mmdeviceapi_0000_0000_0002.eConsole,
out var device).ThrowOnError();
const int CLSCTX_ALL = 23;
device.Activate(typeof(IDeviceTopology).GUID, CLSCTX_ALL, null, out var iface).ThrowOnError();
var topology = (IDeviceTopology)iface;
topology.GetConnector(0, out var connector).ThrowOnError();
var part = (IPart)connector;
if (part.Activate(CLSCTX_ALL, typeof(IAudioAutoGainControl).GUID, out iface).IsError)
{
Console.WriteLine("AGC not supported.");
return;
}
var control = (IAudioAutoGainControl)iface;
control.SetEnabled(true, IntPtr.Zero);
}
[ComImport]
[Guid("bcde0395-e52f-467c-8e3d-c4579291692e")] // CLSID_MMDeviceEnumerator
class MMDeviceEnumerator
{
}
}
You can use either the DirectN's nuget package, or copy to your project only the needed .cs files (and their dependencies). Here, you would need the following:
HRESULT.cs
HRESULTS.cs
IAudioAutoGainControl.cs
IAudioVolumeLevel.cs
IConnector.cs
IControlChangeNotify.cs
IControlInterface.cs
IDeviceTopology.cs
IMMDevice.cs
IMMDeviceCollection.cs
IMMDeviceEnumerator.cs
IMMNotificationClient.cs
IPart.cs
IPartsList.cs
IPerChannelDbLevel.cs
ISubunit.cs
PROPERTYKEY.cs
PropertyType.cs
PropVariant.cs
_tagpropertykey.cs
__MIDL___MIDL_itf_devicetopology_0000_0000_0011.cs
__MIDL___MIDL_itf_devicetopology_0000_0000_0012.cs
__MIDL___MIDL_itf_devicetopology_0000_0000_0013.cs
__MIDL___MIDL_itf_mmdeviceapi_0000_0000_0001.cs
__MIDL___MIDL_itf_mmdeviceapi_0000_0000_0002.cs
Upvotes: 0
Reputation: 7190
This answer has discussed "How to use interface pointer exported by C++ DLL in C#". But, I think what you want more is as below.
You don't need to use the winapi. The auto gain control functionality is implemented in the AudioQualityEnhancer
class, which is a mediahandler. It uses the AutoGainControl
bool property to enable or disable the gain control feature.
Automatic Gain Control example in C#:
using System;
using Ozeki.Media;
namespace Automatic_Gain_Control
{
class Program
{
static Microphone microphone;
static Speaker speaker;
static MediaConnector connector;
static AudioQualityEnhancer audioProcessor;
static void Main(string[] args)
{
microphone = Microphone.GetDefaultDevice();
speaker = Speaker.GetDefaultDevice();
connector = new MediaConnector();
audioProcessor = new AudioQualityEnhancer();
audioProcessor.AutoGainControl = true;//enable
audioProcessor.GainSpeed = 12;
audioProcessor.MaxGain = 30;
connector.Connect(microphone, audioProcessor);
connector.Connect(audioProcessor, speaker);
microphone.Start();
speaker.Start();
Console.ReadLine();
}
}
}
UPDATE:
To disable the AGC with interface simply, You can encapsulate all interface procedures in your own DLL functions, like:
HRESULT EnableAGC()
{
CComPtr<IMMDeviceEnumerator> m_pIMMEnumerator;
CComPtr<IAudioVolumeLevel> m_pMicBoost;
CComPtr<IAudioAutoGainControl> m_pAGC;
HRESULT hr = S_OK;
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (void**)&m_pIMMEnumerator);
if (FAILED(hr)) return hr;
CComPtr<IMMDevice> pIMMDeivce = NULL;
std::wstring strEndPointID;//String of the Device ID
if (strEndPointID.empty())
{
hr = m_pIMMEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pIMMDeivce);
}
else
{
hr = m_pIMMEnumerator->GetDevice(strEndPointID.c_str(), &pIMMDeivce);
}
if (FAILED(hr)) return hr;
CComPtr<IDeviceTopology> pTopo = NULL;
hr = pIMMDeivce->Activate(IID_IDeviceTopology, CLSCTX_INPROC_SERVER, 0, (void**)&pTopo);
if (FAILED(hr)) return hr;
CComPtr<IConnector> pConn = NULL;
hr = pTopo->GetConnector(0, &pConn);
if (FAILED(hr)) return hr;
CComPtr<IConnector> pConnNext = NULL;
hr = pConn->GetConnectedTo(&pConnNext);
if (FAILED(hr)) return hr;
CComPtr<IPart> pPart = NULL;
hr = pConnNext->QueryInterface(IID_IPart, (void**)&pPart);
if (FAILED(hr)) return hr;
hr = pPart->Activate(CLSCTX_INPROC_SERVER, IID_IAudioAutoGainControl, (void**)&m_pAGC);
if (SUCCEEDED(hr) && m_pAGC)
{
//Hardware Supports Microphone AGC
BOOL bEnable = TRUE;
hr = m_pAGC->SetEnabled(bEnable, NULL);
}
else
{
//Hardware not Supports Microphone AGC
}
return hr;
}
Upvotes: 6