Esempio n. 1
0
/*
 * DSOUND_Init
 * Initializes the DirectSound objects.
 */
int DSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize)
{
	HRESULT (WINAPI *aDirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
	HRESULT hr;
	DSBUFFERDESC dsbuf;
	WAVEFORMATEX wfex;
	DSBPOSITIONNOTIFY posn;
	
	if (DSOUND_Installed) {
		DSOUND_Shutdown();
	}

	printOSD("Initializing DirectSound...\n");
	
	if (!_DSOUND_CriticalSectionAlloced) {
		// initialize the critical section object we'll use to
		// simulate (dis|en)abling interrupts
		InitializeCriticalSection(&mutex);
		_DSOUND_CriticalSectionAlloced = TRUE;
	}

	printOSD("  - Loading DSOUND.DLL\n");
	hDSoundDLL = LoadLibrary("DSOUND.DLL");
	if (!hDSoundDLL) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_NoDLL);
		return DSOUND_Error;
	}

	aDirectSoundCreate = (void *)GetProcAddress(hDSoundDLL, "DirectSoundCreate");
	if (!aDirectSoundCreate) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_NoDirectSoundCreate);
		return DSOUND_Error;
	}

	printOSD("  - Creating DirectSound object\n");
	hr = aDirectSoundCreate(NULL, &lpDS, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedDSC);
		return DSOUND_Error;
	}

	hr = IDirectSound_SetCooperativeLevel(lpDS, (HWND)win_gethwnd(), DSSCL_EXCLUSIVE);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetCoopLevel);
		return DSOUND_Error;
	}

	printOSD("  - Creating primary buffer\n");
	ZeroMemory(&dsbuf, sizeof(dsbuf));
	dsbuf.dwSize = sizeof(DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
	hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBPrimary, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreatePrimary);
		return DSOUND_Error;
	}

	printOSD("  - Setting primary buffer format\n"
	         "      Channels:    %d\n"
		 "      Sample rate: %dHz\n"
		 "      Sample size: %d bits\n",
		 numchannels, mixrate, samplebits);
	ZeroMemory(&wfex, sizeof(wfex));
	wfex.wFormatTag      = WAVE_FORMAT_PCM;
	wfex.nChannels       = numchannels;
	wfex.nSamplesPerSec  = mixrate;
	wfex.wBitsPerSample  = samplebits;
	wfex.nBlockAlign     = (wfex.wBitsPerSample / 8) * wfex.nChannels;
	wfex.nAvgBytesPerSec = wfex.nBlockAlign * wfex.nSamplesPerSec;
	hr = IDirectSoundBuffer_SetFormat(lpDSBPrimary, &wfex);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetFormat);
		return DSOUND_Error;
	}

	printOSD("  - Creating secondary buffer\n");
	ZeroMemory(&dsbuf, sizeof(dsbuf));
	dsbuf.dwSize = sizeof(DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
	dsbuf.dwBufferBytes = buffersize;
	dsbuf.lpwfxFormat = &wfex;
	hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBSecondary, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreateSecondary);
		return DSOUND_Error;
	}

	hr = IDirectSoundBuffer_QueryInterface(lpDSBSecondary, &IID_IDirectSoundNotify, &lpDSNotify);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedQueryNotify);
		return DSOUND_Error;
	}

	hPosNotify = (HANDLE *)malloc(sizeof(HANDLE));
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}
	
	hPosNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreateNotifyEvent);
		return DSOUND_Error;
	}

	_DSOUND_BufferLength = 0;
	_DSOUND_NumBuffers   = 1;
	posn.dwOffset = 0;
	posn.hEventNotify = hPosNotify[0];

	hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, 1, &posn);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	DSOUND_Installed = TRUE;
	
	DSOUND_SetErrorCode(DSOUND_Ok);
	return DSOUND_Ok;
}
Esempio n. 2
0
/*
 * DSOUND_BeginBufferedPlayback
 * Spins off a thread that behaves somewhat like the SoundBlaster DMA ISR did.
 */
