1 //#pragma warning (disable:4201)
\r
3 #define WIN32_LEAN_AND_MEAN
\r
5 #include <mmsystem.h>
\r
9 #include "../common/lprintf.h"
\r
12 #define RELEASE(x) if (x) x->Release(); x=NULL;
\r
14 static LPDIRECTSOUND DSound;
\r
15 static LPDIRECTSOUNDBUFFER LoopBuffer;
\r
16 static LPDIRECTSOUNDNOTIFY DSoundNotify;
\r
17 static HANDLE seg_played_event;
\r
18 static int LoopLen, LoopWrite, LoopSeg; // bytes
\r
20 static int LoopBlank(void)
\r
22 void *mema=NULL,*memb=NULL;
\r
23 DWORD sizea=0,sizeb=0;
\r
25 LoopBuffer->Lock(0, LoopLen, &mema,&sizea, &memb,&sizeb, 0);
\r
27 if (mema) memset(mema,0,sizea);
\r
29 LoopBuffer->Unlock(mema,sizea, memb,sizeb);
\r
34 int DSoundInit(HWND wnd_coop, int rate, int stereo, int seg_samples)
\r
38 DSBPOSITIONNOTIFY notifies[NSEGS];
\r
41 memset(&dsbd,0,sizeof(dsbd));
\r
42 memset(&wfx,0,sizeof(wfx));
\r
44 // Make wave format:
\r
45 wfx.wFormatTag=WAVE_FORMAT_PCM;
\r
46 wfx.nChannels=stereo ? 2 : 1;
\r
47 wfx.nSamplesPerSec=rate;
\r
48 wfx.wBitsPerSample=16;
\r
50 wfx.nBlockAlign=(WORD)((wfx.nChannels*wfx.wBitsPerSample)>>3);
\r
51 wfx.nAvgBytesPerSec=wfx.nBlockAlign*wfx.nSamplesPerSec;
\r
53 // Create the DirectSound interface:
\r
54 DirectSoundCreate(NULL,&DSound,NULL);
\r
55 if (DSound==NULL) return 1;
\r
57 LoopSeg = seg_samples * 2;
\r
61 LoopLen = LoopSeg * NSEGS;
\r
63 DSound->SetCooperativeLevel(wnd_coop, DSSCL_PRIORITY);
\r
64 dsbd.dwFlags=DSBCAPS_GLOBALFOCUS; // Play in background
\r
65 dsbd.dwFlags|=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;
\r
67 // Create the looping buffer:
\r
68 dsbd.dwSize=sizeof(dsbd);
\r
69 dsbd.dwBufferBytes=LoopLen;
\r
70 dsbd.lpwfxFormat=&wfx;
\r
72 DSound->CreateSoundBuffer(&dsbd,&LoopBuffer,NULL);
\r
73 if (LoopBuffer==NULL) return 1;
\r
75 LoopBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&DSoundNotify);
\r
76 if (DSoundNotify == NULL) {
\r
77 lprintf("QueryInterface(IID_IDirectSoundNotify) failed\n");
\r
81 seg_played_event = CreateEvent(NULL, 0, 0, NULL);
\r
82 if (seg_played_event == NULL)
\r
85 for (i = 0; i < NSEGS; i++) {
\r
86 notifies[i].dwOffset = i * LoopSeg;
\r
87 notifies[i].hEventNotify = seg_played_event;
\r
89 i = DSoundNotify->SetNotificationPositions(NSEGS, notifies);
\r
91 lprintf("SetNotificationPositions failed\n");
\r
97 LoopBuffer->Play(0, 0, DSBPLAY_LOOPING);
\r
101 void DSoundExit(void)
\r
104 LoopBuffer->Stop();
\r
105 RELEASE(DSoundNotify);
\r
106 RELEASE(LoopBuffer)
\r
108 CloseHandle(seg_played_event);
\r
109 seg_played_event = NULL;
\r
112 static int WriteSeg(const void *buff)
\r
114 void *mema=NULL,*memb=NULL;
\r
115 DWORD sizea=0,sizeb=0;
\r
118 // Lock the segment at 'LoopWrite' and copy the next segment in
\r
119 ret = LoopBuffer->Lock(LoopWrite, LoopSeg, &mema, &sizea, &memb, &sizeb, 0);
\r
121 lprintf("LoopBuffer->Lock() failed: %i\n", ret);
\r
123 if (mema) memcpy(mema,buff,sizea);
\r
124 // if (memb) memcpy(memb,DSoundNext+sizea,sizeb);
\r
125 if (sizeb != 0) lprintf("sizeb is not 0! (%i)\n", sizeb);
\r
127 ret = LoopBuffer->Unlock(mema,sizea, memb, sizeb);
\r
129 lprintf("LoopBuffer->Unlock() failed: %i\n", ret);
\r
134 int DSoundUpdate(const void *buff, int blocking)
\r
139 LoopBuffer->GetCurrentPosition(&play, NULL);
\r
142 // 'LoopWrite' is the next seg in the loop that we want to write
\r
143 // First check that the sound 'play' pointer has moved out of it:
\r
145 while (LoopWrite <= pos && pos < LoopWrite + LoopSeg) {
\r
146 WaitForSingleObject(seg_played_event, 5000);
\r
147 LoopBuffer->GetCurrentPosition(&play, NULL);
\r
152 if (LoopWrite <= pos && pos < LoopWrite + LoopSeg)
\r
158 // Advance LoopWrite to next seg:
\r
159 LoopWrite += LoopSeg;
\r
160 if (LoopWrite + LoopSeg > LoopLen)
\r