2013-04-07 102 views
2

我试图调整麦克风的播放音量级别;但不幸的是我不能。我可以使用NAudio库控制麦克风的录音音量,但我想控制播放音量。有什么方法可以控制Windows 7上的麦克风播放音量吗?C++或C#解决方案对我来说都是可以接受的。windows 7控制麦克风的播放音量

这里有一些试图解决我的问题:

http://www.computercabal.com/2010/11/mute-microphone-from-c-on-windows.html(这家伙写了一个小库,可以静音麦克风录音音量)。

NAudio - Cannot set line control mute value(此解决方案只能将麦克风录音音量静音)。

这又是一个令人沮丧的尝试,通过使用n音讯解决我的问题,这静音只麦克风录音电平,太:

MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(); 

MMDeviceCollection devices = DevEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active); 

MMDevice micDevice = null; 

for (int i = 0; i < devices.Count; i++) 
{ 
    MMDevice deviceAt = devices[i]; 
    Console.WriteLine(deviceAt.FriendlyName); 
    if (deviceAt.FriendlyName.ToLower().StartsWith("mikrofon")) 
    { 
     micDevice = deviceAt; 
    } 
} 

micDevice.AudioEndpointVolume.Mute = true; 
+0

您不通过麦克风播放,您通过扬声器播放。我误解了吗? – 2013-04-07 12:22:49

+0

在Realtek HD Audio Manager的麦克风选项卡中有回放音量级别,实际上我想控制此级别。 – haitaka 2013-04-07 12:24:43

+0

好吧,我明白了,所以在这种情况下,麦克风插孔正用于从媒体设备播放? – 2013-04-07 12:27:32

回答

2

我有同样的问题,我已经使用IDeviceTopology界面找到了答案。

我使用了在网络中浮动的WalkTreeBackwardsFromPart示例。

首先,您必须获取渲染设备(扬声器)的零件。

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; 
IMMDeviceCollection *pDevices = NULL; 

hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices); 

UINT count; 
hr = pDevices->GetCount(&count); 

// Each loop prints the name of an endpoint device. 
for (ULONG i = 0; i < count; i++) 
{ 

     //hr = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); 
    hr = pDevices->Item(i, &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(); 
} 

最后一部分叫做WalkTreeBackwardsFromPart是魔术发生的地方。

我在这里测试的代码只是通过输入部分并找到标有“Front Pink In”(这是麦克风的插孔)的那个,当音量正在显示时,它为此设置音量部分。这不是最好的代码,但我只是想找到正确的部分。

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); 

// see if this is a volume node part 
IAudioVolumeLevel *pVolume = NULL; 
hr = pPart->Activate(CLSCTX_ALL, __uuidof(IAudioVolumeLevel), (void**)&pVolume); 
if (E_NOINTERFACE == hr) { 
    // not a volume node 
} else if (FAILED(hr)) { 
    printf("Unexpected failure trying to activate IAudioVolumeLevel: hr = 0x%08x\n", hr); 
    return hr; 
} else { 
    // it's a volume node... 
    hr = DisplayVolume(pVolume, iTabLevel, wcscmp(L"Front Pink In", pwszPartName) == 0); 
    if (FAILED(hr)) { 
     printf("DisplayVolume failed: hr = 0x%08x", hr); 
     pVolume->Release(); 
     return hr; 
    } 

    if (wcscmp(L"Microphone Boost", pwszPartName) == 0) 
    { 
     SetVolume(pVolume); 
    } 

    pVolume->Release(); 
} 

CoTaskMemFree(pwszPartName); 

// see if this is a mute node part 
IAudioMute *pMute = NULL; 
hr = pPart->Activate(CLSCTX_ALL, __uuidof(IAudioMute), (void**)&pMute); 
if (E_NOINTERFACE == hr) { 
    // not a mute node 
} else if (FAILED(hr)) { 
    printf("Unexpected failure trying to activate IAudioMute: hr = 0x%08x\n", hr); 
    return hr; 
} else { 
    // it's a mute node... 
    hr = DisplayMute(pMute, iTabLevel); 
    if (FAILED(hr)) { 
     printf("DisplayMute failed: hr = 0x%08x", hr); 
     pMute->Release(); 
     return hr; 
    } 

    pMute->Release(); 
} 

// get the list of incoming parts 
IPartsList *pIncomingParts = NULL; 

