2014-03-06 140 views
2

我想控制麥克風輸入上的升壓/ AGC設置。 Windows 7音頻屬性顯示它有一個AGC選項。如何使用C++控制麥克風升壓/ AGC

但是,當我嘗試通過C++訪問它時,它回來說設備上沒有AGC。

我使用DeviceTopology類WASAPI沒有任何API來控制AGC功能 這裏是到目前爲止的代碼:

(大部分來自MSDN論壇樣品解禁)

#include <windows.h> 
    #include <stdio.h> 
    #include <mmdeviceapi.h> 
    #include <devicetopology.h> 

    HRESULT WalkTreeBackwardsFromPart(IPart *pPart, int iTabLevel = 0); 
    HRESULT DisplayVolume(IAudioVolumeLevel *pVolume, int iTabLevel); 
    HRESULT DisplayMute(IAudioMute *pMute, int iTabLevel); 
    void Tab(int iTabLevel); 

    int __cdecl main(void) { 
    HRESULT hr = CoInitialize(NULL); 
    if (FAILED(hr)) { 
     printf("Failed CoInitializeEx: hr = 0x%08x\n", hr); 
     return __LINE__; 
    } 

    // get default render endpoint 
    IMMDeviceEnumerator *pEnum = NULL; 
    hr = CoCreateInstance(
     __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), 
     (void**)&pEnum 
    ); 
    if (FAILED(hr)) { 
     printf("Couldn't get device enumerator: hr = 0x%08x\n", hr); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    IMMDevice *pDevice = NULL; 
    hr = pEnum->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice); 
    if (FAILED(hr)) { 
     printf("Couldn't get default render device: hr = 0x%08x\n", hr); 
     pEnum->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pEnum->Release(); 

    // get device topology object for that endpoint 
    IDeviceTopology *pDT = NULL; 
    hr = pDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&pDT); 
    if (FAILED(hr)) { 
     printf("Couldn't get device topology object: hr = 0x%08x\n", hr); 
     pDevice->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pDevice->Release(); 

    // get the single connector for that endpoint 
    IConnector *pConnEndpoint = NULL; 
    hr = pDT->GetConnector(0, &pConnEndpoint); 
    if (FAILED(hr)) { 
     printf("Couldn't get the connector on the endpoint: hr = 0x%08x\n", hr); 
     pDT->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pDT->Release(); 

    // get the connector on the device that is 
    // connected to 
    // the connector on the endpoint 
    IConnector *pConnDevice = NULL; 
    hr = pConnEndpoint->GetConnectedTo(&pConnDevice); 
    if (FAILED(hr)) { 
     printf("Couldn't get the connector on the device: hr = 0x%08x\n", hr); 
     pConnEndpoint->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pConnEndpoint->Release(); 

    // QI on the device's connector for IPart 
    IPart *pPart = NULL; 
    hr = pConnDevice->QueryInterface(__uuidof(IPart), (void**)&pPart); 
    if (FAILED(hr)) { 
     printf("Couldn't get the part: hr = 0x%08x\n", hr); 
     pConnDevice->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pConnDevice->Release(); 

    // all the real work is done in this function 
    hr = WalkTreeBackwardsFromPart(pPart); 
    if (FAILED(hr)) { 
     printf("Couldn't walk the tree: hr = 0x%08x\n", hr); 
     pPart->Release(); 
     CoUninitialize(); 
     return __LINE__; 
    } 
    pPart->Release(); 

    CoUninitialize(); 

    system("pause"); 
    return 0; 
    } 

    HRESULT WalkTreeBackwardsFromPart(IPart *pPart, int iTabLevel /* = 0 */) { 
    HRESULT hr = S_OK; 

    Tab(iTabLevel); 
    LPWSTR pwszPartName = NULL; 
    hr = pPart->GetName(&pwszPartName); 
    if (FAILED(hr)) { 
     printf("Could not get part name: hr = 0x%08x", hr); 
     return hr; 
    } 
    printf("Part name: %ws\n", *pwszPartName ? pwszPartName : L"(Unnamed)"); 
    CoTaskMemFree(pwszPartName); 


    // 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) { 
      printf("NO AGC CONTROL\n"); 
     // not a Microphone node 
    } else if (FAILED(hr)) { 
     printf("Unexpected failure trying to activate IAudioAutoGainControl : hr = 0x%08x\n", hr); 
     return hr; 
    } else { 
     // it's an AGC node... 
     printf("HAS AGC CONTROL"); 
     if (FAILED(hr)) { 
      printf("AGC Failed: hr = 0x%08x", hr); 
      aGCcontrol->Release(); 
      return hr; 
     } 

     aGCcontrol->Release(); 
    } 


    return S_OK; 
} 

回答

3

我終於想通了如何去做這個。我在上面的示例代碼中省略了代碼的一些重要部分。

爲了幫助其他人有這個相同的困境,這裏的解決方案。編譯只是用printf替換MessageBox語句。

這裏重要的一點是,枚舉部分時一定要知道它是一個輸入還是一個輸出。否則,你將永遠找不到你要找的零件。此示例正在查找eCapture端點的可用部分。

這裏是我的消息來源: http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9741bae1-c330-4802-9860-2fd202dba797/enumeration-of-available-levels-for-a-specific-installed-sound-card?forum=windowspro-audiodevelopment

讓我知道如果你有問題,編譯它。

#include <windows.h> 
#include <stdio.h> 
#include <mmdeviceapi.h> 
#include <devicetopology.h> 

HRESULT WalkTreeBackwardsFromPart(IPart *pPart, int iTabLevel = 0); 
HRESULT DisplayVolume(IAudioVolumeLevel *pVolume, int iTabLevel); 
HRESULT DisplayMute(IAudioMute *pMute, int iTabLevel); 
void Tab(int iTabLevel); 

int __cdecl main(void) { 
HRESULT hr = CoInitialize(NULL); 
if (FAILED(hr)) { 
    printf("Failed CoInitializeEx: hr = 0x%08x\n", hr); 
    return __LINE__; 
} 

// get default render endpoint 
IMMDeviceEnumerator *pEnum = NULL; 
hr = CoCreateInstance(
    __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), 
    (void**)&pEnum 
); 
if (FAILED(hr)) { 
    printf("Couldn't get device enumerator: hr = 0x%08x\n", hr); 
    CoUninitialize(); 
    return __LINE__; 
} 
IMMDevice *pDevice = NULL; 
hr = pEnum->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice); 
if (FAILED(hr)) { 
    printf("Couldn't get default capture device: hr = 0x%08x\n", hr); 
    pEnum->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pEnum->Release(); 

// get device topology object for that endpoint 
IDeviceTopology *pDT = NULL; 
hr = pDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&pDT); 
if (FAILED(hr)) { 
    printf("Couldn't get device topology object: hr = 0x%08x\n", hr); 
    pDevice->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pDevice->Release(); 

// get the single connector for that endpoint 
IConnector *pConnEndpoint = NULL; 
hr = pDT->GetConnector(0, &pConnEndpoint); 
if (FAILED(hr)) { 
    printf("Couldn't get the connector on the endpoint: hr = 0x%08x\n", hr); 
    pDT->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pDT->Release(); 

// get the connector on the device that is 
// connected to 
// the connector on the endpoint 
IConnector *pConnDevice = NULL; 
hr = pConnEndpoint->GetConnectedTo(&pConnDevice); 
if (FAILED(hr)) { 
    printf("Couldn't get the connector on the device: hr = 0x%08x\n", hr); 
    pConnEndpoint->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pConnEndpoint->Release(); 

// QI on the device's connector for IPart 
IPart *pPart = NULL; 
hr = pConnDevice->QueryInterface(__uuidof(IPart), (void**)&pPart); 
if (FAILED(hr)) { 
    printf("Couldn't get the part: hr = 0x%08x\n", hr); 
    pConnDevice->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pConnDevice->Release(); 

// all the real work is done in this function 
hr = WalkTreeBackwardsFromPart(pPart); 
if (FAILED(hr)) { 
    printf("Couldn't walk the tree: hr = 0x%08x\n", hr); 
    pPart->Release(); 
    CoUninitialize(); 
    return __LINE__; 
} 
pPart->Release(); 

CoUninitialize(); 

system("pause"); 
return 0; 
} 

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

LPWSTR pwszPartName = NULL; 
hr = pPart->GetName(&pwszPartName); 
if (FAILED(hr)) { 
    printf("Could not get part name: hr = 0x%08x", hr); 
    return hr; 
} 
printf("Part name: %ws\n", *pwszPartName ? pwszPartName : L"(Unnamed)"); 
CoTaskMemFree(pwszPartName); 


// 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) { 
     printf("NO AGC CONTROL\n"); 
    // not a Microphone node 
} else if (FAILED(hr)) { 
    printf("Unexpected failure trying to activate IAudioAutoGainControl : hr = 0x%08x\n", hr); 
    return hr; 
} else { 
    // it's an AGC node... 
    printf("HAS AGC CONTROL"); 
    aGCcontrol->SetEnabled(1, NULL); //Activate it 

    if (FAILED(hr)) { 
     printf("AGC Failed: hr = 0x%08x", 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 
    MessageBox("No incoming parts at this part\n", MB_OK); 
} 
if (FAILED(hr)) { 
    MessageBox("Couldn't enum outgoing parts", MB_OK); 
} 
UINT nParts = 0; 
hr = pOutgoingParts->GetCount(&nParts); 
if (FAILED(hr)) { 
    MessageBox("Couldn't get count of outgoing parts", MB_OK); 
    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)) { 
     MessageBox("Couldn't get part ", MB_OK); 
     pOutgoingParts->Release(); 
     return hr; 
    } 

    hr = WalkTreeBackwardsFromPart(pOutgoingPart); 
    if (FAILED(hr)) { 
     MessageBox("Couldn't walk tree on part", MB_OK); 
     pOutgoingPart->Release(); 
     pOutgoingParts->Release(); 
     return hr; 
    } 
    pOutgoingPart->Release(); 
} 

pOutgoingParts->Release(); 

return S_OK; 

}