PRB: No Signal is Recorded When Using MCI or waveInxxx APIs

Last reviewed: November 22, 1996
Article ID: Q159753
The information in this article applies to:
  • Microsoft Windows Software Development Kit (SDK) for Windows version 4.0

SYMPTOMS

There is no signal recorded using MCI (Media Control Interface) or waveInXXX APIs to record through the microphone.

CAUSE

There are three possible causes:

  1. The microphone line is muted.

  2. The volume of the microphone line is turned to the minimum.

  3. The microphone line is not selected into the wave input destination.

RESOLUTION

You need to make sure that none of the above conditions exist in your applications. The audio mixer API set provides a means by which each condition can be checked and set accordingly.

MORE INFORMATION

Two input lines are involved when recording from the microphone: the physical source line (microphone) and the logical source line (wave in). This recording architecture can be separated into two distinct components where the signals from the microphone source line feed into the wave in destination line. Multiple controls influence these lines.

The first condition is cleared through a mute control. The second condition through a volume control. To clear the third one, use a LIST control associated with the wave input line. The following Visual C++ sample code consists of three functions for clearing these conditions, respectively. Although this sample is written in Visual C++, you can move the in-line declarations up front and modify the Visual C++ style initialization to make it a C sample:

void UnMute()
{
   // Open the mixer device
   HMIXER hmx;
   mixerOpen(&hmx, 0, 0, 0, 0);

   // Get the line info for the wave in destination line
   MIXERLINE mxl;
  mxl.cbStruct = sizeof(mxl);
  mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
  mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

   // Now find the microphone source line connected to this wave in
   // destination
   DWORD cConnections = mxl.cConnections;
   for(DWORD j=0; j<cConnections; j++){
      mxl.dwSource = j;
      mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_SOURCE);
      if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == mxl.dwComponentType)
         break;
   }
   // Find a mute control, if any, of the microphone line
   LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof MIXERCONTROL);
   MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID,
      MIXERCONTROL_CONTROLTYPE_MUTE, 1, sizeof MIXERCONTROL, pmxctrl};
   if(!mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ONEBYTYPE)){
      // Found, so proceed
      DWORD cChannels = mxl.cChannels;
      if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
         cChannels = 1;

      LPMIXERCONTROLDETAILS_BOOLEAN pbool =
         (LPMIXERCONTROLDETAILS_BOOLEAN) malloc(cChannels * sizeof
MIXERCONTROLDETAILS_BOOLEAN);
      MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl->dwControlID,
cChannels, (HWND)0,
         sizeof MIXERCONTROLDETAILS_BOOLEAN, (LPVOID) pbool};
      mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
      // Unmute the microphone line (for both channels)
      pbool[0].fValue = pbool[cChannels - 1].fValue = 0;
      mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);

    free(pmxctrl);
    free(pbool);
   }
  else
    free(pmxctrl);

   mixerClose(hmx);
}

