⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directsounddevice.cxx

📁 MiniSip Client with DomainKeys Authentication, Sip, Audio communications, Echo Cancel
💻 CXX
字号:
/* Copyright (C) 2004-2006 the Minisip Team  This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA *//* Copyright (C) 2004  * * Authors: Erik Eliasson <eliasson@it.kth.se> *          Johan Bilien <jobi@via.ecp.fr> *	    Cesc Santasusana <c e s c DOT s a n t a [AT} g m a i l DOT c o m>*/#include<config.h>#include<libminisip/soundcard/DirectSoundDevice.h>#include<windows.h>#include<initguid.h>#include<libmutil/merror.h>//Output buffer is set to 100ms#define DS_OUTPUT_BUFFER_SIZE 2*2*48000/10//Input buffer is set to 40ms#define DS_INPUT_BUFFER_SIZE 1*2*48000/25using namespace std;/** *  * Internals:  *  The DirectSound device maintains two buffers, a output buffer and  *  a capture buffer. They are circular buffers with cursors/pointers to *  the current play/capture point. The positions can be set using *  the SetCurrentPosition method. GetCurrentPosition can be used to *  get both the play/capture and write/write cursors. * */DirectSoundDevice::DirectSoundDevice( string device ):SoundDevice( device ){	HRESULT hr;	// Capture buffer settings	WAVEFORMATEX inAudioFormat;	ZeroMemory( &inAudioFormat, sizeof(WAVEFORMATEX) );	inAudioFormat.wFormatTag = WAVE_FORMAT_PCM;	inAudioFormat.nChannels = 1;	inAudioFormat.nSamplesPerSec = 48000;	inAudioFormat.nAvgBytesPerSec=48000*2*1;	inAudioFormat.nBlockAlign=2; 	// number of bytes in smallest "atomic unit" - nChannels*wBitsPerSample/8	inAudioFormat.wBitsPerSample=16;		// set parameters for what the buffer will look like	DSCBUFFERDESC dscbd;	ZeroMemory( &dscbd, sizeof(DSCBUFFERDESC) );	dscbd.dwSize          = sizeof(DSCBUFFERDESC);	dscbd.dwFlags         = 0;	dscbd.dwBufferBytes   = DS_INPUT_BUFFER_SIZE;	dscbd.lpwfxFormat     = &inAudioFormat;	// Playout buffer settings	WAVEFORMATEX outAudioFormat;	ZeroMemory( &outAudioFormat, sizeof(WAVEFORMATEX) );	outAudioFormat.wFormatTag = WAVE_FORMAT_PCM;	outAudioFormat.nChannels = 2;	outAudioFormat.nSamplesPerSec = 48000;	outAudioFormat.nAvgBytesPerSec=48000*2*2;	outAudioFormat.nBlockAlign=4; 	// number of bytes in smallest "atomic unit" - nChannels*wBitsPerSample/8	outAudioFormat.wBitsPerSample=16;		// set parameters for what the buffer will look like	DSBUFFERDESC dsbd;	ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );	dsbd.dwSize          = sizeof(DSBUFFERDESC);	dsbd.dwFlags         = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 ;	dsbd.dwBufferBytes   = /*g_dwOutputBufferSize*/ DS_OUTPUT_BUFFER_SIZE;	dsbd.guid3DAlgorithm = GUID_NULL;	dsbd.lpwfxFormat     = &outAudioFormat;/*#if (_WIN32_WINNT >= 0x0500)#warning "WIN32 0500"#else#warning "WIN32 not high enough"#endif*/	//The following requires Windows XP - if not supported, then	//DirectSoundCreate can be used (windows echo cancelling filter	//will not be possible).	if (FAILED(hr=DirectSoundFullDuplexCreate8(NULL,//&DSDEVID_DefaultVoiceCapture,					NULL,// &DSDEVID_DefaultVoicePlayback, 					&dscbd,					&dsbd,					GetConsoleWindow(),					DSSCL_PRIORITY,					&dsDuplexInterfaceHandle,					&inputBufferHandle,					&outputBufferHandle,					NULL ))){		merror("Can not create DirectSound device (DirectSoundFullDuplexCreate8)");	}	setCaptureNotificationPoints(inputBufferHandle);}HRESULT DirectSoundDevice::setCaptureNotificationPoints(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB){	LPDIRECTSOUNDNOTIFY8 pDSNotify;	WAVEFORMATEX         wfx;  	DSBPOSITIONNOTIFY  rgdsbpn[cEvents];	HRESULT    hr;	if (NULL == pDSCB) return E_INVALIDARG;	if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify)))	{		return hr;	}	if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL)))	{		return hr;	}	// Create events.	for (int i = 0; i < cEvents; ++i)	{		inputSoundEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);		if (NULL == inputSoundEvent[i])		{			hr = GetLastError();			return hr;		}	}	// Describe notifications. 	rgdsbpn[0].dwOffset = (DS_INPUT_BUFFER_SIZE/2) -1;	rgdsbpn[0].hEventNotify = inputSoundEvent[0];	rgdsbpn[1].dwOffset = DS_INPUT_BUFFER_SIZE - 1;	rgdsbpn[1].hEventNotify = inputSoundEvent[1];	// Create notifications.	//cerr << "setCaptureNotificationPoints: cEvents="<< cEvents<<endl;	if (FAILED(hr = pDSNotify->SetNotificationPositions(cEvents, rgdsbpn))){		cerr << "DirectSoundDevice::setCaptureNotificationPoints: ERROR: failed to set notification points"<<endl;		cerr << "Error code: "<< hex << hr << dec << endl;	}		pDSNotify->Release();	 //TODO: This line should not be commented				 //out?!		return hr;}DirectSoundDevice::~DirectSoundDevice(){	//TODO: FIXME: Release DirectSound resources }int DirectSoundDevice::openRecord( int samplingRate, int nChannels, int format ){	this->nChannelsRecord = 1;	this->samplingRate = 48000;	this->openedRecord = true;	if (FAILED(inputBufferHandle->Start(DSCBSTART_LOOPING))){		merror("Could not start recording on direct sound input buffer");			}	return 0;}int DirectSoundDevice::openPlayback( int samplingRate, 				int nChannels, 				int format ){	HRESULT hr;	this->nChannelsPlay = nChannels;	this->nChannelsPlay = 2;	this->samplingRate = 48000;	openedPlayback = true;	if (FAILED(hr = outputBufferHandle->Play(0,					/*0xFFFFFFFF*/ 0,	//Priority: TODO: check if we can set it to 0xFFFFFFFF (source must be created with DSBCAPS_LOCDEFER)					DSBPLAY_LOOPING					))){		cerr << "ERROR: DirectSoundDevice: Play failed."<<endl;		cerr << "Error code: "<< hex << hr << endl;	}		return 0;}int DirectSoundDevice::closeRecord(){	if (FAILED(inputBufferHandle->Stop())){		merror("Could not stop recording on direct sound input buffer");			}	return 0;}int DirectSoundDevice::closePlayback(){	if (FAILED(outputBufferHandle->Stop())){		merror("Could not stop recording on direct sound input buffer");			}	return 0;}int DirectSoundDevice::readFromDevice( byte_t * buffer, uint32_t nSamples ){	static int wait_i=0;	//Wait until the record cursor reaches the end of a 20ms block	if (WaitForSingleObject( inputSoundEvent[wait_i], INFINITE)==WAIT_FAILED){		merror("DirectSoundDevice::readFromDevice (waiting for capture data): WaitForSingleObject");	}	//The condition must be manually reset.	ResetEvent(inputSoundEvent[wait_i]);	VOID * lockedBuffer;	DWORD lockedBufferSize;	int readBlockSize = (48000*1*2)/50; // 20 ms, mono, 16 bit samples	assert( (int)nSamples == (readBlockSize/2) );	inputBufferHandle->Lock(wait_i*readBlockSize, readBlockSize, &lockedBuffer, &lockedBufferSize, NULL,NULL,0);	short *sp = (short*) lockedBuffer;	for (int n=0; n<readBlockSize/2; n++){		((short*)buffer)[n] = sp[n];	}	inputBufferHandle->Unlock(lockedBuffer, lockedBufferSize, NULL,0);		wait_i = (wait_i+1) % cEvents;		return nSamples;}int DirectSoundDevice::writeToDevice( byte_t * buffer, uint32_t nSamples ){	static int wait_i=0;	HRESULT hr;	VOID * lockedBuffer;	DWORD lockedBufferSize;	int writeBlockSize = (48000*2*2)/50;	assert( (int)(nSamples * 2 * getNChannelsPlay()) == writeBlockSize);		if (FAILED(hr=outputBufferHandle->Lock(wait_i*writeBlockSize, writeBlockSize, &lockedBuffer, &lockedBufferSize, NULL,NULL,0))){		cerr <<"DirectSoundDevice: Lock failed on buffer"<< endl;	}	short *sp = (short*) lockedBuffer;	for (int n=0; n<(int)nSamples * (int)getNChannelsPlay(); n++){		sp[n]=((short*)buffer)[n];	}	if (FAILED(hr=outputBufferHandle->Unlock(lockedBuffer, lockedBufferSize, NULL,0))){		cerr <<"DirectSoundDevice: Unlock failed on buffer"<< endl;	}		wait_i = (wait_i+1) % 5; //FIXME: Hardcoded to be 100ms - 5  20ms blocks		return nSamples;}		int DirectSoundDevice::readError( int errcode, byte_t * buffer, uint32_t nSamples ) {	return -1;}int DirectSoundDevice::writeError( int errcode, byte_t * buffer, uint32_t nSamples ) {	return -1;}	void DirectSoundDevice::sync(){}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -