// {CFBE95E1-5DB4-11d8-929C-92B98A07327D}
DEFINE_GUID(CLSID_ZQAudio,
0xcfbe95e1, 0x5db4, 0x11d8, 0x92, 0x9c, 0x92, 0xb9, 0x8a, 0x7, 0x32, 0x7d);
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{ &MEDIATYPE_Audio // clsMajorType
, &MEDIASUBTYPE_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 函数声明
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; //声道模式设置
//int s;
CCritSec m_Mylock; //锁定对象
//构造函数,同时调用基类的构造函数
CZQAudio(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
: CTransInPlaceFilter (tszName, punk, CLSID_ZQAudio, phr)
{ Audio_Channel_Mode=0; }
//主要执行函数
HRESULT Transform(IMediaSample *pSample);
//检查输入类型
HRESULT CheckInputType(const CMediaType *mtIn);
//检查输入与输出类型是否一致
//HRESULT CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut){ return S_OK; };
//取得类型
HRESULT GetMediaType(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
//
// 创建一个对象实例
CUnknown * WINAPI CZQAudio::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
CZQAudio *pNewObject = new CZQAudio(NAME("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;
//进行声道选择
switch(Audio_Channel_Mode)
{
case 1:r_pos=0;
w_pos=2;
break; //左声道
case 2:r_pos=2;
w_pos=0;
break; //右声道
default:return NOERROR; //不处理(双声道模式)
}
pSample->GetPointer(&pOutData); //取得缓冲区指针
SampleSize=pSample->GetActualDataLength(); //取得有效数据大小
n=SampleSize/4; //循环次数
//执行声道切换操作
for(i=0;i
w_pos+=4;
r_pos+=4;
}
return NOERROR;
}
HRESULT CZQAudio::GetMediaType(int iPosition,CMediaType *pMediaType)
{
return NOERROR;
}
HRESULT CZQAudio::CheckInputType(const CMediaType *mtIn)
{
//检查是否在停止状态,且是否是音频数据类型
if(IsStopped() && *mtIn->Type()==MEDIATYPE_Audio)
{
//检查是否是PCM格式的数据
if(*mtIn->Subtype()==MEDIASUBTYPE_PCM ||
*mtIn->Subtype()==MEDIASUBTYPE_WAVE)
{
return S_OK; //成功
}
}
return E_INVALIDARG; //无效类型
}
//设置声道
STDMETHODIMP CZQAudio::put_AudioMode(int inAudio_Channel_Mode)
{
//判断参数是否合法
if(inAudio_Channel_Mode>=0 && inAudio_Channel_Mode<=2){
Audio_Channel_Mode=inAudio_Channel_Mode;
return S_OK;
}
return E_INVALIDARG; //参数无效
}
//取得声道模式设置
STDMETHODIMP CZQAudio::get_AudioMode(int *outAudio_Channel_Mode)
{
//取得声道模式设置
*outAudio_Channel_Mode=Audio_Channel_Mode;
return S_OK;
}
//暴露接口
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);
}
}
/******************************全局函数******************************/
* 注册及反注册函数
/**************************************************************************/
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
//屏蔽 4514 警告
#pragma warning( disable:4514)
//IZQAudio.h
//声道切换的自定义接口
#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);
// 双声道模式参数声明
#define AM_AUDIO_DUAL_MERGE 0 //双声道
#define AM_AUDIO_DUAL_LEFT 1 //左声道
#define AM_AUDIO_DUAL_RIGHT 2 //右声道
//IZQAudioInterface 接口定义
DECLARE_INTERFACE_(IZQAudioInterface,IUnknown)
{
//设置声道:0-不处理声道,1-左声道,2-右声道
STDMETHOD (put_AudioMode) (THIS_
int inAudio_Channel_Mode
) PURE;
//返回声道的设置
STDMETHOD (get_AudioMode) (THIS_
int *outAudio_Channel_Mode
) PURE;
};
#ifdef _cplusplus
}
#endif
#endif //_H_IZQAudio_
将以上文件加入到VC工程里,并安装DirectX8.1 SDK,设置好相关的文件搜索路径(具体可参考
另外,用它对某些VCD格式的歌曲会无效,原因在于Mpeg Audio Decoder解码器的设置问题,你可在程序中包含MpegType.h文件来切换声道.
以上均是我摸索实验的结果,如有错误还请指出!