Example #1
0
// ---------------------------------------------------------------------------------------
// ds3d_init()
//
// Initialize the DirectSound3D system.  Call the initialization for the pDS3D_listener
// 
// returns:     -1	=> init failed
//              0		=> success
int ds3d_init(int voice_manager_required)
{
	if (DS3D_inited == TRUE)
		return 0;

#ifndef USE_OPENAL
	if (voice_manager_required == 1)
	{
		LPKSPROPERTYSET pset;
		pset = (LPKSPROPERTYSET)ds_get_property_set_interface();

		if (pset == NULL)
		{
			nprintf(("Sound", "Disabling DirectSound3D since unable to get property set interface\n"));
			return -1;
		}

		HRESULT hr;
		unsigned long driver_support = 0;

		hr = pset->QuerySupport(DSPROPSETID_VoiceManager_Def, DSPROPERTY_VMANAGER_MODE, &driver_support);
		if (FAILED(hr))
		{
			nprintf(("Sound",
					 "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n"));
			return -1;
		}

		if ((driver_support & KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET) != (KSPROPERTY_SUPPORT_SET |
																				   KSPROPERTY_SUPPORT_GET))
		{
			nprintf(("Sound",
					 "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n"));
			return -1;
		}

		VmMode vmode = DSPROPERTY_VMANAGER_MODE_AUTO;
		hr = pset->Set(DSPROPSETID_VoiceManager_Def, DSPROPERTY_VMANAGER_MODE, NULL, 0, &vmode, sizeof(float));
		if (FAILED(hr))
		{
			nprintf(("Sound",
					 "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n"));
			return -1;
		}
	}
#endif

	if (ds3d_init_listener() != 0)
	{
		return -1;
	}

	DS3D_inited = TRUE;
	return 0;
}
Example #2
0
//===========================================================================
// EAXSetf
//===========================================================================
void EAXSetf(DWORD prop, float value)
{
	if(!eaxListener) return;
	eaxListener->Set(DSPROPSETID_EAX_ListenerProperties,
		prop | DSPROPERTY_EAXLISTENER_DEFERRED, NULL, 0, 
		&value, sizeof(float));
}
Example #3
0
//===========================================================================
// EAXCommitDeferred
//===========================================================================
void EAXCommitDeferred(void)
{
	if(!eaxListener) return;
	eaxListener->Set(DSPROPSETID_EAX_ListenerProperties,
		DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS, 
		NULL, 0, NULL, 0);
}
Example #4
0
//===========================================================================
// EAXMuldw
//	Linear multiplication for a logarithmic property.
//===========================================================================
void EAXMuldw(DWORD prop, float mul)
{
	DWORD	retBytes;
	LONG	value;

	if(!eaxListener) return;
	if(FAILED(hr = eaxListener->Get(DSPROPSETID_EAX_ListenerProperties,
		prop, NULL, 0, &value, sizeof(value), &retBytes)))
	{
		/*if(!ignore_eax_errors)
			Con_Message("DS_EAXMuldw (prop:%i) get failed. Result: %x.\n", 
				prop, hr & 0xffff);*/
		return;
	}
	EAXSetdw(prop, LinLog(pow(10, value/2000.0f) * mul));
}
Example #5
0
//===========================================================================
// DS_Shutdown
//===========================================================================
void DS_Shutdown(void)
{
	if(!initOk) return;

	if(eaxListener) eaxListener->Release();
	if(dsListener) dsListener->Release();
	if(primary) primary->Release();
	if(dsound) dsound->Release();
	
	eaxListener = NULL;
	dsListener = NULL;
	primary = NULL;
	dsound = NULL;

	initOk = false;
}
Example #6
0
//-----------------------------------------------------------------------------
// Установка eax параметров
// на входе    :  prop     - указатель на eax интерфейс
//  			  type     - тип интерфейса (слушатель или буфер)
//  			  version  - версия интерфейса
//  			  data     - указатель на данные для установки
// на выходе   :  успешность установки параметров
//-----------------------------------------------------------------------------
int eax_Set(LPKSPROPERTYSET prop, int type, int version, void* data)
{
	// проверка параметров
	if ((!prop) || (version == 0) || (type > EAX_BUFFER))
		return false;

	// установка параметров
	if (prop->Set(EAX_Guid[type][version],
			  	EAX_Param[type][version],
			  	NULL,
			  	0,
			  	data,
			  	EAX_StructSize[type][version]) != DS_OK)
		return false;

	return true;
}
Example #7
0
//-----------------------------------------------------------------------------
// Проверка возможности чтения и записи
// на входе    :  prop     - указатель на eax интерфейс
//  			  type     - тип интерфейса (слушатель или буфер)
//  			  version  - версия интерфейса
// на выходе   :  успешность возможности чтения и записи
//-----------------------------------------------------------------------------
int eax_TestQuerySupport(LPKSPROPERTYSET prop, int type, int version)
{
	unsigned long support;

	// проверка параметров
	if (!prop)
		return false;

	// проверим поддержку слушателя
	if (prop->QuerySupport(EAX_Guid[type][version],
			  	EAX_Param[type][version],
			  	& support) == DS_OK) {
		// проверка возможности чтения и записи
		if ((support & KSPROPERTY_SUPPORT_GET) &&
			(support & KSPROPERTY_SUPPORT_SET))
			return true;
	}
	return false;
}
Example #8
0
//===========================================================================
// EAXMulf
//	Linear multiplication for a linear property.
//===========================================================================
void EAXMulf(DWORD prop, float mul, float min, float max)
{
	DWORD retBytes;
	float value;

	if(!eaxListener) return;
	if(FAILED(hr = eaxListener->Get(DSPROPSETID_EAX_ListenerProperties,
		prop, NULL, 0, &value, sizeof(value), &retBytes)))
	{
/*		if(!ignore_eax_errors)
			Con_Message("DS_EAXMulf (prop:%i) get failed. Result: %x.\n", 
				prop, hr & 0xffff);*/
		return;
	}
	value *= mul;
	if(value < min) value = min;
	if(value > max) value = max;
	EAXSetf(prop, value);
}
Example #9
0
//-----------------------------------------------------------------------------
// Установка предустановленного eax окружения
// на входе    :  direct   - указатель на объект воспроизведения
//  			  version  - версия интерфейса
// на выходе   :  успешность устаноки окружения
//-----------------------------------------------------------------------------
int eax_TestSupport(LPDIRECTSOUND direct, int version)
{
	// объявление переменных
	WAVEFORMATEX wfx;   		   // формат звука
	DSBUFFERDESC dsbd;  		   // дескриптор
	int ok; 			  // флаг инициализации EAX интерфейса
	LPDIRECTSOUNDBUFFER Buffer;
	LPDIRECTSOUND3DBUFFER Buffer3D;
	LPKSPROPERTYSET ListenerPropSet;
	LPKSPROPERTYSET BufferPropSet;

	// заполним структуру с форматом
	wfx.wFormatTag = 1;
	wfx.nChannels = 2;
	wfx.nSamplesPerSec = 44100;
	wfx.wBitsPerSample = 16;
	wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) >> 3;
	wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
	wfx.cbSize = 0;

	// обнулим параметры
	ok = false;
	Buffer = 0;
	Buffer3D = 0;
	ListenerPropSet = 0;
	BufferPropSet = 0;

	// проверка наличия объекта воспроизведения
	if (direct) {
		// занесение данных вторичного буфера
		ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
		dsbd.dwSize = sizeof(DSBUFFERDESC);
		dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRL3D;
		dsbd.dwBufferBytes = 128;
		dsbd.lpwfxFormat = &wfx;

		// Создание вторичного буфера
		ok = (direct->CreateSoundBuffer(&dsbd, & Buffer, NULL) == DS_OK) ?
			true :
			false;

		// получим интерфейс для работы с EAX слушателем
		if (ok)
			ok = (Buffer->QueryInterface(IID_IKsPropertySet,
						  	(void * *) &ListenerPropSet) == DS_OK) ?
				true :
				false;

		// Создание интерфейса для трехмерного звука
		if (ok)
			ok = (Buffer->QueryInterface(IID_IDirectSound3DBuffer,
						  	(VOID * *) &Buffer3D) == DS_OK) ?
				true :
				false;

		// получение интерфейсов
		ListenerPropSet = eax_GetBufferInterface(Buffer);
		BufferPropSet = eax_GetBuffer3DInterface(Buffer3D);

		// проверка возможности чтения и записи слушателя
		if (ok)
			ok = eax_TestQuerySupport(ListenerPropSet, EAX_LISTENER, version);

		if (ok)
			ok = eax_TestQuerySupport(ListenerPropSet, EAX_BUFFER, version);

		// освободим EAX источник
		if (BufferPropSet) {
			BufferPropSet->Release();
			BufferPropSet = 0;
		}

		// освободим 3D буфер
		if (Buffer3D) {
			Buffer3D->Release();
			Buffer3D = 0;
		}

		// освободим EAX слушателя
		if (ListenerPropSet) {
			ListenerPropSet->Release();
			ListenerPropSet = 0;
		}

		// освободим буфер
		if (Buffer) {
			Buffer->Release();
			Buffer = 0;
		}
	}
	return ok;
}
Example #10
0
//===========================================================================
// DS_Init
//===========================================================================
int DS_Init(void)
{
	HWND				hWnd;
	DSBUFFERDESC		desc;
	LPDIRECTSOUNDBUFFER	bufTemp;

	if(initOk) return true;

	// Are we in verbose mode?	
	if((verbose = ArgExists("-verbose")))
		Con_Message("DS_Init(Compat): Initializing sound driver...\n");

	// Get Doomsday's window handle.
	hWnd = (HWND) DD_GetInteger(DD_WINDOW_HANDLE);

	hr = DS_OK;
	if(ArgExists("-noeax") 
		|| FAILED(hr = EAXDirectSoundCreate(NULL, &dsound, NULL)))
	{
		// EAX can't be initialized. Use normal DS, then.
		if(FAILED(hr)) Error("DS_Init", "EAX 2 couldn't be initialized.");
		if(FAILED(hr = DirectSoundCreate(NULL, &dsound, NULL)))
		{
			Error("DS_Init", "Failed to create dsound interface.");
			return false;
		}
	}
	// Set the cooperative level.
	if(FAILED(hr = dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)))
	{
		Error("DS_Init", "Couldn't set dSound coop level.");
		return false;
	}
	// Get the primary buffer and the listener.
	primary = NULL;
	memset(&desc, 0, sizeof(desc));
	desc.dwSize = sizeof(desc);
	desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
	dsListener = NULL;
	if(SUCCEEDED(dsound->CreateSoundBuffer(&desc, &primary, NULL)))
	{
		// Query the listener interface.
		primary->QueryInterface(IID_IDirectSound3DListener, 
			(void**) &dsListener);
	}
	else
	{
		// Failure; get a 2D primary buffer, then.
		desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
		dsound->CreateSoundBuffer(&desc, &primary, NULL);
	}
	// Start playing the primary buffer.
	if(primary) 
	{
		if(FAILED(hr = primary->Play(0, 0, DSBPLAY_LOOPING)))
			Error("DS_Init", "Can't play primary buffer.");
	}
	
	// Try to get the EAX listener property set. 
	// Create a temporary secondary buffer for it.
	eaxListener = NULL;
	if(SUCCEEDED(CreateDSBuffer(DSBCAPS_STATIC | DSBCAPS_CTRL3D, 
		DSBSIZE_MIN, 22050, 8, 1, &bufTemp)))
	{
		// Now try to get the property set.
		if(SUCCEEDED(hr = bufTemp->QueryInterface(IID_IKsPropertySet, 
			(void**) &eaxListener)))
		{
			DWORD support = 0, revsize = 0;
			// Check for support.
			if(FAILED(hr = eaxListener->QuerySupport(
				DSPROPSETID_EAX_ListenerProperties,
				DSPROPERTY_EAXLISTENER_ENVIRONMENT,
				&support)) 
				|| ((support & NEEDED_SUPPORT) != NEEDED_SUPPORT))
			{
				Error("DS_Init", "Sufficient EAX2 support not present.");
				eaxListener->Release();
				eaxListener = NULL;
			}
			else
			{
				// EAX is supported!
				if(verbose) Con_Message("DS_Init(Compat): EAX2 is available.\n");
			}
		}
		// Release the temporary buffer interface.
		bufTemp->Release();
	}
		
	// Get the caps.
	dsCaps.dwSize = sizeof(dsCaps);
	dsound->GetCaps(&dsCaps);
	if(verbose) Con_Message("DS_Init(Compat): Number of hardware 3D "
		"buffers: %i\n", dsCaps.dwMaxHw3DAllBuffers);

	// Configure the DS3D listener.
	if(dsListener)
	{
		dsListener->SetDistanceFactor(1/36.0f, DS3D_DEFERRED);
		dsListener->SetDopplerFactor(2, DS3D_DEFERRED);
	}

	// Success!
	initOk = true;
	return true;
}
LPKSPROPERTYSET	CSoundDriverDSound::createPropertySet(CSourceDSound *source)
{
	if (_Sources.empty())
		return NULL;

	LPDIRECTSOUND3DBUFFER8 d3dBuffer;
	if (source == NULL)
		d3dBuffer = (*_Sources.begin())->_3DBuffer;
	else
	{
		d3dBuffer = source->_3DBuffer;
	}
	LPKSPROPERTYSET	propertySet;
	d3dBuffer->QueryInterface(IID_IKsPropertySet, (void**) &propertySet);

	// some checking code
	{
		if (propertySet != 0)
		{
			char *listenerProperties[] =
			{
				"DSPROPERTY_EAXLISTENER_NONE",
				"DSPROPERTY_EAXLISTENER_ALLPARAMETERS",
				"DSPROPERTY_EAXLISTENER_ROOM",
				"DSPROPERTY_EAXLISTENER_ROOMHF",
				"DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR",
				"DSPROPERTY_EAXLISTENER_DECAYTIME",
				"DSPROPERTY_EAXLISTENER_DECAYHFRATIO",
				"DSPROPERTY_EAXLISTENER_REFLECTIONS",
				"DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY",
				"DSPROPERTY_EAXLISTENER_REVERB",
				"DSPROPERTY_EAXLISTENER_REVERBDELAY",
				"DSPROPERTY_EAXLISTENER_ENVIRONMENT",
				"DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE",
				"DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION",
				"DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF",
				"DSPROPERTY_EAXLISTENER_FLAGS"
			};
			uint i;
			for (i=DSPROPERTY_EAXLISTENER_NONE; i<= DSPROPERTY_EAXLISTENER_FLAGS; ++i)
			{
				ULONG ulSupport = 0;
				propertySet->QuerySupport(DSPROPSETID_EAX_ListenerProperties, i, &ulSupport);
				if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) != (KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
				{
//					nlwarning("CSoundDriverDSound::createPropertySet : listener property %s not supported", listenerProperties[i]);
				}
			}

			char *bufferProperties[] =
			{
				"DSPROPERTY_EAXBUFFER_NONE",
				"DSPROPERTY_EAXBUFFER_ALLPARAMETERS",
				"DSPROPERTY_EAXBUFFER_DIRECT",
				"DSPROPERTY_EAXBUFFER_DIRECTHF",
				"DSPROPERTY_EAXBUFFER_ROOM",
				"DSPROPERTY_EAXBUFFER_ROOMHF",
				"DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR",
				"DSPROPERTY_EAXBUFFER_OBSTRUCTION",
				"DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO",
				"DSPROPERTY_EAXBUFFER_OCCLUSION",
				"DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO",
				"DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO",
				"DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF",
				"DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR",
				"DSPROPERTY_EAXBUFFER_FLAGS"
			};

			for (i=DSPROPERTY_EAXBUFFER_NONE; i<=DSPROPERTY_EAXBUFFER_FLAGS; ++i)
			{
				ULONG ulSupport = 0;
				propertySet->QuerySupport(DSPROPSETID_EAX_BufferProperties, i, &ulSupport);
				if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) != (KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
				{
//					nlwarning("CSoundDriverDSound::createPropertySet : buffer property %s not supported", bufferProperties[i]);
				}
			}
		}
		else
		{
			nlwarning("CSoundDriverDSound::createPropertySet : propertie set not available !");
		}
	}

	return propertySet;
}
// Given a DirectX device identified by "guid", 
// find the corresponding wave device ID and return it in "waveID".
// Inspired by DirectSoundEnumeratorDlg.cpp on chrisnet.net (via google.com/codesearch) 
HRESULT GetWaveDeviceIDFromGUID(LPGUID lpGUID, DIRECTSOUNDDEVICE_DATAFLOW dataflowType, DWORD* waveID)
{
	HRESULT hr;
	LPKSPROPERTYSET propSet = NULL;
	DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA deviceDescription;
	PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA deviceDescriptionPtr = NULL;
	ULONG ulBytesReturned = 0;

	/* Assume we're going to fail.  If we succeed, this will be overwritten. */
	*waveID = -666;

	/* If we're passed a NULL GUID-ptr, we assume it's on purpose. */
	if (!lpGUID) {
		*waveID = -1;
		return S_OK;
	}

	IClassFactory *factory = dsound_GetClassFactory(CLSID_DirectSoundPrivate);
	if (factory == NULL) {
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID():  cannot obtain class factory\n"));
		hr = CLASS_E_CLASSNOTAVAILABLE;
		goto error;
	}

	hr = factory->CreateInstance(NULL, IID_IKsPropertySet,(LPVOID *)&propSet);
	if (FAILED(hr)) {
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID():  cannot instantiate property-set\n"));
		goto error;
	}

	// An anonymous DirectX team member tipped off Mr. Chrisnet.net that it's
	// necessary to call Get() twice.  Good to know.
	memset(&deviceDescription, 0, sizeof(deviceDescription));
	deviceDescription.DeviceId = *lpGUID;
	deviceDescription.DataFlow = dataflowType;
	deviceDescription.WaveDeviceId = 666; // so we can see if it's changed.
	// On the first call the final size is unknown so pass the size of the struct in order to receive
    // "Type" and "DataFlow" values, ulBytesReturned will be populated with bytes required for struct+strings.
    hr = propSet->Get(DSPROPSETID_DirectSoundDevice,
					DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
					NULL,
					0,
					&deviceDescription,
					sizeof(deviceDescription),
					&ulBytesReturned
				);
	if (FAILED(hr)) {
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID():  property-get 1 failed\n"));
		goto error;
	}
	if (!ulBytesReturned) {
		// I don't know what to make of this situation... why would the return code
		// be successful, but the byte-count be zero?  Oh well, it may never happen.
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID(): failed to get byte-size for description\n"));
		hr = ERROR_INVALID_HANDLE; // not sure what the correct error-value; this is in the ballpark
		goto error;
	}
	// On the first call it notifies us of the required amount of memory in order to receive the strings.
    // Allocate the required memory, the strings will be pointed to the memory space directly after the struct.
	deviceDescriptionPtr = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA)malloc(ulBytesReturned);
	if (!deviceDescriptionPtr) {
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID(): failed to dynamically allocate for description\n"));
		hr = ERROR_NOT_ENOUGH_MEMORY;
		goto error;
	}
	*deviceDescriptionPtr = deviceDescription;
    hr = propSet->Get(DSPROPSETID_DirectSoundDevice,
					DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
					NULL,
					0,
					deviceDescriptionPtr,
					ulBytesReturned,
					&ulBytesReturned
				);
	if (FAILED(hr)) {
		DPRINTF(("ERROR GetWaveDeviceIDFromGUID():  property-get 2 failed\n"));
		goto error;
	}
	
	DPRINTF(("OBTAINED DEVICE INFO: \n\ttype/waveID:  %d/%d\n\tdescription:   %s\n\tmodule:   %s\n\tinterface:   %s\n", deviceDescriptionPtr->Type, deviceDescriptionPtr->WaveDeviceId, deviceDescriptionPtr->Description, deviceDescriptionPtr->Module, deviceDescriptionPtr->Interface));

	// All of that bullshit for one little integer.
	*waveID = deviceDescriptionPtr->WaveDeviceId;
	hr = S_OK;

error:
	if (propSet) { propSet->Release(); }
	if (factory) { factory->Release(); }
	if (deviceDescriptionPtr) { free(deviceDescriptionPtr); }
	return hr; // return the last result, which should be appropriate
}