/* * 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; }
/* * 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; }
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; }