在 C# 中使用 'DefaultAudioEndpoint' 以外的音频端点

using an Audio Endpoint other than 'DefaultAudioEndpoint' in C#

This programrgb 键盘的音频可视化工具,可收听 windows' 默认音频设备。我的音频设置有点复杂,我使用的不仅仅是默认音频设备。例如,当我从 Winamp 播放音乐时,它会通过设备 Auxillary 1 (Synchronous Audio Router) 而不是我设置为默认值的 Desktop Input (Synchronous Audio Router)。我希望能够更改程序为可视化监听的设备。

我在声明音频设备的源中找到了; CSCoreAudioInput.cs 中的第 32-36 行:

public void Initialize()
{
    MMDevice captureDevice = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Console);
    WaveFormat deviceFormat = captureDevice.DeviceFormat;
    _audioEndpointVolume = AudioEndpointVolume.FromDevice(captureDevice);
}

我从 documentation 中理解它的方式,MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Console) 部分是 Windows 为应用程序提供我的默认 IMMEndpoint "Desktop Input."

的地方

我将如何改变 DefaultAudioEndpoint

Further Reading 展示了几种获取 IMMDevice 的方法,DefaultAudioEnpoint 就是其中之一。在我看来,我必须枚举设备,然后使用 PKEY_Device_FriendlyName 分离出 Auxillary 1 (Synchronous Audio Router)。这对我来说有点多,因为我几乎没有 C# 经验。有没有更简单的方法来选择不同的端点?我在正确的轨道上吗?还是我完全错过了标记?

还有,MMDeviceIMMDevice有什么区别?源似乎只使用 MMDevice 而所有 Microsoft 文档引用 IMMDevice.

谢谢。

我做到了!

我找到了程序使用 MMDevice 而不是 IMMDevice 的原因。开发人员已选择使用 CSCore 库而不是 Windows 自己的核心音频 API。

从继续阅读 CSCore MMDeviceEnumerator Documentation 看来,我必须制作一个单独的程序来输出所有端点及其各自的端点 ID 字符串。然后我可以用 GetDevice(String id) 方法替换 DefaultAudioEndpoint 方法,其中 String id 是我从单独程序中选择的任何端点的 ID。

为了找到我想要的端点,我写了这个简短的程序来找到我想要的所有信息:

static void Main(string[] args)
    {
        MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
        MMDeviceCollection collection = enumerator.EnumAudioEndpoints(DataFlow.Render,DeviceState.Active);
        Console.WriteLine($"\nNumber of active Devices: {collection.GetCount()}");

        int i = 0;
        foreach (MMDevice device in collection){

            Console.WriteLine($"\n{i} Friendly name: {device.FriendlyName}");
            Console.WriteLine($"Endpoint ID: {device.DeviceID}");
            i++;
        }
        Console.ReadKey();
    }

这告诉我我想要的端点是我列表中的项目编号 3(数组中的 2),而不是使用 GetDevice(String id) 我使用 ItemAt(int deviceIndex).

MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
MMDeviceCollection collection = enumerator.EnumAudioEndpoints(DataFlow.Render,DeviceState.Active);
MMDevice captureDevice = collection.ItemAt(2);

但是在这种情况下,程序没有使用 captureDevice 来引入音频数据。这些是神奇的台词:

_capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i));
_capture.Initialize();

我发现 WasapiLoopbackCapture 使用 Windows' 默认设备除非更改,并且代码使用 DefaultAudioEndpoint 获取默认设备的属性。所以我添加了

_capture.Device = captureDevice;
//before
_capture.Initialize();

现在程序可以正确地从我的非默认音频端点提取音频数据。

本周有人要求我解决类似类型的问题。虽然有一些库可以做到这一点,但我特别要求 "non ish" 程序员做到这一点,所以我在 PowerShell 中开发了它。

Powershell default audio device changer - Github

也许您可以根据需要进行更改。