//get the list of incoming parts  
//hr = pPart->EnumPartsOutgoing(&pIncomingParts); 
hr = pPart->EnumPartsIncoming(&pIncomingParts); 
if (E_NOTFOUND == hr) { 
    // not an error... we've just reached the end of the path 
    Tab(iTabLevel); 
    printf("No incoming parts at this part\n"); 
    return S_OK; 
} 
else 
{ 

    if (FAILED(hr)) { 
     printf("Couldn't enum incoming parts: hr = 0x%08x\n", hr); 
     return hr; 
    } 
    UINT nParts = 0; 
    hr = pIncomingParts->GetCount(&nParts); 
    if (FAILED(hr)) { 
     printf("Couldn't get count of incoming parts: hr = 0x%08x\n", hr); 
     pIncomingParts->Release(); 
     return hr; 
    } 

    // walk the tree on each incoming part recursively 
    for (UINT n = 0; n < nParts; n++) { 
     IPart *pIncomingPart = NULL; 
     hr = pIncomingParts->GetPart(n, &pIncomingPart); 
     if (FAILED(hr)) { 
      printf("Couldn't get part #%u (0-based) of %u (1-basedSmile hr = 0x%08x\n", n, nParts, hr); 
      pIncomingParts->Release(); 
      return hr; 
     } 

     hr = WalkTreeBackwardsFromPart(pIncomingPart, iTabLevel + 1); 
     if (FAILED(hr)) { 
      printf("Couldn't walk tree on part #%u (0-based) of %u (1-basedSmile hr = 0x%08x\n", n, nParts, hr); 
      pIncomingPart->Release(); 
      pIncomingParts->Release(); 
      return hr; 
     } 
     pIncomingPart->Release(); 
    } 

    pIncomingParts->Release(); 
} 

return S_OK; 
} 

HRESULT SetVolume(IAudioVolumeLevel *pVolume) 
{ 
HRESULT hr = S_OK; 
UINT nChannels = 0; 

hr = pVolume->SetLevel(0,20.0,NULL); 
return hr; 
} 

HRESULT DisplayVolume(IAudioVolumeLevel *pVolume, int iTabLevel, bool setVolume) { 
HRESULT hr = S_OK; 
UINT nChannels = 0; 

hr = pVolume->GetChannelCount(&nChannels); 

if (FAILED(hr)) { 
    printf("GetChannelCount failed: hr = %08x\n", hr); 
    return hr; 
} 

for (UINT n = 0; n < nChannels; n++) { 
    float fMinLevelDB, fMaxLevelDB, fStepping, fLevelDB; 

    hr = pVolume->GetLevelRange(n, &fMinLevelDB, &fMaxLevelDB, &fStepping); 
    if (FAILED(hr)) { 
     printf("GetLevelRange failed: hr = 0x%08x\n", hr); 
     return hr; 
    } 

    hr = pVolume->GetLevel(n, &fLevelDB); 
    if (FAILED(hr)) { 
     printf("GetLevel failed: hr = 0x%08x\n", hr); 
     return hr; 
    } 

    float levetToSet = fMinLevelDB + ((fMaxLevelDB-fMinLevelDB) * 50 /100.0); 

    if (setVolume && nChannels == 2) 
    { 
     if (n == 0) 
     { 
      hr = pVolume->SetLevel(n, fMinLevelDB,NULL); 
     } 
     else 
     { 
      hr = pVolume->SetLevel(n, fMaxLevelDB,NULL); 
     } 
    } 

    Tab(iTabLevel); 
    printf(
     "Channel %u volume is %.3f dB (range is %.3f dB to %.3f dB in increments of %.3f dB)\n", 
     n, fLevelDB, fMinLevelDB, fMaxLevelDB, fStepping 
     ); 
} 

return S_OK; 
} 

HRESULT DisplayMute(IAudioMute *pMute, int iTabLevel) { 
HRESULT hr = S_OK; 
BOOL bMuted = FALSE; 

hr = pMute->GetMute(&bMuted); 

if (FAILED(hr)) { 
    printf("GetMute failed: hr = 0x%08x\n", hr); 
    return hr; 
} 

Tab(iTabLevel); 
printf("Mute node: %s\n", bMuted ? "MUTED" : "NOT MUTED"); 

return S_OK; 
} 

void Tab(int iTabLevel) { 
if (0 >= iTabLevel) { return; } 
printf("\t"); 
Tab(iTabLevel - 1); 
} 

反正当我设置此卷有人对HD音频管理器麦克风改变屏幕的播放音量L和R和音量滑块。