When we write multimedia player programs, we often encounter problems that don't know how to switch between left channels or right-channel audio, and use MCI interface or media player controls can only use adjustment channels. The method reaches the purpose of switching the channel, but there is only one speaker to emit a sound, and some songs in some VCD formats can even switch channels with this method. But when we use the media player to play the VCD format file, if you carefully observe, we will find that the MPEG Audio Decoder filter can be switched by the property -> Advanced -> select MPEG Audio Decoder Filter -> Properties -> Channel method - Sound or stereo state, how does the media player implement this function, but why can't we directly implement it directly in VB? In fact, this is because the media player is based on DirectShow technology. Similarly, we can also directly call DirectShow to play the purpose of playing multimedia files, but to implement switching channels, you must first understand the format of audio data, and below 16-bit audio data (8-bit audio is just less bytes) Data) Simply talk about the decompressed audio data in the channel distribution format that is about to play. When the audio data is decoded by various decoder, it will be sent to the sound card data buffer when playing, and its data is WAVE format, for example: AA BB CC DD, where AA-left channel, BB-right channel , CC-left channel, DD-right channel, is it simple to :) If you want to switch to the left channel, use the left channel to fill to the right channel, even the audio data above is: AA AA CC CC This form knows it, the next step is to use DirectShow technology to write a filter in front of the sound card Reandere, as long as it is the audio data of the two-channel format, we can have channels. Switch. The following list is listed in the Filter source code for 16 audio channels (it is very simple, but you have to know about COM)
//
//
// filename: myfilter.cpp
// Author: DAMO
// Date: 2004.06.01
// Comment:
//
//
#include
#include
#include "izqaudio.h" // Custom interface
// {cfbe95e1-5db4-11d8-929c-92b98a07327d}
Define_guid (CLSID_ZQAUDIO,
0xcfbe95e1, 0x5db4, 0x11d8, 0x92, 0x9c, 0x92, 0x32, 0x8a, 0x7, 0x32, 0x7d);
Const amoviesetup_mediatype sudPintypes =
{& Mediatype_audio // CLSMAJORTYPE
& Mediabtype_pcm}; // CLSMINORTYPE
Const Amoviesetup_pin psudpins [] = {{L "Input" // strname
False // Brendered
, False // Boutput
False // Bzero
, False // BMANY
, & Clsid_null // ClsConnectStofilter
, L "" // strConnectStopin
1 // Ntypes
& Sudpintypes // lptypes
}
, {L "OUTPUT" // Strname
False // Brendered
True // Boutput
False // Bzero
, False // BMANY
, & Clsid_null // ClsConnectStofilter
, L "" // strConnectStopin
1 // Ntypes
& Sudpintypes // lptypes
}
}
const amoviesetup_filter suDnullnull =
{& Clsid_zqaudio // CLSID
, L "zhang qiang filter" // strname
, MERIT_DO_NOT_USE // DWMERIT
2 // npins
, psudpins}; // LPPIN
// czqaudio
//
Class Czqaudio:
Public CTRANSINPLACEFILTER,
Public IzqAudioInterface
{
PUBLIC:
// COM function declaration
Static Cunknown * WinAPI CreateInstance (LPunknown Punk, HRESULT * PHR);
STDMETHODIMP NondelegatingQueryInterface (Refiid Riid, Void ** PPV);
Declare_iunknown;
STDMETHODIMP PUT_AUDIOMODE (Int INAUDIO_CHANNEL_MODE);
STDMETHODIMP GET_AUDIOMODE (INT * OUTAUDIO_CHANNEL_MODE);
Private:
INT AUDIO_CHANNEL_MODE; // Sound mode settings
// int S;
Ccritsec M_Mylock; // Lock object
// Construct the function while calling the constructor of the base class
Czqaudio (Tchar * Tszname, LPunknown Punk, HRESULT * PHR)
: CTransinplaceFilter (Tszname, Punk, CLSID_ZQAUDIO, PHR)
{Audio_Channel_Mode = 0;}
// Main execution function
HRESULT TRANSFORM (IMEDISAMPLE * PSAMPLE); / / Check the input type
HRESULT CHECKINPUTTYPE (Const CMediatyPE * MTIN);
// Check if the input and output types are consistent
// HRESULT CHECKTRANSFORM (const cmediatype * mtin, const cmediatype * mtout) {returnide s_ok;};
// Type
HRESULT GETMEDITYPE (int iposition, cmediatype * pmediatype);
}
// Needed for the createInstance Mechanism
CFactoryTemplate g_templates [] =
{{L "zhang qiang filter"
& Clsid_zqaudio
, Czqaudio :: CreateInstance
NULL
& Sudnullnull}
}
INT g_ctemplates = sizeof (g_templates) / sizeof (g_templates [0]);
//
// CreateInstance
//
// Create an object instance
Cunknown * WinAPI Czqaudio :: CreateInstance (lpunknown punk, hresult * phr) {
Czqaudio * pnewobject = new czqaudio ("ZHANG Qiang Audio Filter", Punk, PHR);
IF (pnewobject == NULL) {
* pHR = E_OUTOFMEMORY;
}
Return PnewObject;
} // createInstance
HRESULT CZQAUDIO :: Transform (iMediaSample * psample)
{
BYTE * PoutData;
INT i = 0, w_pos = 0, r_pos = 0, Samplesize = 0, N = 0;
// Perform channel selection
Switch (audio_channel_mode)
{
Case 1: r_pos = 0;
W_POS = 2;
Break; // Left channel
Case 2: r_pos = 2;
W_POS = 0;
Break; // Right channel
DEFAULT: RETURN NOERROR; / / Do not process (two-channel mode)
}
Psample-> getPointer (& PoutData); // acquire buffer pointer
Samplesize = psample-> getActualDatalength (); // acquired valid data size
n = Samplesize / 4; // Cycle number
/ / Perform a channel switching operation
For (i = 0; i Memcpy (poutdata w_pos, poutdata r_pos, 2); W_POS = 4; R_POS = 4; } Return noerror; } HRESULT CZQAUDIO :: getMediaType (int iposition, cmediatype * pmediatype) { Return noerror; } HRESULT CZQAUDIO :: CheckinPuttype (const cmediatype * mtin) { / / Check if it is stopped, and whether it is an audio data type IF (isstopped () && * mtin-> type () == mediatype_audio) { / / Check if it is a PCM format IF (* mtin-> subtype () == MediaSubType_PCM || * Mtin-> Subtype () == MediaSubType_wave) { Return S_OK; // Successful } } Return E_INVALIDARG; // Invalid Type } // Set the channel STDMETHODIMP CZQAUDIO :: PUT_AUDIOMODE (INT INAUDIO_CHANNEL_MODE) { / / Judgment whether the parameter is legal IF (INAUDIO_CHANNEL_MODE> = 0 && INAUDIO_CHANNEL_MODE <= 2) { Audio_Channel_Mode = INAUDIO_CHANNEL_MODE Return S_OK; } Return E_INVALIDARG; // Parameter is invalid } // Get channel mode settings STDMETHODIMP CZQAUDIO :: GET_AUDIOMODE (INT * OUTAUDIO_CHANNEL_MODE) { // Get channel mode settings * Outaudio_channel_mode = audio_channel_mode; Return S_OK; } // Exposure interface StdMethodimp Czqaudio :: NondelegatingQueryinterface (Refiid Riid, Void ** PPV) { Checkpointer (PPV, E_POINTER); IF (riid == iid_izqaudiointerface) { Return GetInterface ((izqaudioInterface *) this, ppv); } else { Return CTransinplaceFilter :: NondelegatingQueryInterface (RIID, PPV); } } / ********************************************************************************* ************* / * Registration and anti-registration functions / ************************************************** ************************ / Stdapi DllregisterServer () { Return AmoviedllRegisterServer2 (TRUE); } Stdapi DllunregisterServer () { Return AmoviedllRegisterServer2 (False); } // Shield 4514 Warning #pragma Warning (Disable: 4514) //Izqaudio.h // Custom interface for channel switching #ifndef _h_izqaudioInterface_ #define _h_izqaudioInterface_ #ifdef _cplusplus Extern "C" { #ENDIF // izqaudiochannel's guid // {83ba1141-6135-11d8-929c-a23780a5eb7c} Define_guid (IID_IZQAUDIOINTERFACE, 0x83ba1141, 0x6135, 0x11d8, 0x92, 0x9c, 0xa2, 0x37, 0x80, 0xa5, 0xeb, 0x7c); // Dual channel mode parameter declaration #define am_audio_dual_merge 0 // Double channel #DEFINE AM_AUDIO_DUAL_LEFT 1 / / Left #define am_audio_dual_right 2 // Right Volume // izqaudiointerface interface definition Declare_Interface_ (IzqAudioInterface, IUNKNOWN) { // Set the channel: 0- does not process the channel, 1-left channel, 2-right channel STDMETHOD (PUT_AUDIOMODE) (THIS_ INT INAUDIO_CHANNEL_MODE Pure; // Return to the channel setting STDMETHOD (THIS_ INT * OUTAUDIO_CHANNEL_MODE Pure; } #ifdef _cplusplus } #ENDIF #ENDIF / / _ H_IZQAUDIO_ // ********************************************* The source of IzqAutio.h file Code *********************************************************** * //Izqaudio.h #Ifndef // custom interface channel switching _H_IZQAudioInterface_ # define _H_IZQAudioInterface_ # ifdef _cplusplusextern "C" {# endif // IZQAudioChannel's GUID // {83BA1141-6135-11d8-929C-A23780A5EB7C} DEFINE_GUID (IID_IZQAudioInterface, 0x83ba1141, 0x6135, 0x11d8 , 0x92, 0x9c, 0xa2, 0x37, 0x80, 0xa5, 0xeb, 0x7c); // Double-channel mode parameter declaration #define am_audio_dual_merge 0 // Double channel #define am_audio_dual_LEFT 1 // Left channel #define am_audio_dual_right 2 // Right channel // izqaudioInterface interface definition declare_interface_ (izqaudiointerface, iUnknown) {// Set channel: 0- Do not processed channel, 1-left, 2-right channel stdmethod (this_ int inaudio_channel_mode) Pure; / / Return to the channel setting stdmethod (this_ int * outaudio_channel_mode) pure;}; # ifdef _cplusplus} # Endif # endif // h_izqaudio_ // *********************** The following is the content of the zqaudio.def file *************** ************ Library Zqaudio.Axexports DllgetClassObject Private DllcanunloadNow Private DllRegisterServer Private DllunregisterServer Private