int DSOUND_BeginBufferedPlayback(char *BufferStart, int (*CallBackFunc)(int), int buffersize, int numdivisions)
{
	DWORD threadid;
	HRESULT hr;
	DSBPOSITIONNOTIFY *posns;
	int i;
	
	_DSOUND_CallBack = CallBackFunc;
	_DSOUND_MixBuffer = BufferStart;

	if (!lpDSBSecondary) return DSOUND_Error;

	if (isrthread) {
		DSOUND_StopPlayback();
	}
	
	isrfinish = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (!isrfinish) {
		DSOUND_SetErrorCode(DSOUND_FailedCreateFinishEvent);
		return DSOUND_Error;
	}
	
	isrthread = CreateThread(NULL, 0, isr, NULL, CREATE_SUSPENDED, &threadid);
	if (!isrthread) {
		DSOUND_SetErrorCode(DSOUND_FailedCreateThread);
		return DSOUND_Error;
	}

	hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)*numdivisions);
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}
	
	memset(hPosNotify, 0, sizeof(HANDLE)*numdivisions);
	for (i=0; i<numdivisions; i++) {
		hPosNotify[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (!hPosNotify[i]) {
			DSOUND_Shutdown();
			DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
			return DSOUND_Error;
		}
	}

	posns = (LPDSBPOSITIONNOTIFY)malloc(sizeof(DSBPOSITIONNOTIFY)*numdivisions);
	if (!posns) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	_DSOUND_BufferLength = buffersize/numdivisions;
	_DSOUND_NumBuffers   = numdivisions;
	for (i=0; i<numdivisions; i++) {
		posns[i].dwOffset = i*_DSOUND_BufferLength;
		posns[i].hEventNotify = hPosNotify[i];
	}

	hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, numdivisions, posns);
	if (hr != DS_OK) {
		free(posns);
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	free(posns);

	SetThreadPriority(isrthread, THREAD_PRIORITY_ABOVE_NORMAL);
	ResumeThread(isrthread);

	hr = IDirectSoundBuffer_Play(lpDSBSecondary, 0, 0, DSBPLAY_LOOPING);
	if (hr != DS_OK) {
		DSOUND_SetErrorCode(DSOUND_FailedPlaySecondary);
		return DSOUND_Error;
	}

	return DSOUND_Ok;
}
Esempio n. 3
0
soundplay_t *SND_InitPlayback(int speed, int bits)
{
	int ret;
	DSBCAPS caps;
	DSBUFFERDESC bufdesc;
	LPDIRECTSOUND ds;
	dsplay_t *hnd;
	WAVEFORMATEX	format; 

	if (!hInstDS)
	{
		hInstDS = LoadLibrary("dsound.dll");
		
		if (hInstDS == NULL)
		{
			printf ("Couldn't load dsound.dll\n");
			return NULL;
		}

		pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");

		if (!pDirectSoundCreate)
		{
			printf ("Couldn't get DS proc addr\n");
			return NULL;
		}
				
//		pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA");
	}

	ds = NULL;
	pDirectSoundCreate(NULL, &ds, NULL);

	if (!ds)
		return NULL;
	hnd = malloc(sizeof(*hnd));
	memset(hnd, 0, sizeof(*hnd));

	hnd->funcs.update = DSOUND_UpdatePlayback;
	hnd->funcs.close = DSOUND_Shutdown;

	hnd->ds = ds;
	hnd->sampbytes = bits/8;

	if (FAILED(IDirectSound_SetCooperativeLevel (hnd->ds, GetDesktopWindow(), DSSCL_EXCLUSIVE)))
		printf("SetCooperativeLevel failed\n");

	memset(&bufdesc, 0, sizeof(bufdesc));
	bufdesc.dwSize = sizeof(bufdesc);
//	bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS;	//so we hear it if quake is loaded
	bufdesc.dwFlags |= DSBCAPS_PRIMARYBUFFER; //so we can set speed
	bufdesc.dwFlags |= DSBCAPS_CTRLVOLUME;
	bufdesc.lpwfxFormat = NULL;
	bufdesc.dwBufferBytes = 0;

	format.wFormatTag = WAVE_FORMAT_PCM;
	format.cbSize = 0;

	format.nChannels = 1;
    format.wBitsPerSample = bits;
    format.nSamplesPerSec = speed;
    format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
    format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;

	ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);

	if (!hnd->dsbuf)
	{
		printf("Couldn't create primary buffer\n");
		DSOUND_Shutdown(&hnd->funcs);
		return NULL;
	}

	if (FAILED(IDirectSoundBuffer_SetFormat(hnd->dsbuf, &format)))
		printf("SetFormat failed\n");

	//and now make a secondary buffer
	bufdesc.dwFlags = 0;
	bufdesc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
	bufdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
	bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS;
	bufdesc.dwBufferBytes = speed * format.nChannels * hnd->sampbytes;
	bufdesc.lpwfxFormat = &format;

	ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);
	if (!hnd->dsbuf)
	{
		printf("Couldn't create secondary buffer\n");
		DSOUND_Shutdown(&hnd->funcs);
		return NULL;
	}








	memset(&caps, 0, sizeof(caps));
	caps.dwSize = sizeof(caps);
	IDirectSoundBuffer_GetCaps(hnd->dsbuf, &caps);
	hnd->buffersize = caps.dwBufferBytes / hnd->sampbytes;

	//clear out the buffer
	{
		char *buffer;
		int buffersize=0;
		IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
		ret = IDirectSoundBuffer_Lock(hnd->dsbuf, 0, hnd->buffersize*hnd->sampbytes, (void**)&buffer, &buffersize, NULL, NULL, 0);
		memset(buffer, 0, buffersize);
		IDirectSoundBuffer_Unlock(hnd->dsbuf, buffer, buffersize, NULL, 0);
		IDirectSoundBuffer_Stop(hnd->dsbuf);
	}
//DSERR_INVALIDPARAM
	IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
	

	IDirectSoundBuffer_GetCurrentPosition(hnd->dsbuf, &hnd->readpos, &hnd->writepos);

	hnd->writepos = hnd->readpos + speed / 2;	//position our write position a quater of a second infront of the read position

	printf("%i %i\n", 100*hnd->readpos / hnd->buffersize, 100*hnd->writepos / hnd->buffersize);

	return &hnd->funcs;
}