Winapi 获取waveIn设备的全名
我一直在使用获取waveIn设备的名称,但该结构仅支持31个字符加上一个null,这意味着在我的计算机上,我获取的设备名称被截断:Winapi 获取waveIn设备的全名,winapi,audio,Winapi,Audio,我一直在使用获取waveIn设备的名称,但该结构仅支持31个字符加上一个null,这意味着在我的计算机上,我获取的设备名称被截断: Microphone / Line In (SigmaTel Microphone Array (SigmaTel High, 我确信一定有办法获得设备的完整名称,但有人知道这是什么吗?是的,有一个解决办法。我已经在运输代码中多次解决了这个问题 使用DirectSoundCapture枚举音频捕获设备。API是DirectSoundCaptureEnumera
Microphone / Line In (SigmaTel
Microphone Array (SigmaTel High,
我确信一定有办法获得设备的完整名称,但有人知道这是什么吗?是的,有一个解决办法。我已经在运输代码中多次解决了这个问题 使用DirectSoundCapture枚举音频捕获设备。API是DirectSoundCaptureEnumerate。它将返回设备的完整名称 当然,您可能会想“那太好了,但是我的其余代码都设置为使用Wave API,而不是DirectSound。我不想将其全部切换。那么如何将DirectSoundCaptureEnumerate返回的GUID ID映射到WaveIn API使用的整数ID?” 解决方案是为DirectSoundPrivate对象共同创建实例(或直接从dsound.dll调用GetClassObject),以获取指向IKsPropertySet接口的指针。从这个接口,您可以获得DSound GUID到Wave ID的映射。有关详细信息,请参阅此网页:
您想使用上述网页上所述的DSPROPERTY\u DIRECTSOUNDDEVICE\u WAVEDEVICEMAPPING。DirectSoundPrivate似乎有一些问题。我试图从一个空项目中访问它,它工作正常。但是,当我尝试从COM DLL或DLL线程访问它时,它会从
IKsPropertySet::Get
返回E\u NOTIMPL
错误
但我想出了另一个窍门。DirectSound似乎按波id顺序枚举捕获和渲染设备(不包括第一个默认值)
我们仍然需要与旧的WaveAPI交互,而且它仍然缺乏一种正确的方式来实现这一点。DirectShow提供基于WaveIn的音频输入设备,我需要获得相应的WASAPI id,反之亦然。有一种涉及注册表的方法比使用DirectSound更简单。如果使用WAVEINCAPS2结构,则其名称GUID引用HKLM\System\CurrentControlSet\Control\MediaCategories下的键。如果密钥不存在,则只需在结构中使用名称。这在上有记录。下面是一个例子:
public static ICollection<AudioInputDevice> GetDevices()
{
RegistryKey namesKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\MediaCategories");
List<AudioInputDevice> devices = new List<AudioInputDevice>();
for(int i=0, deviceCount=waveInGetNumDevs(); i<deviceCount; i++)
{
WAVEINCAPS2 caps;
if(waveInGetDevCaps(new IntPtr(i), out caps, Marshal.SizeOf(typeof(WAVEINCAPS2))) == 0 && caps.Formats != 0)
{
string name = null;
if(namesKey != null)
{
RegistryKey nameKey = namesKey.OpenSubKey(caps.NameGuid.ToString("B"));
if(nameKey != null) name = nameKey.GetValue("Name") as string;
}
devices.Add(new AudioInputDevice(name ?? caps.Name, caps.ProductGuid));
}
}
return devices;
}
struct WAVEINCAPS2
{
public short ManufacturerId, ProductId;
public uint DriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string Name;
public uint Formats;
public short Channels;
ushort Reserved;
public Guid ManufacturerGuid, ProductGuid, NameGuid;
}
[DllImport("winmm.dll")]
static extern int waveInGetDevCaps(IntPtr deviceId, out WAVEINCAPS2 caps, int capsSize);
[DllImport("winmm.dll", ExactSpelling=true)]
static extern int waveInGetNumDevs();
publicstaticicollection-GetDevices()
{
RegistryKey namesKey=Registry.LocalMachine.OpenSubKey(@“System\CurrentControlSet\Control\MediaCategories”);
列表设备=新列表();
对于(int i=0,deviceCount=waveInGetNumDevs();i我完成了waveIn设备的名称,探索了从MMDeviceEnumerator返回的名称。对于每个waveIn设备,当名称未完成是其中一个EnumerateAudioEndpoint的全名的一部分时,我将此全名按waveIn设备的相同顺序用于填充组合框
VisualBasic.NET:
Dim wain = New WaveIn()
Dim DeviceInfoI As WaveInCapabilities
Dim nomedevice As String
For de = 0 To wain.DeviceCount - 1
DeviceInfoI = wain.GetCapabilities(de)
nomedevice = DeviceInfoI.ProductName
For deg = 0 To devices.Count - 1
If InStr(devices.Item(deg).FriendlyName, nomedevice) Then
nomedevice = devices.Item(deg).FriendlyName
Exit For
End If
Next
cmbMessaggiVocaliMIC.Items.Add(nomedevice)
Next
cmbMessaggiVocaliMIC.SelectedIndex = 0
waveIn.DeviceNumber = cmbMessaggiVocaliMIC.SelectedIndex
基于@Andrea Bertucelli answer的改进/完整C#WPF代码
using NAudio.CoreAudioApi;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Windows;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
foreach (KeyValuePair<string, MMDevice> device in GetInputAudioDevices())
{
Console.WriteLine("Name: {0}, State: {1}", device.Key, device.Value.State);
}
}
public Dictionary<string, MMDevice> GetInputAudioDevices()
{
Dictionary<string, MMDevice> retVal = new Dictionary<string, MMDevice>();
MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
int waveInDevices = WaveIn.DeviceCount;
for (int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
{
WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
foreach (MMDevice device in enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All))
{
if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
{
retVal.Add(device.FriendlyName, device);
break;
}
}
}
return retVal;
}
}
}
使用NAudio.CoreAudioApi;
使用NAudio.波;
使用制度;
使用System.Collections.Generic;
使用System.Windows;
命名空间WpfApp2
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
foreach(GetInputAudioDevices()中的KeyValuePair设备)
{
WriteLine(“名称:{0},状态:{1}”,device.Key,device.Value.State);
}
}
公共字典GetInputAudioDevices()
{
Dictionary retVal=新字典();
MMDeviceEnumerator枚举器=新的MMDeviceEnumerator();
int waveInDevices=WaveIn.DeviceCount;
对于(int-waveInDevice=0;waveInDevice
我找到了另一种使用注册表查找音频设备全名的方法,包括输入和输出
适用于Windows 7和Windows 10
这个方法首先尝试了Adam M.的方法。他的方法对我不起作用,但为了以防万一,我添加了作为首选方法
procedure TForm_Config.FormCreate(Sender: TObject);
type
tagWAVEOUTCAPS2A = packed record
wMid: WORD;
wPid: WORD;
vDriverVersion: MMVERSION;
szPname: array[0..MAXPNAMELEN-1] of AnsiChar;
dwFormats: DWORD;
wChannels: WORD;
wReserved1: WORD;
dwSupport: DWORD;
ManufacturerGuid: System.TGUID;
ProductGuid: System.TGUID;
NameGuid: System.TGUID;
end;
var
i,outdevs: Integer;
woCaps: tagWAVEOUTCAPS2A;
RegistryService: TRegistry;
iClasses, iSubClasses, iNames: Integer;
audioDeviceClasses, audioDeviceSubClasses, audioDeviceNames: TStringList;
initialDeviceName, partialDeviceName, fullDeviceName: string;
begin
audioDeviceClasses := TStringList.Create;
audioDeviceSubClasses := TStringList.Create;
audioDeviceNames := TStringList.Create;
try
RegistryService := TRegistry.Create;
try
RegistryService.RootKey := HKEY_LOCAL_MACHINE;
if RegistryService.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\HDAUDIO\') then begin
RegistryService.GetKeyNames(audioDeviceClasses);
RegistryService.CloseKey();
for iClasses := 0 to audioDeviceClasses.Count - 1 do begin
if RegistryService.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\HDAUDIO\'+audioDeviceClasses[iClasses]) then begin
RegistryService.GetKeyNames(audioDeviceSubClasses);
RegistryService.CloseKey();
for iSubClasses := 0 to audioDeviceSubClasses.Count - 1 do begin
if RegistryService.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\HDAUDIO\'+audioDeviceClasses[iClasses]+'\'+audioDeviceSubClasses[iSubClasses]) then begin
if RegistryService.ValueExists('DeviceDesc') then begin
fullDeviceName := Trim(RegistryService.ReadString('DeviceDesc'));
if AnsiPos(';',fullDeviceName) > 0 then begin
fullDeviceName := Trim(AnsiMidStr(fullDeviceName, AnsiPos(';',fullDeviceName)+1, Length(fullDeviceName)));
end;
audioDeviceNames.Add(fullDeviceName);
end;
RegistryService.CloseKey();
end;
end;
end;
end;
end;
finally
FreeAndNil(RegistryService);
end;
// WaveOutDevComboBox is a selection box (combo) placed in the form and will receive the list of output audio devices
WaveOutDevComboBox.Clear;
try
outdevs := waveOutGetNumDevs;
for i := 0 to outdevs - 1 do begin
ZeroMemory(@woCaps, sizeof(woCaps));
if waveOutGetDevCaps(i, @woCaps, sizeof(woCaps)) = MMSYSERR_NOERROR then begin
RegistryService := TRegistry.Create;
try
RegistryService.RootKey := HKEY_LOCAL_MACHINE;
if RegistryService.OpenKeyReadOnly('\System\CurrentControlSet\Control\MediaCategories\' + GUIDToString(woCaps.NameGuid)) then begin
WaveOutDevComboBox.Items.Add(RegistryService.ReadString('Name'));
RegistryService.CloseKey();
end
else begin
initialDeviceName := '';
partialDeviceName := Trim(woCaps.szPname);
if AnsiPos('(',partialDeviceName) > 0 then begin
initialDeviceName := Trim(AnsiLeftStr(partialDeviceName,AnsiPos('(',partialDeviceName)-1));
partialDeviceName := Trim(AnsiMidStr(partialDeviceName,AnsiPos('(',partialDeviceName)+1,Length(partialDeviceName)));
if AnsiPos(')',partialDeviceName) > 0 then begin
partialDeviceName := Trim(AnsiLeftStr(partialDeviceName,AnsiPos(')',partialDeviceName)-1));
end;
end;
for iNames := 0 to audioDeviceNames.Count - 1 do begin
fullDeviceName := audioDeviceNames[iNames];
if AnsiStartsText(partialDeviceName,fullDeviceName) then begin
break;
end
else begin
fullDeviceName := partialDeviceName;
end;
end;
WaveOutDevComboBox.Items.Add(initialDeviceName + IfThen(initialDeviceName<>EmptyStr,' (','') + fullDeviceName + IfThen(initialDeviceName<>EmptyStr,')',''));
end;
finally
FreeAndNil(RegistryService);
end;
end;
end;
except
WaveOutDevComboBox.Enabled := False;
end;
finally
FreeAndNil(audioDeviceClasses);
FreeAndNil(audioDeviceSubClasses);
FreeAndNil(audioDeviceNames);
end;
end;
过程TForm_Config.FormCreate(发送方:TObject);
类型
tagWAVEOUTCAPS2A=打包记录
wMid:WORD;
wPid:WORD;
VDR版本:MMV版本;
szPname:AnsiChar的数组[0..MAXPNAMELEN-1];
DWORD格式:DWORD;
频道:单词;
Wreserved 1:单词;
德沃德支持:德沃德;
ManufacturerGuid:System.TGUID;
ProductGuid:System.TGUID;
NameGuid:System.TGUID;
结束;
变量
i、 outdevs:整数;
woCaps:tagWAVEOUTCAPS2A;
注册服务:TRegistry;
iClass、iSubClass、iNames:整数;
音频设备类、音频设备子类、音频设备名称:TStringList;
initialDeviceName、partialDeviceName、fullDeviceName:string;
开始
audioDeviceClasses:=TStringList.Create;
audioDeviceSubClasses:=TStringList.Create;
audioDeviceNames:=TStringList.Create;
尝试
RegistryService:=TRegistry.Create;
尝试
RegistryService.RootKey:=HKEY\U LOCAL\U MACHINE;
如果RegistryService.OpenKeyReadOnly(“\SYSTEM\CurrentControlSet\Enum\HDAUDIO\”),则开始
RegistryService.GetKeyNames(AudioDeviceClass);
RegistryService.CloseKey();
对于iClass:=0到AudioDeviceClass。计数-1开始
如果RegistryService.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\HDAUDIO\'+AudioDeviceClass[iClasses]),则开始
GetKeyNames(AudioDeviceSubclass);
RegistryService.CloseKey();
对于iSubclass:=0到AudioDeviceSubclass
using NAudio.CoreAudioApi;
using NAudio.Wave;
//create enumerator
var enumerator = new MMDeviceEnumerator();
//cycle through all audio devices
for (int i = 0; i < WaveIn.DeviceCount; i++)
Console.WriteLine(enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active)[i]);
//clean up
enumerator.Dispose();
//create enumerator
var enumerator = new MMDeviceEnumerator();
//cyckle trough all audio devices
for (int i = 0; i < WaveOut.DeviceCount; i++)
Console.WriteLine(enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active)[i]);
//clean up
enumerator.Dispose();