--- /dev/null
+//#pragma warning (disable:4201)\r
+#include <stdlib.h>\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+#include <mmsystem.h>\r
+#include <dsound.h>\r
+\r
+#include "dsnd.h"\r
+#include "../common/lprintf.h"\r
+\r
+#define NSEGS 4\r
+#define RELEASE(x) if (x) x->Release(); x=NULL;\r
+\r
+static LPDIRECTSOUND DSound;\r
+static LPDIRECTSOUNDBUFFER LoopBuffer;\r
+static LPDIRECTSOUNDNOTIFY DSoundNotify;\r
+static HANDLE seg_played_event;\r
+static int LoopLen, LoopWrite, LoopSeg; // bytes\r
+\r
+static int LoopBlank(void)\r
+{\r
+ void *mema=NULL,*memb=NULL;\r
+ DWORD sizea=0,sizeb=0;\r
+\r
+ LoopBuffer->Lock(0, LoopLen, &mema,&sizea, &memb,&sizeb, 0);\r
+ \r
+ if (mema) memset(mema,0,sizea);\r
+\r
+ LoopBuffer->Unlock(mema,sizea, memb,sizeb);\r
+\r
+ return 0;\r
+}\r
+\r
+int DSoundInit(HWND wnd_coop, int rate, int stereo, int seg_samples)\r
+{\r
+ DSBUFFERDESC dsbd;\r
+ WAVEFORMATEX wfx;\r
+ DSBPOSITIONNOTIFY notifies[NSEGS];\r
+ int i;\r
+\r
+ memset(&dsbd,0,sizeof(dsbd));\r
+ memset(&wfx,0,sizeof(wfx));\r
+\r
+ // Make wave format:\r
+ wfx.wFormatTag=WAVE_FORMAT_PCM;\r
+ wfx.nChannels=stereo ? 2 : 1;\r
+ wfx.nSamplesPerSec=rate;\r
+ wfx.wBitsPerSample=16;\r
+\r
+ wfx.nBlockAlign=(WORD)((wfx.nChannels*wfx.wBitsPerSample)>>3);\r
+ wfx.nAvgBytesPerSec=wfx.nBlockAlign*wfx.nSamplesPerSec;\r
+\r
+ // Create the DirectSound interface:\r
+ DirectSoundCreate(NULL,&DSound,NULL);\r
+ if (DSound==NULL) return 1;\r
+\r
+ LoopSeg = seg_samples * 2;\r
+ if (stereo)\r
+ LoopSeg *= 2;\r
+\r
+ LoopLen = LoopSeg * NSEGS;\r
+\r
+ DSound->SetCooperativeLevel(wnd_coop, DSSCL_PRIORITY);\r
+ dsbd.dwFlags=DSBCAPS_GLOBALFOCUS; // Play in background\r
+ dsbd.dwFlags|=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;\r
+\r
+ // Create the looping buffer:\r
+ dsbd.dwSize=sizeof(dsbd);\r
+ dsbd.dwBufferBytes=LoopLen;\r
+ dsbd.lpwfxFormat=&wfx;\r
+\r
+ DSound->CreateSoundBuffer(&dsbd,&LoopBuffer,NULL);\r
+ if (LoopBuffer==NULL) return 1;\r
+\r
+ LoopBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&DSoundNotify);\r
+ if (DSoundNotify == NULL) {\r
+ lprintf("QueryInterface(IID_IDirectSoundNotify) failed\n");\r
+ goto out;\r
+ }\r
+\r
+ seg_played_event = CreateEvent(NULL, 0, 0, NULL);\r
+ if (seg_played_event == NULL)\r
+ goto out;\r
+\r
+ for (i = 0; i < NSEGS; i++) {\r
+ notifies[i].dwOffset = i * LoopSeg;\r
+ notifies[i].hEventNotify = seg_played_event;\r
+ }\r
+ i = DSoundNotify->SetNotificationPositions(NSEGS, notifies);\r
+ if (i != DS_OK) {\r
+ lprintf("SetNotificationPositions failed\n");\r
+ goto out;\r
+ }\r
+\r
+out:\r
+ LoopBlank();\r
+ LoopBuffer->Play(0, 0, DSBPLAY_LOOPING);\r
+ return 0;\r
+}\r
+\r
+void DSoundExit(void)\r
+{\r
+ if (LoopBuffer)\r
+ LoopBuffer->Stop();\r
+ RELEASE(DSoundNotify);\r
+ RELEASE(LoopBuffer)\r
+ RELEASE(DSound)\r
+ CloseHandle(seg_played_event);\r
+ seg_played_event = NULL;\r
+}\r
+\r
+static int WriteSeg(const void *buff)\r
+{\r
+ void *mema=NULL,*memb=NULL;\r
+ DWORD sizea=0,sizeb=0;\r
+ int ret;\r
+\r
+ // Lock the segment at 'LoopWrite' and copy the next segment in\r
+ ret = LoopBuffer->Lock(LoopWrite, LoopSeg, &mema, &sizea, &memb, &sizeb, 0);\r
+ if (ret != DS_OK)\r
+ lprintf("LoopBuffer->Lock() failed: %i\n", ret);\r
+\r
+ if (mema) memcpy(mema,buff,sizea);\r
+// if (memb) memcpy(memb,DSoundNext+sizea,sizeb);\r
+ if (sizeb != 0) lprintf("sizeb is not 0! (%i)\n", sizeb);\r
+\r
+ ret = LoopBuffer->Unlock(mema,sizea, memb, sizeb);\r
+ if (ret != DS_OK)\r
+ lprintf("LoopBuffer->Unlock() failed: %i\n", ret);\r
+\r
+ return 0;\r
+}\r
+\r
+int DSoundUpdate(const void *buff, int blocking)\r
+{\r
+ DWORD play = 0;\r
+ int pos;\r
+\r
+ LoopBuffer->GetCurrentPosition(&play, NULL);\r
+ pos = play;\r
+\r
+ // 'LoopWrite' is the next seg in the loop that we want to write\r
+ // First check that the sound 'play' pointer has moved out of it:\r
+ if (blocking) {\r
+ while (LoopWrite <= pos && pos < LoopWrite + LoopSeg) {\r
+ WaitForSingleObject(seg_played_event, 5000);\r
+ LoopBuffer->GetCurrentPosition(&play, NULL);\r
+ pos = play;\r
+ }\r
+ }\r
+ else {\r
+ if (LoopWrite <= pos && pos < LoopWrite + LoopSeg)\r
+ return 1;\r
+ }\r
+\r
+ WriteSeg(buff);\r
+\r
+ // Advance LoopWrite to next seg:\r
+ LoopWrite += LoopSeg;\r
+ if (LoopWrite + LoopSeg > LoopLen)\r
+ LoopWrite = 0;\r
+\r
+ return 0;\r
+}\r
+\r