2010-06-11 23 views
7

Tout d'abord, sachez que je sais qu'il y a déjà quelques questions comme celles-ci; Cependant, ils ne semblent pas résoudre le problème de manière adéquate. J'ai une application C#, avec tous les hooks pInvoke pour parler à l'API waveXXX, et je suis capable de capturer et de lire de l'audio avec ça. Je suis également capable d'ajuster le volume du haut-parleur (WaveOut) avec cette API.
Le problème est que, pour une raison quelconque, cette API ne me permet pas de régler le volume du microphone (WaveIn). Donc, j'ai réussi à trouver un code de mixage que j'ai également tiré et accès via pInvoke et qui me permet d'ajuster le volume du microphone, mais seulement sur mon PC W7. Le code du mélangeur que j'ai commencé avec vient d'ici: http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/05dc2d35-1d45-4837-8e16-562ee919da85 et cela fonctionne, mais est écrit pour régler le volume du haut-parleur. J'ai ajouté la méthode SetMicVolume montré ici ...Comment ajuster le gain du microphone à partir de C# (doit fonctionner sous XP & W7)

public static void SetMicVolume(int mxid, int percentage) 
    { 
     bool rc; 
     int mixer, vVolume; 
     MIXERCONTROL volCtrl = new MIXERCONTROL(); 
     int currentVol; 
     mixerOpen(out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN); 
     int type = MIXERCONTROL_CONTROLTYPE_VOLUME; 
     rc = GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, type, out volCtrl, out currentVol); 
     if (rc == false) 
     { 
      mixerClose(mixer); 
      mixerOpen(out mixer, 0, 0, 0, 0); 
      rc = GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, type, out volCtrl, out currentVol); 
      if (rc == false)  
       throw new Exception("SetMicVolume/GetVolumeControl() failed"); 
     } 
     vVolume = ((int)((float)(volCtrl.lMaximum - volCtrl.lMinimum)/100.0F) * percentage); 
     rc = SetVolumeControl(mixer, volCtrl, vVolume); 
     if (rc == false) 
      throw new Exception("SetMicVolume/SetVolumeControl() failed"); 
     mixerClose(mixer); 
    } 

Notez la "deuxième tentative" d'appeler GetVolumeControl(). Cela est fait parce que sur XP, dans le premier appel à GetVolumeControl (se référer au site ci-dessus pour ce code), l'appel à mixerGetLineControlsA() échoue avec les systèmes XP retournant MIXERR_INVALCONTROL. Ensuite, avec cette deuxième tentative en utilisant mixerOpen (out mixer, 0, 0, 0, 0), le code ne retourne pas un échec mais le gain du micro n'est pas affecté. Notez, comme je l'ai dit plus haut, cela fonctionne sur W7 (la seconde tentative n'est jamais exécutée car elle n'échoue pas en utilisant mixerOpen (out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN)). Je reconnais ne pas avoir une bonne compréhension de l'API de mixage, donc c'est ce que je suis en train de regarder maintenant; Cependant, si quelqu'un a une idée pourquoi cela fonctionnerait sur W7, mais pas XP, je voudrais bien l'entendre. Pendant ce temps, si je le découvre avant que j'obtienne une réponse, je posterai ma propre réponse ...

Répondre

1

Le code suivant semble fonctionner ok pour moi maintenant (mis à jour 6/29/2010). Notez que mes cas de test sont mes deux PC, l'un étant W7 l'autre étant XP, donc ce n'est pas concluant. J'ai vérifié que cela ne fonctionne pas pour toutes les machines, mais pour celles sur lesquelles elles fonctionnent, ça semble aller.

