6

enter image description herehttps://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

Don P
  • 519
  • 6
  • 12

2 Answers2

6

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;
}
Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • what is Ozeki.Media? This seems like it implements its own Auto gain control. I'm not interested in that. I'm more interested in disabling the one that comes on my sound card that is visible in windows sound settings - low level device setting. – Don P May 21 '19 at 14:48
  • That's the reference in OzekiSDK.dll(should be downloaded). Yes, that's implements its own Auto gain control. To disable the AGC with interface simply, you can encapsulate all interface procedures in your own DLL functions. See my update. – Drake Wu May 22 '19 at 03:34
0

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   
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298