c++ - 在 DirectX 项目中正确设置 MMDevice

标签 c++ windows directx wasapi

我目前正在尝试拼凑一个基于着色器的音乐可视化工具。计划是从当前的 MMDevice 读取数据,我正在尝试遵循文档,但我一定做错了什么,因为我必须跳过各种障碍才能获得甚至只是要编译的 MMDeviceEnumerator

为了定义 MMDeviceEnumeratorIMMDeviceEnumeratoruuid,我必须设置 #define WINAPI_FAMILY WINAPI_FAMILY_GAMES。这也是定义 EDataFlowERole 枚举所必需的。 我的第一个问题是我是否在某处遗漏了某些配置,或者这是否是启用这些功能的预期方法

目前,我在 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 the IMMDevice interface in it's API surface. See Microsoft Docs.

关于c++ - 在 DirectX 项目中正确设置 MMDevice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69052064/

相关文章:

c++ - IASetIndexBuffer 内存泄漏原因

c++ - 没有默认构造函数的重复元素模板化数组

c++ - 是否有一种有效的标准算法来栅格包括其内部区域的多边形

c++ - 在共享指针的值中调用 std::swap 会调用一堆构造函数和析构函数

Python 屏幕截图 2+ 监视器 (windows)

c# - 直接视频缓冲区访问

c++ - 表达式 : Invalid Operator < - Can't find the error

c++ - BB10 - 启用 Qml 调试。仅在安全环境中使用

windows - 从 .bat 脚本运行 Powershell 命令不起作用,但是当我直接在命令行中键入它时它起作用

java - Windows 将凭据传播到 Java 桌面应用程序