2010-06-11 13 views
7

En primer lugar, tenga en cuenta que sé que hay algunas preguntas como esta ya publicadas; sin embargo, ellos no parecen abordar el problema adecuadamente. Tengo una aplicación C#, con todos los ganchos pInvoke para hablar con la API waveXXX, y puedo capturar y reproducir audio con eso. También puedo ajustar el volumen de los altavoces (WaveOut) con esa API.
El problema es que, por cualquier razón, esa API no me permite ajustar el volumen del micrófono (WaveIn). Entonces, logré encontrar un código de mezclador que también obtuve y el acceso a a través de pInvoke, y eso me permite ajustar el volumen del micrófono, pero solo en mi W7 PC. El código del mezclador que comencé proviene de aquí: http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/05dc2d35-1d45-4837-8e16-562ee919da85 y funciona, pero está escrito para ajustar el volumen del altavoz. He añadido el método SetMicVolume se muestra aquí ...Cómo ajustar la ganancia del micrófono desde C# (necesita trabajar en XP y 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); 
    } 

Nota del "segundo intento" para llamar GetVolumeControl(). Esto se hace porque en XP, en la primera llamada a GetVolumeControl (consulte el sitio anterior para ese código), la llamada a mixerGetLineControlsA() falla con los sistemas XP que devuelven MIXERR_INVALCONTROL. Luego, con este segundo intento utilizando mixer Open (mezclador de salida, 0, 0, 0, 0), el código no devuelve un error, pero la ganancia del micrófono no se ve afectada. Tenga en cuenta que, como dije antes, esto funciona en W7 (el segundo intento nunca se ejecuta porque no falla utilizando mixerOpen (out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN)).

Admito que no tengo una buena comprensión de la API de mezclador, así que eso es lo que estoy buscando ahora; sin embargo, si alguien tiene una pista de por qué esto funcionaría en W7, pero no en XP, me gustaría escucharlo. Mientras tanto, si lo resuelvo antes de obtener una respuesta, publicaré mi propia respuesta ...

Respuesta

1

El siguiente código parece funcionar bien para mí ahora (actualizan 6/29/2010). Tenga en cuenta que mis casos de prueba son mis dos PC, una es W7 y la otra es XP, por lo que no es concluyente. He verificado que esto no funciona para todas las máquinas, pero para aquellas en las que funcionan, parece estar bien.

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); 
    } 

en cuenta que la principal diferencia es que estoy usando un tipo de componente de 'MIXERLINE_COMPONENTTYPE_DST_WAVEIN' en lugar de 'MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE'. Realmente no entiendo esto, así que si alguien quiere dar una explicación (o decirme que esto no va a funcionar genéricamente), ¡estoy dando la bienvenida a las respuestas!

+0

Tenga en cuenta que ya he tenido una máquina XP que falló, por lo que aún no es perfecta ... –

+0

¿Qué es int mxid en su código? ¿Cómo conseguir uno? –

1

Intenté hacer exactamente esto hace un tiempo cuando estaba escribiendo .NET Voice Recorder usando NAudio, y me pareció extremadamente difícil. Probablemente tenga que terminar escribiendo dos lotes de código, uno para XP y uno para Vista/Win 7. Estoy usando NAudio para la interoperabilidad del mezclador.

Esto es lo que terminó con (todavía no funciona en todas partes)

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

Marca, gracias por la respuesta rápida. No había oído hablar de NAudio antes de esto (lo que me sorprende un poco porque en los últimos meses he estado haciendo muchas 'búsquedas' de varios problemas de audio en la PC). Parece bastante maduro. Echaré un vistazo a eso; Sin embargo, me gustaría encontrar una solución simplemente usando la API básica del mezclador solo para poder evitar un gran paquete solo para hacer un control de volumen de micrófono. –

+0

Mark, he estado navegando por el paquete NAudio (se ve realmente limpio); pero no veo ninguna llamada a mixerOpen(). Si esa observación es correcta, ¿cómo usa NAudio el mezclador? –

+0

no necesita abrir el mezclador para cambiar los controles en él –

Cuestiones relacionadas