2009-09-19 19 views
9

Utilizzo il waveInGetDevCaps per ottenere il nome dei dispositivi waveIn, ma la struttura WAVEINCAPS supporta solo 31 caratteri più un valore null, nel senso che sul mio computer i nomi dei dispositivi che ottengo vengono troncati :Ottieni il nome completo di un dispositivo waveIn

Microphone/Line In (SigmaTel 
Microphone Array (SigmaTel High, 

sono sicuro che ci deve essere un modo di ottenere il nome completo del dispositivo, ma qualcuno sa di cosa si tratta?

risposta

7

Sì, c'è una soluzione alternativa. Ho risolto questo problema più volte nel codice di spedizione.

Enumerare i dispositivi di acquisizione audio con DirectSoundCapture. L'API è DirectSoundCaptureEnumerate. Ti restituirà il nome completo dei dispositivi.

Ovviamente, probabilmente stai pensando "È fantastico, ma il resto del mio codice è configurato per utilizzare l'API Wave, non DirectSound. Non voglio spostarlo da capo. ID GUID restituiti da DirectSoundCaptureEnumerate agli ID interi utilizzati dall'API WaveIn? "

La soluzione è CoCreateInstance per l'oggetto DirectSoundPrivate (o chiamare GetClassObject direttamente da dsound.dll) per ottenere un puntatore a un'interfaccia IKsPropertySet. Da questa interfaccia, è possibile ottenere il DSID di GUID per il mapping di Wave ID. Per maggiori dettagli vedi questa pagina web:

http://msdn.microsoft.com/en-us/library/bb206182(VS.85).aspx

Si desidera utilizzare il DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING come descritto sulla pagina web di cui sopra.

+0

grazie, questo è davvero disponibile (anche se la vergogna deve essere così contorto) –

+1

che collegano sembra essere rotto . hai un altro link o almeno il titolo dell'articolo su msdn? –

+2

Un altro metodo per ottenere il GUID è chiamare waveOutGetDevCaps con una struttura WAVEOUTCAPS2 anziché con la normale struttura WAVEOUTCAPS. http://msdn.microsoft.com/en-us/library/windows/hardware/ff536382%28v=vs.85%29.aspx – leiflundgren

2

Sembra che DirectSoundPrivate abbia alcuni problemi. Sto cercando di accedervi da un progetto vuoto e funziona bene. Tuttavia, quando provo ad accedere da COM DLL o da un thread DLL restituisce l'errore E_NOTIMPL da IKsPropertySet::Get.

Ma ho capito un altro trucco. Sembra che DirectSound enumeri i dispositivi di acquisizione e rendering in ordine id wave (escluso il primo valore predefinito).

Dobbiamo ancora interagire con la vecchia API Wave e manca ancora un modo corretto per farlo. DirectShow fornisce dispositivi di input audio basati su WaveIn e ho bisogno di ottenere un ID WASAPI corrispondente e viceversa.

3

C'è un modo per coinvolgere il registro che è più semplice rispetto all'utilizzo di DirectSound. Se si utilizza la struttura WAVEINCAPS2, ha un GUID di nome che fa riferimento a una chiave in HKLM \ System \ CurrentControlSet \ Control \ MediaCategories. Se la chiave non esiste, basta usare il nome nella struttura. Questo è documentato su http://msdn.microsoft.com/en-us/library/windows/hardware/ff536382%28v=vs.85%29.aspx. Ecco un esempio:

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(); 
+3

grazie per attirare questo alla mia attenzione. Sembra promettente, ma purtroppo i miei test (su Win 7) hanno dimostrato che sebbene la struttura WAVEINCAPS2 presenti Guids, essi non sono contenuti nel registro. Sembra che i produttori di dispositivi audio driver non si preoccupino semplicemente di modificare questi valori: http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.mmedia/2006-08/msg00102.html –

+0

Not tutti i GUID saranno presenti nel registro, nel qual caso si suppone di utilizzare il nome all'interno della struttura. (Solitamente il registro viene usato solo se il nome è più lungo dei 31 caratteri disponibili nella struttura.) Se il nome è troncato a 31 caratteri ma la chiave non è nel registro, allora forse i produttori erano pigri. :-( –

3

Ho completato i nomi dei dispositivi waveIn, esplorando i nomi restituiti da MMDeviceEnumerator. Per ogni dispositivo waveIn, quando il nome incompleto fa parte del nome completo di uno di EnumerateAudioEndPoints, ho utilizzato questo nome completo per popolato combobox nello stesso ordine dei dispositivi 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 
2

Migliorata/completo di codice C# WPF in base a @Andrea Bertucelli risposta

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; 
     } 
    } 
} 
Problemi correlati