public static bool setMicVolume(int mxid, int percentage) 
    { 
     if (mixerdisabled) 
      return(false); 

     bool rc; 
     int mixer, vVolume, ctrltype, comptype; 
     MIXERCONTROL volCtrl = new MIXERCONTROL(); 
     int currentVol; 
     int mr = mixerOpen(out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN); 
     if (mr != MMSYSERR_NOERROR) 
     { 
      Warning("mixerOpen() failed: " + mr.ToString()); 
      mixerdisabled = true; 
      return(false); 
     } 
     ctrltype = MIXERCONTROL_CONTROLTYPE_VOLUME; 
     comptype = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; 
     rc = GetVolumeControl(mixer, comptype, ctrltype, out volCtrl, out currentVol); 
     if (rc == false) 
     { 
      Warning("SetMicVolume/GetVolumeControl() failed"); 
      mixerdisabled = true; 
      mixerClose(mixer); 
      return(false); 
     } 
     vVolume = ((int)((float)(volCtrl.lMaximum - volCtrl.lMinimum)/100.0F) * percentage); 
     rc = SetVolumeControl(mixer, volCtrl, vVolume); 
     if (rc == false) 
     { 
      Warning("SetMicVolume/SetVolumeControl() failed"); 
      mixerdisabled = true; 
      mixerClose(mixer); 
      return (false); 
     } 
     mixerClose(mixer); 
     return (true); 
    } 

Notez que la principale différence est que j'utilise un type de composant « MIXERLINE_COMPONENTTYPE_DST_WAVEIN » au lieu de « MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ». Je ne comprends pas vraiment cela, donc si quelqu'un veut intervenir avec une explication (ou pour me dire que cela ne va pas fonctionner de manière générique), je me réjouis des réponses!

+0

Notez que j'ai déjà eu une machine XP qui a échoué, donc ce n'est toujours pas parfait ... –

+0

Qu'est-ce que int mxid dans votre code? Comment en obtenir un? –

1

J'ai essayé de faire exactement cela il y a quelque temps quand j'écrivais .NET Voice Recorder en utilisant NAudio, et je l'ai trouvé extrêmement difficile. Vous devez probablement écrire deux lots de code, un pour XP et un pour Vista/Win 7. J'utilise NAudio pour l'interopérateur de mixage.

C'est ce que j'ai fini avec (ne fonctionne toujours pas partout)

private void TryGetVolumeControl() 
    { 
     int waveInDeviceNumber = waveIn.DeviceNumber; 
     if (Environment.OSVersion.Version.Major >= 6) // Vista and over 
     { 
      var mixerLine = new MixerLine((IntPtr)waveInDeviceNumber, 0, MixerFlags.WaveIn); 
      foreach (var control in mixerLine.Controls) 
      { 
       if (control.ControlType == MixerControlType.Volume) 
       { 
        volumeControl = control as UnsignedMixerControl; 
        MicrophoneLevel = desiredVolume; 
        break; 
       } 
      } 
     } 
     else 
     { 
      var mixer = new Mixer(waveInDeviceNumber); 
      foreach (var destination in mixer.Destinations) 
      { 
       if (destination.ComponentType == MixerLineComponentType.DestinationWaveIn) 
       { 
        foreach (var source in destination.Sources) 
        { 
         if (source.ComponentType == MixerLineComponentType.SourceMicrophone) 
         { 
          foreach (var control in source.Controls) 
          { 
           if (control.ControlType == MixerControlType.Volume) 
           { 
            volumeControl = control as UnsignedMixerControl; 
            MicrophoneLevel = desiredVolume; 
            break; 
           } 
          } 
         } 
        } 
       } 
      } 
     } 

    } 
+0

Mark, merci pour la réponse rapide. N'avait pas entendu parler de NAudio avant cela (qui me surprend un peu parce que les derniers mois, j'ai fait beaucoup de 'googling' pour divers problèmes audio sur le pc). Il semble assez mature. Je vais jeter un coup d'oeil à ça; cependant, je voudrais bien trouver une solution en utilisant simplement l'API de base de la console de mixage, afin d'éviter de tirer un gros paquet juste pour faire mic-volume-control. –

+0

Mark, j'ai parcouru le paquet NAudio (l'air vraiment propre); mais je ne vois aucun appel à mixerOpen(). Si cette observation est correcte, comment NAudio utilise-t-elle le mélangeur? –

+0

vous n'avez pas besoin d'ouvrir le mélangeur pour changer les contrôles –