我目前正在尝试拼凑一个基于着色器的音乐可视化工具。计划是从当前的 MMDevice 读取数据,我正在尝试遵循文档,但我一定做错了什么,因为我必须跳过各种障碍才能获得甚至只是要编译的 MMDeviceEnumerator
。
为了定义 MMDeviceEnumerator
和 IMMDeviceEnumerator
的 uuid
,我必须设置 #define WINAPI_FAMILY WINAPI_FAMILY_GAMES
。这也是定义 EDataFlow
和 ERole
枚举所必需的。 我的第一个问题是我是否在某处遗漏了某些配置,或者这是否是启用这些功能的预期方法。
目前,我在 AudioStream
类中有以下代码:
class AudioStream {
public:
AudioStream() {
//SUCCEEDING(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
SUCCEEDING(CoCreateInstance(
__uuidof(IMMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(MMDeviceEnumerator),
(void**)&this->mmDeviceEnumerator));
SUCCEEDING(this->mmDeviceEnumerator->GetDefaultAudioEndpoint(
eRender,
eConsole,
&this->mmDevice));
}
private:
IAudioClient* audioClient = NULL;
IAudioCaptureClient* captureClient = NULL;
IMMDeviceEnumerator* mmDeviceEnumerator = NULL;
IMMDevice* mmDevice = NULL;
};
如果您熟悉 DirectX 12 项目模板的外观,该对象将在 Sample3DSceneRenderer
构造函数中实例化。 我现在遇到的主要问题是启动期间立即出现以下两个错误:
onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!75AA0DFF: (caller: 75B1CF2C) ReturnHr(1) tid(42a8) 80040154 Class not registered
onecore\com\combase\dcomrem\resolver.cxx(2507)\combase.dll!75B1CF4D: (caller: 75AA29E4) ReturnHr(2) tid(42a8) 80040154 Class not registered
这会导致整个应用程序挂起,并且项目模板可视化永远不会出现(后续宏退出)。有谁知道为什么会失败?它必须与 CoCreateInstance
调用有关:(
最佳答案
您正在编写通用 Windows 平台 (UWP) 应用,因为这是“内置”DirectX 12 应用项目模板在 Visual Studio 中创建的内容。 UWP 无法访问所有相同的 API,并且 IMMDevice 不属于 UWP API 表面积的一部分。
您定义了 WINAPI_FAMILY_GAMES
的事实意味着您破解了 API Family Partition 宏,它将定义 UWP 上下文中的 API,但这并不意味着 API 实际上在所有 UWP 运行的 AppContainer 进程中工作英寸。
你确实有两个选择:
(1) 如果您想要编写 UWP,则需要通过 Windows::Devices::Enumeration
中的正确 Windows 运行时 API 枚举音频设备。命名空间。
假设您正在使用C++/CX language extensions (而不是更现代的 C++/WinRT projections ),那么这段代码就可以工作:
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
while (operation->Status == Windows::Foundation::AsyncStatus::Started)
{
Sleep(100);
}
if (operation->Status != Windows::Foundation::AsyncStatus::Completed)
{
throw std::runtime_error("FindAllAsync");
}
DeviceInformationCollection^ devices = operation->GetResults();
for (unsigned i = 0; i < devices->Size; ++i)
{
using Windows::Devices::Enumeration::DeviceInformation;
DeviceInformation^ d = devices->GetAt(i);
// d->Id->Data();
// d->Name->Data();
}
Also, if you want to get access to the audio capture device from a UWP, you must add a capability to your manifest to request it via
<DeviceCapability Name="microphone"/>
. See Microsoft Docs.
您应该花时间阅读Microsoft Docs以便您更好地了解支持哪些内容和不支持哪些内容。
(2) 如果您想要编写 Win32 桌面应用程序,请使用 directx-vs-templates相反,其中包括适用于 Win32 桌面应用程序的 DirectX 12 启动模板(如果您喜欢的话,还可添加适用于 UWP 的替代 DirectX 模板)。
Whichever appmodel you use, you may want to take a look at DirectX Tool Kit for Audio.
BTW,
WINAPI_FAMILY_GAMES
is used by the Microsoft GDK for Xbox which is for writing titles for Xbox One and Xbox Series X|S. It uses Win32 APIs and doesn't use Windows Runtime APIs, so it has theIMMDevice
interface in it's API surface. See Microsoft Docs.
关于c++ - 在 DirectX 项目中正确设置 MMDevice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69052064/