C++实现Windows音频输入设备监听功能及输出设备配置求助
实现Windows音频输入设备的监听功能(C++)
核心思路
Windows的“监听此设备”功能,需要通过Core Audio API操作音频端点设备的监听属性,而非ChatGPT提到的不存在的PKEY_AudioEndpoint_Enable_Stereo_Mix。核心是为目标输入设备指定关联的输出设备,并启用监听状态。
实现步骤与代码示例
以下是完整的C++实现代码,包含设备枚举、监听设置的核心逻辑:
#include <windows.h> #include <mmdeviceapi.h> #include <propsys.h> #include <functiondiscoverykeys_devpkey.h> #include <iostream> #pragma comment(lib, "ole32.lib") #pragma comment(lib, "propsys.lib") #pragma comment(lib, "mmdevapi.lib") // 获取指定类型的设备(输入/输出)的ID HRESULT GetDeviceID(EDataFlow deviceFlow, LPCWSTR deviceName, LPWSTR& deviceID) { HRESULT hr = CoInitialize(nullptr); if (FAILED(hr)) return hr; IMMDeviceEnumerator* pEnumerator = nullptr; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); if (FAILED(hr)) { CoUninitialize(); return hr; } IMMDeviceCollection* pCollection = nullptr; hr = pEnumerator->EnumAudioEndpoints(deviceFlow, DEVICE_STATE_ACTIVE, &pCollection); if (FAILED(hr)) { pEnumerator->Release(); CoUninitialize(); return hr; } UINT count = 0; hr = pCollection->GetCount(&count); if (FAILED(hr)) { pCollection->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } for (UINT i = 0; i < count; i++) { IMMDevice* pDevice = nullptr; hr = pCollection->Item(i, &pDevice); if (FAILED(hr)) continue; IPropertyStore* pProps = nullptr; hr = pDevice->OpenPropertyStore(STGM_READ, &pProps); if (FAILED(hr)) { pDevice->Release(); continue; } PROPVARIANT varName; PropVariantInit(&varName); hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName); if (SUCCEEDED(hr) && varName.vt == VT_LPWSTR) { if (_wcsicmp(varName.pwszVal, deviceName) == 0) { hr = pDevice->GetId(&deviceID); PropVariantClear(&varName); pProps->Release(); pDevice->Release(); break; } } PropVariantClear(&varName); pProps->Release(); pDevice->Release(); } pCollection->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } // 设置输入设备的监听功能 HRESULT SetListenInFunction(LPCWSTR inputDeviceID, LPCWSTR outputDeviceID, BOOL enable) { HRESULT hr = CoInitialize(nullptr); if (FAILED(hr)) return hr; IMMDeviceEnumerator* pEnumerator = nullptr; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); if (FAILED(hr)) { CoUninitialize(); return hr; } IMMDevice* pInputDevice = nullptr; hr = pEnumerator->GetDevice(inputDeviceID, &pInputDevice); if (FAILED(hr)) { pEnumerator->Release(); CoUninitialize(); return hr; } IPropertyStore* pProps = nullptr; hr = pInputDevice->OpenPropertyStore(STGM_READWRITE, &pProps); if (FAILED(hr)) { pInputDevice->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } // 设置监听的目标输出设备ID PROPVARIANT varOutputID; PropVariantInit(&varOutputID); varOutputID.vt = VT_LPWSTR; varOutputID.pwszVal = const_cast<LPWSTR>(outputDeviceID); hr = pProps->SetValue(PKEY_AudioEndpoint_ListenToDevice, varOutputID); if (FAILED(hr)) { PropVariantClear(&varOutputID); pProps->Release(); pInputDevice->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } PropVariantClear(&varOutputID); // 启用/禁用监听 PROPVARIANT varEnable; PropVariantInit(&varEnable); varEnable.vt = VT_BOOL; varEnable.boolVal = enable ? VARIANT_TRUE : VARIANT_FALSE; hr = pProps->SetValue(PKEY_AudioEndpoint_EnableListen, varEnable); if (FAILED(hr)) { PropVariantClear(&varEnable); pProps->Release(); pInputDevice->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } PropVariantClear(&varEnable); // 提交属性更改 hr = pProps->Commit(); pProps->Release(); pInputDevice->Release(); pEnumerator->Release(); CoUninitialize(); return hr; } int main() { // 示例:设置名为"麦克风"的输入设备,监听输出到"扬声器" LPWSTR inputDeviceID = nullptr; HRESULT hr = GetDeviceID(eCapture, L"麦克风", inputDeviceID); if (FAILED(hr)) { std::cout << "获取输入设备ID失败" << std::endl; return 1; } LPWSTR outputDeviceID = nullptr; hr = GetDeviceID(eRender, L"扬声器", outputDeviceID); if (FAILED(hr)) { CoTaskMemFree(inputDeviceID); std::cout << "获取输出设备ID失败" << std::endl; return 1; } hr = SetListenInFunction(inputDeviceID, outputDeviceID, TRUE); if (SUCCEEDED(hr)) { std::cout << "监听功能已启用" << std::endl; } else { std::cout << "启用监听失败,错误码:" << hr << std::endl; } CoTaskMemFree(inputDeviceID); CoTaskMemFree(outputDeviceID); return 0; }
关键说明
- 依赖与编译:需要链接
ole32.lib、propsys.lib、mmdevapi.lib,并确保Windows SDK版本支持Core Audio API(Windows 7及以上)。 - 设备名称匹配:代码中通过设备友好名称(如"麦克风"、"扬声器")查找设备,你需要根据实际设备名称修改。
- 权限问题:普通用户权限通常可修改个人音频设备设置,若操作系统级设备可能需要管理员权限。
- 错误处理:代码中保留了HRESULT检查,实际使用时可根据错误码进一步排查问题(如设备不存在、权限不足)。
内容的提问来源于stack exchange,提问作者ZeTr0nIx
相关产品推荐
相关产品推荐