void SetVolume()
{
   // Open the mixer device
   HMIXER hmx;
   mixerOpen(&hmx, 0, 0, 0, 0);

   // Get the line info for the wave in destination line
   MIXERLINE mxl;
    mxl.cbStruct = sizeof(mxl);
    mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
    mixerGetLineInfo((HMIXEROBJ)hmx, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);

   // Now find the microphone source line connected to this wave in
   // destination
   DWORD cConnections = mxl.cConnections;
   for(DWORD j=0; j<cConnections; j++){
      mxl.dwSource = j;
      mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_SOURCE);
      if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == mxl.dwComponentType)
         break;
   }
   // Find a volume control, if any, of the microphone line
   LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof MIXERCONTROL);
   MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID,
      MIXERCONTROL_CONTROLTYPE_VOLUME, 1, sizeof MIXERCONTROL, pmxctrl};
   if(!mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ONEBYTYPE)){
      // Found!
      DWORD cChannels = mxl.cChannels;
      if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
         cChannels = 1;

      LPMIXERCONTROLDETAILS_UNSIGNED pUnsigned =
(LPMIXERCONTROLDETAILS_UNSIGNED)
         malloc(cChannels * sizeof MIXERCONTROLDETAILS_UNSIGNED);
      MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl->dwControlID,
cChannels, (HWND)0,
         sizeof MIXERCONTROLDETAILS_UNSIGNED, (LPVOID) pUnsigned};
      mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
      // Set the volume to the middle  (for both channels as needed)
      pUnsigned[0].dwValue = pUnsigned[cChannels - 1].dwValue =
         (pmxctrl->Bounds.dwMinimum+pmxctrl->Bounds.dwMaximum)/2;
      mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);

    free(pmxctrl);
    free(pUnsigned);
   }
  else
    free(pmxctrl);
   mixerClose(hmx);
}
void SelectMic()
{
   // Open the mixer device
   HMIXER hmx;
   mixerOpen(&hmx, 0, 0, 0, 0);

   // Get the line info for the wave in destination line
   MIXERLINE mxl;
    mxl.cbStruct      = sizeof(mxl);
    mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
    mixerGetLineInfo((HMIXEROBJ)hmx, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);

   // Find a LIST control, if any, for the wave in line
   LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(mxl.cControls * sizeof
MIXERCONTROL);
   MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID, 0,
      mxl.cControls, sizeof MIXERCONTROL, pmxctrl};
   mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ALL);

   // Now walk through each control to find a type of LIST control. This
   // can be either Mux, Single-select, Mixer or Multiple-select.
   DWORD i;
   for(i=0; i < mxl.cControls; i++)
      if (MIXERCONTROL_CT_CLASS_LIST == (pmxctrl[i].dwControlType
&MIXERCONTROL_CT_CLASS_MASK))
         break;
   if (i < mxl.cControls) { // Found a LIST control
      // Check if the LIST control is a Mux or Single-select type
      BOOL bOneItemOnly = FALSE;
      switch (pmxctrl[i].dwControlType) {
         case MIXERCONTROL_CONTROLTYPE_MUX:
         case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
            bOneItemOnly = TRUE;
      }

      DWORD cChannels = mxl.cChannels, cMultipleItems = 0;
      if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl[i].fdwControl)
         cChannels = 1;
      if (MIXERCONTROL_CONTROLF_MULTIPLE & pmxctrl[i].fdwControl)
         cMultipleItems = pmxctrl[i].cMultipleItems;

      // Get the text description of each item
      LPMIXERCONTROLDETAILS_LISTTEXT plisttext =
(LPMIXERCONTROLDETAILS_LISTTEXT)
         malloc(cChannels * cMultipleItems * sizeof
MIXERCONTROLDETAILS_LISTTEXT);
      MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl[i].dwControlID,
cChannels,
         (HWND)cMultipleItems, sizeof MIXERCONTROLDETAILS_LISTTEXT,
(LPVOID) plisttext};
      mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_LISTTEXT);

      // Now get the value for each item
      LPMIXERCONTROLDETAILS_BOOLEAN plistbool =
(LPMIXERCONTROLDETAILS_BOOLEAN)
         malloc(cChannels * cMultipleItems * sizeof
MIXERCONTROLDETAILS_BOOLEAN);
      mxcd.cbDetails = sizeof MIXERCONTROLDETAILS_BOOLEAN;
      mxcd.paDetails = plistbool;
      mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);

      // Select the "Microphone" item
      for (DWORD j=0; j<cMultipleItems; j = j + cChannels)
         if (0 == strcmp(plisttext[j].szName, "Microphone"))
            // Select it for both left and right channels
            plistbool[j].fValue = plistbool[j+ cChannels - 1].fValue = 1;
         else if (bOneItemOnly)
            // Mux or Single-select allows only one item to be selected
            // so clear other items as necessary
            plistbool[j].fValue = plistbool[j+ cChannels - 1].fValue = 0;
      // Now actually set the new values in
      mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);

    free(pmxctrl);
    free(plisttext);
    free(plistbool);
   }
  else
    free(pmxctrl);
   mixerClose(hmx);
}


KBCategory: kbmm kbprb
KBSubcategory: MMWave MMMixer
Additional reference words: 4.00 kbdsd waveInOpen waveInAddBuffer new type
waveaudio



THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 22, 1996
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.