How to use DirectShow technology to switch two-channel audio channel

xiaoxiao2021-03-06  41

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 // DirectShow (Includes Windows.h)

#include // Declares define_guid to declare an extern_c const.

#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

转载请注明原文地址:https://www.9cbs.com/read-69020.html

New Post(0)