Skip to content

Commit 2915bf5

Browse files
committed
声卡选择
1 parent 3c6d5ef commit 2915bf5

File tree

7 files changed

+659
-0
lines changed

7 files changed

+659
-0
lines changed

XCoder/Properties/Resources.Designer.cs

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

XCoder/Properties/Resources.resx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,8 @@
117117
<resheader name="writer">
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120+
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
121+
<data name="playTest" type="System.Resources.ResXFileRef, System.Windows.Forms">
122+
<value>..\Windows\playTest.wav;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
123+
</data>
120124
</root>

XCoder/Windows/AudioHelper.cs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+

2+
using Microsoft.Win32;
3+
using NAudio.CoreAudioApi;
4+
using NewLife;
5+
using NewLife.Collections;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.ComponentModel;
9+
using System.Configuration;
10+
using System.Linq;
11+
using System.Runtime.CompilerServices;
12+
using System.Text;
13+
using System.Threading.Tasks;
14+
15+
namespace XCoder
16+
{
17+
public class AudioDevice
18+
{
19+
/// <summary>设备名称</summary>
20+
public string Name { get; set; }
21+
22+
/// <summary>ContainerID</summary>
23+
public string ContainerId { get; set; }
24+
25+
/// <summary>播放设备</summary>
26+
public MMDevice PlaybackDevice;
27+
28+
/// <summary>录音设备</summary>
29+
public MMDevice RecordingDevice;
30+
31+
public override string ToString()
32+
{
33+
var sb = Pool.StringBuilder.Get();
34+
35+
sb.AppendLine($"设备:{Name}");
36+
sb.AppendLine($"ContainerID:{ContainerId}");
37+
38+
sb.Append("播放:");
39+
if (PlaybackDevice != null)
40+
{
41+
sb.Append($" 声道:{PlaybackDevice.AudioClient.MixFormat.Channels}");
42+
sb.Append($" 采样率:{PlaybackDevice.AudioClient.MixFormat.SampleRate}");
43+
}
44+
else
45+
{
46+
sb.Append("无");
47+
}
48+
sb.AppendLine();
49+
50+
sb.Append("录音:");
51+
if (RecordingDevice != null)
52+
{
53+
sb.Append($" 声道:{RecordingDevice.AudioClient.MixFormat.Channels}");
54+
sb.Append($" 采样率:{RecordingDevice.AudioClient.MixFormat.SampleRate}");
55+
}
56+
else
57+
{
58+
sb.Append("无");
59+
}
60+
sb.AppendLine();
61+
62+
return sb.Return(true);
63+
}
64+
65+
/// <summary>字符串截取括号内内容</summary>
66+
/// <remarks>FriendlyName 中截取括号内声卡名称</remarks>
67+
/// <param name="str"></param>
68+
/// <returns></returns>
69+
private string getCardName(string str)
70+
{
71+
if (str == null) return null;
72+
73+
int start = str.IndexOf('(') + 1;
74+
int end = str.IndexOf(')', start);
75+
if (start > 0 && end > start)
76+
{
77+
return str.Substring(start, end - start);
78+
}
79+
80+
return null;
81+
}
82+
83+
/// <summary>获取声卡名称</summary>
84+
/// <returns></returns>
85+
public string GetCardName()
86+
{
87+
if (PlaybackDevice != null)
88+
{
89+
return PlaybackDevice.DeviceFriendlyName;
90+
//return getCardName(PlaybackDevice.DeviceFriendlyName);
91+
}
92+
if (RecordingDevice != null)
93+
{
94+
return RecordingDevice.DeviceFriendlyName;
95+
//return getCardName(RecordingDevice.DeviceFriendlyName);
96+
}
97+
return null;
98+
}
99+
100+
}
101+
102+
public static class AudioHelper
103+
{
104+
/// <summary>从注册表获取音频设备ContainerID</summary>
105+
/// <param name="deviceId"></param>
106+
/// <param name="basepath"></param>
107+
/// <returns></returns>
108+
public static string GetAudioContainerID(string deviceId, string basepath = "SYSTEM\\CurrentControlSet\\Enum\\SWD\\MMDEVAPI\\")
109+
{
110+
string registryPath = basepath + deviceId;
111+
112+
using (RegistryKey deviceKey = Registry.LocalMachine.OpenSubKey(registryPath))
113+
{
114+
if (deviceKey == null) return null;
115+
116+
string containerIdStr = deviceKey.GetValue("ContainerID") as string;
117+
if (!string.IsNullOrEmpty(containerIdStr))
118+
{
119+
return containerIdStr;
120+
// Guid.TryParse(containerIdStr, out Guid containerId);
121+
// return containerId;
122+
}
123+
}
124+
125+
return null;
126+
}
127+
128+
/// <summary>获取所有声卡</summary>
129+
/// <returns></returns>
130+
public static Dictionary<string, AudioDevice> GetAudioDevices()
131+
{
132+
var dic = new Dictionary<string, AudioDevice>();
133+
var enumerator = new MMDeviceEnumerator();
134+
var playbackDevices = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
135+
var recordingDevices = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active);
136+
137+
foreach (var dev in playbackDevices)
138+
{
139+
var containerId = GetAudioContainerID(dev.ID);
140+
if (containerId != null)
141+
{
142+
if (!dic.TryGetValue(containerId, out var audioDevice))
143+
{
144+
audioDevice = new AudioDevice { ContainerId = containerId };
145+
dic[containerId] = audioDevice;
146+
}
147+
audioDevice.PlaybackDevice = dev;
148+
}
149+
}
150+
foreach (var dev in recordingDevices)
151+
{
152+
var containerId = GetAudioContainerID(dev.ID);
153+
if (containerId != null)
154+
{
155+
if (!dic.TryGetValue(containerId, out var audioDevice))
156+
{
157+
audioDevice = new AudioDevice { ContainerId = containerId };
158+
dic[containerId] = audioDevice;
159+
}
160+
audioDevice.RecordingDevice = dev;
161+
}
162+
}
163+
164+
foreach (var item in dic)
165+
{
166+
var dev = item.Value;
167+
// 尝试从ContainerID获取设备名称
168+
dev.Name = dev.ContainerId;
169+
var name = dev.GetCardName();
170+
if (!name.IsNullOrEmpty()) dev.Name = name;
171+
}
172+
173+
return dic;
174+
}
175+
176+
/// <summary>从USB设备获取声卡</summary>
177+
/// <param name="dev"></param>
178+
/// <returns></returns>
179+
public static AudioDevice GetAudioDevice(this UsbDevice dev)
180+
{
181+
var devs = AudioHelper.GetAudioDevices();
182+
if (devs.ContainsKey(dev.ContainerId)) { return devs[dev.ContainerId]; }
183+
184+
return null;
185+
}
186+
}
187+
}

XCoder/Windows/AudioSelect.Designer.cs

Lines changed: 142 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)