Automatic selection of sound card input terminal in DirectShow

Source: Internet
Author: User

In some applications that use sound cards for audio collection, there are usually the following functional requirements: when the program starts, it is required that a specific input terminal be automatically selected for the sound card-for example, some common collection programs want to use "line in" as the default input, and some video conferencing software, you want to use "Microphone" as the default input. Unfortunately, DirectShow does not directly support this function.

As you know, sound cards appear in DirectShow in the form of filters, which are generally called audio capture filter. Each input pin of the filter represents an input terminal of the sound card. The Pin name is the name of the Input Terminal. For different sound cards, the number and type of input terminals may be different. Take avance ac97 audio and soundmax digital audio sound cards as examples. Their input pin values are respectively (Note: they are listed by "index: PIN name ):

0: Mono Mix 1: Stereo mix 2: aux 3: TV tuner Audio 4: CD PLAYER 5: Line in 6: microphone 7: Phone Line
0: cd player 1: Micro-Phone 2: Line-In 3: Mono out 4: wave out mix

In DirectShow, you can use indexes to enumerate all input pins of the audio capture filter. However, the index alone cannot identify the specific input terminal types represented by the pin, in addition, the indexes of different sound cards do not have universal significance. For an unknown sound card, how does an application select a specific type of input terminal in a unified way? There is a stupid way, that is, to guess-as much as possible to guess the name of the input pin! Take "line in" as the default input as an example:

// DEMO code 1
// We set "line in" as default, by checking the pin name
If (pinname. comparenocase ("line in") = 0 |
Pinname. comparenocase ("line-in") = 0 |
Pinname. comparenocase ("line_in") = 0 |
Pinname. comparenocase ("linein") = 0 |
Pinname. comparenocase ("line") = 0)
{
Found = true;
}

The Code is a bit ugly, but if there is no better solution, it is also a solution. (Note: This method is used in the avcap example in Chapter 2nd of DirectShow practice selection .) Is there a better way? Yes! It depends on the combination of Windows multimedia API functions-through a series of functions such as mixergetdevcaps and mixergetlineinfo, we can first obtain the name of the input terminal used on the current system and the current sound card, then enumerate the input pin on the audio capture filter, and select one of them with the matching name. Use the Windows multimedia API function to query the name of a specific input terminal. The getconnectionname function is implemented as follows:

// DEMO code 2
// Some frequently-used line type:
// Line in-> mixerline_componenttype_src_line
// Microphone-> mixerline_componenttype_src_microphone
// CD player-> mixerline_componenttype_src_compactdisc
Bool getconnectionname (DWORD inlinetype, cstring & outname)
{
Uint cmixers = mixergetnumdevs ();
If (cmixers <1)
{
Trace ("No mixer device present .");
Return false;
}

// Open a mixer and determine its capabilities.
Hmixer;
If (mixeropen (& hmixer, 0, 0, 0, 0 )! = Mmsyserr_noerror)
{
Trace ("cocould not open mixer device .");
Return false;
}

Mixercaps caps;
If (mixergetdevcaps (uint) hmixer, & caps, sizeof (mixercaps ))! = Mmsyserr_noerror)
{
Mixerclose (hmixer );
Return false;
}

Trace ("Name of device: % s/n", caps. szpname );

Mixerline;
Bool found = false;
Int cdest = caps. cdestinations;
For (INT I = 0; I <cdest &&! Found; I ++)
{
Line. cbstruct = sizeof (mixerline );
Line. dwsource = 0;
Line. dwdestination = I;
Mixergetlineinfo (hmixerobj) hmixer, & line, mixer_getlineinfof_destination );

// For recording control
If (line. dwcomponenttype = mixerline_componenttype_dst_wavein)
{
// Enumerate all source connections for this destination line
Uint cconnections = line. cconnections;
For (uint J = 0; j <cconnections; j ++)
{
Line. cbstruct = sizeof (mixerline );
Line. dwsource = J;
Line. dwdestination = I;
Mixergetlineinfo (hmixerobj) hmixer, & line, mixer_getlineinfof_source );

// Compare with the user-specified line type
If (line. dwcomponenttype = inlinetype)
{
// Retrieve the connection name
Outname = line. szname;
Found = true;
Break;
}
}
}
}

Mixerclose (hmixer );
Return found;
}

Therefore, the Demo code 1 can be modified as follows:

// DEMO code 3
Cstring defaultconnection;
Getconnectionname (mixerline_componenttype_src_line, defaultconnection );
If (pinname = defaultconnection)
{
Found = true;
}

Obviously, 2nd solutions are better than 1st. However, it is better to update the DirectShow SDK by Microsoft, so that an interface (such as iamaudioconnection) is added to each input pin of the audio capture filter; through the iamaudioconnection interface, developers can easily identify the input terminal types represented by pin (like Windows multimedia, different input terminal types are identified using an integer value ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.