在 DirectX 项目中正确设置 MMDevice
Correctly setting up MMDevice in a DirectX project
我目前正在尝试拼凑一个基于着色器的音乐可视化工具。计划是从当前的 MMDevice
中读取数据,我正在尝试按照文档进行操作,但我一定是做错了什么,因为我不得不跳过各种障碍才能获得 MMDeviceEnumerator
编译。
为了定义 MMDeviceEnumerator
和 IMMDeviceEnumerator
的 uuid
,我必须设置 #define WINAPI_FAMILY WINAPI_FAMILY_GAMES
。这也是定义 EDataFlow
和 ERole
枚举所必需的。 我的第一个问题是我是否在某处遗漏了某些配置,或者这是否是启用这些功能的预期方法。
目前,我在 AudioStream
class 中有以下代码:
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 无法访问所有相同的 APIs 并且 IMMDevice 不是 UWP API 表面区域的一部分。
您定义 WINAPI_FAMILY_GAMES
的事实意味着您破解了 API 系列分区宏,它将 定义 UWP 上下文中的 API ,但这并不意味着 API 实际上 从所有 UWP 运行 中的 AppContainer 进程中工作 。
你真的有两个选择:
(1) 如果您想要 编写 UWP,那么您将需要通过适当的 Windows 运行时 API 枚举音频设备,这在 Windows::Devices::Enumeration
命名空间中。
假设您使用的是 C++/CX language extensions (instead of the more modern 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.
您应该花时间阅读有关 UWP 的 Microsoft Docs,以便您更好地了解支持和不支持的内容。
(2) 如果您想要 编写 Win32 桌面应用程序,请改用 directx-vs-templates,其中包括用于 Win32 桌面应用程序的 DirectX 12 起始模板(加上替代的 DirectX UWP 模板,如果你喜欢的话)。
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.
我目前正在尝试拼凑一个基于着色器的音乐可视化工具。计划是从当前的 MMDevice
中读取数据,我正在尝试按照文档进行操作,但我一定是做错了什么,因为我不得不跳过各种障碍才能获得 MMDeviceEnumerator
编译。
为了定义 MMDeviceEnumerator
和 IMMDeviceEnumerator
的 uuid
,我必须设置 #define WINAPI_FAMILY WINAPI_FAMILY_GAMES
。这也是定义 EDataFlow
和 ERole
枚举所必需的。 我的第一个问题是我是否在某处遗漏了某些配置,或者这是否是启用这些功能的预期方法。
目前,我在 AudioStream
class 中有以下代码:
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 无法访问所有相同的 APIs 并且 IMMDevice 不是 UWP API 表面区域的一部分。
您定义 WINAPI_FAMILY_GAMES
的事实意味着您破解了 API 系列分区宏,它将 定义 UWP 上下文中的 API ,但这并不意味着 API 实际上 从所有 UWP 运行 中的 AppContainer 进程中工作 。
你真的有两个选择:
(1) 如果您想要 编写 UWP,那么您将需要通过适当的 Windows 运行时 API 枚举音频设备,这在 Windows::Devices::Enumeration
命名空间中。
假设您使用的是 C++/CX language extensions (instead of the more modern 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.
您应该花时间阅读有关 UWP 的 Microsoft Docs,以便您更好地了解支持和不支持的内容。
(2) 如果您想要 编写 Win32 桌面应用程序,请改用 directx-vs-templates,其中包括用于 Win32 桌面应用程序的 DirectX 12 起始模板(加上替代的 DirectX UWP 模板,如果你喜欢的话)。
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.