zoukankan      html  css  js  c++  java
  • DirectShow(三)AudioCapture

    1. 环境:xp+vs2005+DXSDK9_sumer2004
    2. 目的:将采集到的麦克风声音送至声卡
    3. GraphEdit模拟
    • add filter

    • connect filter

    • play,即可在耳机中听到麦克风中自己的声音(确认耳机和麦克风插好,并且没有被静音),有一点延时 :-)

     4.  代码实现(具体解释请参考此处,代码是俺抄的:-)):

    // AudioCaptureSaveConsole.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include<iostream>
    #include<cstring>
    #include<dshow.h>
    #include<windows.h>
    #include<conio.h>
    #include<stdio.h>
    //#include"streams.h"
    
    
    bool Bstr_Compare(BSTR,BSTR);//Function to compare BSTR strings
    void HR_Failed(HRESULT hr);// hr status function
    IMoniker* Device_Read(ICreateDevEnum*,IMoniker*,GUID,BSTR);//Device reading function
    IBaseFilter* Device_Init(IMoniker*,IBaseFilter*);//Function to initialize Input/Output devices
    void Device_Addition(IGraphBuilder*,IBaseFilter*,BSTR);//Function to add device to graph
    void Device_Connect(IBaseFilter*,IBaseFilter*,BSTR,BSTR);//Function to connect the two devices
    void Run_Graph(IMediaControl*);//Function to run the graph
    IFileSinkFilter* Add_File(IGraphBuilder*,IBaseFilter*,IFileSinkFilter*,BSTR);//Function to access default WAV file
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HRESULT hr;	// COM result
    	IGraphBuilder *pGraph = NULL;// Main graphbuilder pointer
    	IMediaControl *pControl = NULL;	// Media Control interface
    	ICreateDevEnum *pDeviceEnum = NULL;// System device enumerator
    	IBaseFilter *pInputDevice = NULL, *pOutputDevice = NULL;// Input and output filters(devices)
    	IBaseFilter *pWAVRecorder = NULL;//This is the transform filter that converts raw input to WAV
    	IBaseFilter *pFileWriter = NULL;// FileWriter filter shall be refernced by this pointer
    	IFileSinkFilter *pFile = NULL;
    
    	IMoniker *pDeviceMonik = NULL;// Device moniker
    	GUID DEVICE_CLSID ;// GUID i.e.  CLSID_Xxxxxxxxxxx
    	BSTR bstrDeviceName= {'\0'};// FriendlyName of device
    	BSTR bstrInPinName= {'\0'};// Input pin name
    	BSTR bstrOutPinName= {'\0'};// Output pin name
    
    	hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED );// Initialise COM
    	if (FAILED(hr))
    	{
    		HR_Failed(hr);
    		return hr;
    	}
    	hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&pGraph);//Initialize Graph builder
    	if (FAILED(hr))
    	{
    		HR_Failed(hr);
    		return hr;
    	}
    	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void **)&pDeviceEnum);//Initialize Device enumerator
    	if (FAILED(hr))
    	{
    		HR_Failed(hr);
    		return hr;
    	}
    	hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);// Query interface for IMediaControl
    	if (FAILED(hr))
    	{
    		HR_Failed(hr);
    		return hr;
    	}
    
    
    	/*******************************************************************************/
    	//Front mic input
    	DEVICE_CLSID = CLSID_AudioInputDeviceCategory;// the input device category
    	//bstrDeviceName = SysAllocString(L"Front Mic (IDT High Definition ");// device name as seen in Graphedit.exe
    	bstrDeviceName = SysAllocString(L"Realtek HD Audio Input");
    	pDeviceMonik = Device_Read(pDeviceEnum,pDeviceMonik,DEVICE_CLSID,bstrDeviceName);//read the required device 
    	pInputDevice = Device_Init(pDeviceMonik,pInputDevice);//Return the device after initializing it
    	Device_Addition(pGraph,pInputDevice,bstrDeviceName);//add device to graph
    	SysFreeString(bstrDeviceName);
    	/******************************************************************************/
    	//Transform filter
    	DEVICE_CLSID = CLSID_LegacyAmFilterCategory;// the DirectShow filters category
    	//bstrDeviceName = SysAllocString(L"AudioRecorder WAV Dest");// device name as seen in Graphedit.exe,using SysAllicString(..) to properly allocate string 
    	bstrDeviceName = SysAllocString(L"WAV Dest");
    	pDeviceMonik = Device_Read(pDeviceEnum,pDeviceMonik,DEVICE_CLSID,bstrDeviceName);//read the required device
    	pWAVRecorder = Device_Init(pDeviceMonik,pWAVRecorder);//Return the device after initializing it
    	Device_Addition(pGraph,pWAVRecorder,bstrDeviceName);//add device to graph
    	SysFreeString(bstrDeviceName);
    	/******************************************************************************/
    	//Connect input to output, Mic to AudioRecoder WAV Dest filter
    	bstrInPinName = SysAllocString(L"Capture");//Input pin name, as seen in GraphEdit
    	bstrOutPinName = SysAllocString(L"In");//Output pin name, this one will be input for AudioRecorder WAV Dest filter
    	Device_Connect(pInputDevice,pWAVRecorder,bstrInPinName,bstrOutPinName);//connect
    	SysFreeString(bstrInPinName);
    	SysFreeString(bstrOutPinName);
    	SysFreeString(bstrDeviceName);
    	/*******************************************************************************/
    	//Default output device
    	DEVICE_CLSID = CLSID_LegacyAmFilterCategory;// the DirectShow filters category
    	bstrDeviceName = SysAllocString(L"File writer");// device name as seen in Graphedit.exe,using SysAllicString(..) to properly allocate string 
    	pDeviceMonik = Device_Read(pDeviceEnum,pDeviceMonik,DEVICE_CLSID,bstrDeviceName);//read the required device
    	pFileWriter = Device_Init(pDeviceMonik,pFileWriter);//Return the device after initializing it
    	SysFreeString(bstrDeviceName);
    	SysAllocString(L"..\\test.wav");//This is the file name as seen in GraphEdit
    	// access the default file before adding to the graph.
    	//This function must be called first before adding
    	//the device to the graph.
    	pFile = Add_File(pGraph,pFileWriter,pFile,bstrDeviceName);
    	Device_Addition(pGraph,pFileWriter,bstrDeviceName);//add device to graph
    	/******************************************************************************/
    	//Connect input to output, AudioRecoder WAV Dest filter to test.wav i.e. File writer filter
    	bstrInPinName = SysAllocString(L"Out");//Input pin name, as seen in GraphEdit
    	bstrOutPinName = SysAllocString(L"in");//Output pin name, this one will be input for File writer filter
    	Device_Connect(pWAVRecorder,pFileWriter,bstrInPinName,bstrOutPinName);//Connect
    	SysFreeString(bstrInPinName);
    	SysFreeString(bstrOutPinName);
    	SysFreeString(bstrDeviceName);
    	/*******************************************************************************/
    
    	//Now run the graph
    	Run_Graph(pControl);
    
    	//Loop till you don't close the console window or hit a key!
    	cout<<"Close the window to exit or hit any key"<<endl;
    	while(!_kbhit())
    	{
    
    	}
    
    	pFile->Release();
    	pControl->Release();//Release control
    	pDeviceEnum->Release();//Release Device enumerator
    	pGraph->Release();//Release the Graph
    }
    
    
    /************************************************************/
    bool Bstr_Compare(BSTR bstrFilter,BSTR bstrDevice)
    {
    	bool flag = true;
    	int strlenFilter = SysStringLen(bstrFilter);//set string length
    	int strlenDevice = SysStringLen(bstrDevice);//set string length
    	char* chrFilter = (char*)malloc(strlenFilter+1);// allocate memory
    	char* chrDevice = (char*)malloc(strlenDevice+1);// allocate memory
    	int j = 0;
    
    	if (strlenFilter!=strlenDevice)//if the strings are of not the same length,means they totall different strings
    		flag = false;//sety flag to false to indicate "not-same" strings
    	else
    	{
    		for(; j < strlenFilter;j++)//now, copy 1 by 1 each char to chrFilter and chrDevice respectively
    		{
    			chrFilter[j] = (char)bstrFilter[j];//copy
    			chrDevice[j] = (char)bstrDevice[j];//copy
    			cout<<j;
    
    		}
    		chrFilter[strlenFilter] = '\0';//add terminating character
    		chrDevice[strlenDevice] = '\0';//add terminating character
    
    		for(j=0; j < strlenFilter;j++)//check loop
    		{
    			if(chrFilter[j] != chrDevice[j])//check if there are chars that are not samne
    				flag = false;//if chars are not same, set flag to false to indicate "not-same" strings
    		}
    
    		if(flag == true && j == strlenFilter-1)//see if we went through the 'check loop' 
    			flag = true;//means strings are same
    	}
    	return flag;
    }
    
    
    /************************************************************/
    void HR_Failed(HRESULT hr)
    {
    // 	TCHAR szErr[MAX_ERROR_TEXT_LEN];
    // 	DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
    // 	if (res == 0)
    // 	{
    // 		StringCchPrintf(szErr, MAX_ERROR_TEXT_LEN, L"Unknown Error: 0x%2x", hr);
    // 	}
    // 
    // 	MessageBox(0, szErr, TEXT("Error!"), MB_OK | MB_ICONERROR);
    	return;
    }
    
    /************************************************************/
    IMoniker* Device_Read(ICreateDevEnum* pDeviceEnum,IMoniker *pDeviceMonik,GUID DEVICE_CLSID,BSTR bstrDeviceName)
    {
    	HRESULT hr;
    	IEnumMoniker *pEnumCat = NULL;// Device enumeration moniker
    	VARIANT varName;
    
    	hr = pDeviceEnum->CreateClassEnumerator(DEVICE_CLSID, &pEnumCat, 0);// Enumerate the specified device, distinguished by DEVICE_CLSID
    
    	if (hr == S_OK) 
    	{
    		ULONG cFetched;
    		while (pEnumCat->Next(1, &pDeviceMonik, &cFetched) == S_OK)//Pickup as moniker
    		{
    			IPropertyBag *pPropBag = NULL;
    			hr = pDeviceMonik->BindToStorage(0, 0, IID_IPropertyBag,(void **)&pPropBag);//bind the properties of the moniker
    			if (SUCCEEDED(hr))
    			{
    				VariantInit(&varName);// Initialise the variant data type
    				hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    				if (SUCCEEDED(hr))
    				{	
    					if(Bstr_Compare(varName.bstrVal,bstrDeviceName) == true)//make a comparison
    					{	
    						wcout<<varName.bstrVal<<" found"<<endl;
    						return pDeviceMonik;
    					}
    				}
    				else HR_Failed(hr);
    				VariantClear(&varName);//clear the variant data type
    				pPropBag->Release();//release the properties
    			}
    			else HR_Failed(hr);
    			pDeviceMonik->Release();//release Device moniker
    		}
    		pEnumCat->Release();//release category enumerator
    	}
    	else HR_Failed(hr);
    	return NULL;
    }
    
    /************************************************************/
    IBaseFilter* Device_Init(IMoniker* pDeviceMonik,IBaseFilter* pDevice)
    {
    	HRESULT hr;
    	hr = pDeviceMonik->BindToObject(NULL, NULL, IID_IBaseFilter,(void**)&pDevice);//Instantiate the device
    	if (SUCCEEDED(hr))
    	{
    		cout<<"Device initiation successful..."<<endl;
    	}
    	else HR_Failed(hr);
    
    	return pDevice;
    }
    
    
    /************************************************************/
    void Device_Addition(IGraphBuilder* pGraph,IBaseFilter* pDevice,BSTR bstrName)
    {
    	HRESULT hr;
    	hr = pGraph->AddFilter(pDevice,bstrName);//Adding to main graph
    	if(SUCCEEDED(hr))
    	{
    		wcout<<"Addition of "<<bstrName<<" successful..."<<endl;
    	}
    	else HR_Failed(hr);
    }
    
    
    /************************************************************/
    void Device_Connect(IBaseFilter* pInputDevice,IBaseFilter* pOutputDevice,BSTR bstrInputPin,BSTR bstrOutputPin)
    {
    	HRESULT hr;
    	IEnumPins *pInputPin = NULL,*pOutputPin  = NULL;// Pin enumeration
    	IPin *pIn = NULL, *pOut = NULL;// Pins
    
    	hr = pInputDevice->EnumPins(&pInputPin);// Enumerate the pin
    	if(SUCCEEDED(hr))
    	{
    		cout<<"Input Pin Enumeration successful..."<<endl;
    		hr = pInputDevice->FindPin(bstrInputPin,&pIn);//Get hold of the pin as seen in GraphEdit
    		if(SUCCEEDED(hr))
    		{
    			wcout<<bstrInputPin<<" Input pin found"<<endl;	
    		}
    		else HR_Failed(hr);
    
    	}
    	else HR_Failed(hr);
    
    	hr = pOutputDevice->EnumPins(&pOutputPin);//Enumerate the pin
    	if(SUCCEEDED(hr))
    	{
    		cout<<"Output Pin Enumeration successful..."<<endl;
    		hr = pOutputDevice->FindPin(bstrOutputPin,&pOut);
    		if(SUCCEEDED(hr))
    		{
    			wcout<<bstrOutputPin<<" Output pin found"<<endl;
    		}
    		else HR_Failed(hr);
    
    	}
    	else HR_Failed(hr);
    
    	hr = pIn->Connect(pOut,NULL);	//Connect the input pin to output pin
    	if(SUCCEEDED(hr))
    	{
    		cout<<"Pin connection successful..."<<endl;
    	}
    	else HR_Failed(hr);
    
    }
    
    
    /************************************************************/
    void Run_Graph(IMediaControl* pControl)
    {
    	HRESULT hr;
    	hr = pControl->Run();// Now run the graph, i.e. start recording!
    	if(SUCCEEDED(hr))
    	{
    		cout<<"You must be recodring to something!!!"<<endl;
    	}
    	else HR_Failed(hr);
    }
    IFileSinkFilter* Add_File(IGraphBuilder *pGraph,IBaseFilter* pDevice,IFileSinkFilter* pFile,BSTR bstrName)
    {
    	HRESULT hr;
    
    	IFileSinkFilter *pFileSink= NULL;// pointer to filter that allows data writing
    	hr = pDevice->QueryInterface(IID_IFileSinkFilter, (void**)&pFile);
    	if(SUCCEEDED(hr))
    	{
    		wcout<<"Querying of IFileSinkFilter "<<bstrName<<" successful..."<<endl;
    	}
    	else HR_Failed(hr);
    	hr = pFile->SetFileName(bstrName,NULL);//setting the name of the file
    	if(SUCCEEDED(hr))
    	{
    		wcout<<"Setting name to "<<bstrName<<" successful..."<<endl;
    	}
    	else HR_Failed(hr);
    
    	return pFileSink = pFile;
    }
  • 相关阅读:
    twisted与websocket
    【算法竞赛 数学】拉格朗日插值法
    Event and Delegate
    Lambda 表达式 问题
    Singleton 模式
    COM Interop 简介
    outlook2007阻止附件的问题 http://hi.baidu.com/simplejoy/blog/item/53693897bd16046554fb9631.html
    Lnk1202 http://www.codeguru.com/forum/archive/index.php/t386908.html
    error LNK2001: unresolved external symbol
    Delegate 示例
  • 原文地址:https://www.cnblogs.com/dahai/p/2089180.html
Copyright © 2011-2022 走看看