rlm@1
|
1 #include "stdafx.h"
|
rlm@1
|
2 #include <mmreg.h>
|
rlm@1
|
3 #include <dsound.h>
|
rlm@1
|
4
|
rlm@1
|
5 #include "resource.h"
|
rlm@1
|
6 #include "AVIWrite.h"
|
rlm@1
|
7 #include "Sound.h"
|
rlm@1
|
8 #include "WavWriter.h"
|
rlm@1
|
9 #include "VBA.h"
|
rlm@1
|
10
|
rlm@1
|
11 #include "../gba/GBAGlobals.h"
|
rlm@1
|
12 #include "../gba/GBASound.h"
|
rlm@1
|
13 #include "../common/nesvideos-piece.h"
|
rlm@1
|
14
|
rlm@1
|
15 extern void directXMessage(const char *);
|
rlm@1
|
16
|
rlm@1
|
17 class DirectSound : public ISound
|
rlm@1
|
18 {
|
rlm@1
|
19 private:
|
rlm@1
|
20 HINSTANCE dsoundDLL;
|
rlm@1
|
21 LPDIRECTSOUND pDirectSound;
|
rlm@1
|
22 LPDIRECTSOUNDBUFFER dsbPrimary;
|
rlm@1
|
23 LPDIRECTSOUNDBUFFER dsbSecondary;
|
rlm@1
|
24 LPDIRECTSOUNDNOTIFY dsbNotify;
|
rlm@1
|
25 HANDLE dsbEvent;
|
rlm@1
|
26 WAVEFORMATEX wfx;
|
rlm@1
|
27 float curRate;
|
rlm@1
|
28 public:
|
rlm@1
|
29 DirectSound();
|
rlm@1
|
30 virtual ~DirectSound();
|
rlm@1
|
31
|
rlm@1
|
32 bool init();
|
rlm@1
|
33 void pause();
|
rlm@1
|
34 void reset();
|
rlm@1
|
35 void resume();
|
rlm@1
|
36 void write();
|
rlm@1
|
37 void setSpeed(float rate);
|
rlm@1
|
38 bool isPlaying();
|
rlm@1
|
39 void clearAudioBuffer();
|
rlm@1
|
40 };
|
rlm@1
|
41
|
rlm@1
|
42 DirectSound::DirectSound()
|
rlm@1
|
43 {
|
rlm@1
|
44 dsoundDLL = NULL;
|
rlm@1
|
45 pDirectSound = NULL;
|
rlm@1
|
46 dsbPrimary = NULL;
|
rlm@1
|
47 dsbSecondary = NULL;
|
rlm@1
|
48 dsbNotify = NULL;
|
rlm@1
|
49 dsbEvent = NULL;
|
rlm@1
|
50 }
|
rlm@1
|
51
|
rlm@1
|
52 DirectSound::~DirectSound()
|
rlm@1
|
53 {
|
rlm@1
|
54 if (theApp.aviRecorder != NULL)
|
rlm@1
|
55 {
|
rlm@1
|
56 delete theApp.aviRecorder;
|
rlm@1
|
57 theApp.aviRecorder = NULL;
|
rlm@1
|
58 theApp.aviRecording = false;
|
rlm@1
|
59 }
|
rlm@1
|
60
|
rlm@1
|
61 if (theApp.soundRecording)
|
rlm@1
|
62 {
|
rlm@1
|
63 if (theApp.soundRecorder != NULL)
|
rlm@1
|
64 {
|
rlm@1
|
65 delete theApp.soundRecorder;
|
rlm@1
|
66 theApp.soundRecorder = NULL;
|
rlm@1
|
67 }
|
rlm@1
|
68 theApp.soundRecording = false;
|
rlm@1
|
69 }
|
rlm@1
|
70
|
rlm@1
|
71 if (dsbNotify != NULL)
|
rlm@1
|
72 {
|
rlm@1
|
73 dsbNotify->Release();
|
rlm@1
|
74 dsbNotify = NULL;
|
rlm@1
|
75 }
|
rlm@1
|
76
|
rlm@1
|
77 if (dsbEvent != NULL)
|
rlm@1
|
78 {
|
rlm@1
|
79 CloseHandle(dsbEvent);
|
rlm@1
|
80 dsbEvent = NULL;
|
rlm@1
|
81 }
|
rlm@1
|
82
|
rlm@1
|
83 if (pDirectSound != NULL)
|
rlm@1
|
84 {
|
rlm@1
|
85 if (dsbPrimary != NULL)
|
rlm@1
|
86 {
|
rlm@1
|
87 dsbPrimary->Release();
|
rlm@1
|
88 dsbPrimary = NULL;
|
rlm@1
|
89 }
|
rlm@1
|
90
|
rlm@1
|
91 if (dsbSecondary != NULL)
|
rlm@1
|
92 {
|
rlm@1
|
93 dsbSecondary->Release();
|
rlm@1
|
94 dsbSecondary = NULL;
|
rlm@1
|
95 }
|
rlm@1
|
96
|
rlm@1
|
97 pDirectSound->Release();
|
rlm@1
|
98 pDirectSound = NULL;
|
rlm@1
|
99 }
|
rlm@1
|
100
|
rlm@1
|
101 if (dsoundDLL != NULL)
|
rlm@1
|
102 {
|
rlm@1
|
103 FreeLibrary(dsoundDLL);
|
rlm@1
|
104 dsoundDLL = NULL;
|
rlm@1
|
105 }
|
rlm@1
|
106 }
|
rlm@1
|
107
|
rlm@1
|
108 bool DirectSound::init()
|
rlm@1
|
109 {
|
rlm@1
|
110 HRESULT hr;
|
rlm@1
|
111
|
rlm@1
|
112 dsoundDLL = LoadLibrary("DSOUND.DLL");
|
rlm@1
|
113 HRESULT (WINAPI *DSoundCreate)(LPCGUID, LPDIRECTSOUND *, IUnknown *);
|
rlm@1
|
114 if (dsoundDLL != NULL)
|
rlm@1
|
115 {
|
rlm@1
|
116 DSoundCreate = (HRESULT (WINAPI *)(LPCGUID, LPDIRECTSOUND *, IUnknown *))
|
rlm@1
|
117 GetProcAddress(dsoundDLL, "DirectSoundCreate");
|
rlm@1
|
118
|
rlm@1
|
119 if (DSoundCreate == NULL)
|
rlm@1
|
120 {
|
rlm@1
|
121 directXMessage("DirectSoundCreate");
|
rlm@1
|
122 return false;
|
rlm@1
|
123 }
|
rlm@1
|
124 }
|
rlm@1
|
125 else
|
rlm@1
|
126 {
|
rlm@1
|
127 directXMessage("DSOUND.DLL");
|
rlm@1
|
128 return false;
|
rlm@1
|
129 }
|
rlm@1
|
130
|
rlm@1
|
131 if (FAILED(hr = DSoundCreate(NULL, &pDirectSound, NULL)))
|
rlm@1
|
132 {
|
rlm@1
|
133 // errorMessage(myLoadString(IDS_ERROR_SOUND_CREATE), hr);
|
rlm@1
|
134 systemMessage(IDS_CANNOT_CREATE_DIRECTSOUND,
|
rlm@1
|
135 "Cannot create DirectSound %08x", hr);
|
rlm@1
|
136 pDirectSound = NULL;
|
rlm@1
|
137 dsbSecondary = NULL;
|
rlm@1
|
138 return false;
|
rlm@1
|
139 }
|
rlm@1
|
140
|
rlm@1
|
141 if (FAILED(hr = pDirectSound->SetCooperativeLevel((HWND)*theApp.m_pMainWnd, DSSCL_EXCLUSIVE)))
|
rlm@1
|
142 {
|
rlm@1
|
143 // errorMessage(myLoadString(IDS_ERROR_SOUND_LEVEL), hr);
|
rlm@1
|
144 systemMessage(IDS_CANNOT_SETCOOPERATIVELEVEL,
|
rlm@1
|
145 "Cannot SetCooperativeLevel %08x", hr);
|
rlm@1
|
146 return false;
|
rlm@1
|
147 }
|
rlm@1
|
148
|
rlm@1
|
149 DSBUFFERDESC dsbdesc;
|
rlm@1
|
150 ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
|
rlm@1
|
151 dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
rlm@1
|
152 dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
rlm@1
|
153
|
rlm@1
|
154 if (FAILED(hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbPrimary, NULL)))
|
rlm@1
|
155 {
|
rlm@1
|
156 // errorMessage(myLoadString(IDS_ERROR_SOUND_BUFFER),hr);
|
rlm@1
|
157 systemMessage(IDS_CANNOT_CREATESOUNDBUFFER,
|
rlm@1
|
158 "Cannot CreateSoundBuffer %08x", hr);
|
rlm@1
|
159 return false;
|
rlm@1
|
160 }
|
rlm@1
|
161
|
rlm@1
|
162 // Set primary buffer format
|
rlm@1
|
163
|
rlm@1
|
164 memset(&wfx, 0, sizeof(WAVEFORMATEX));
|
rlm@1
|
165 wfx.wFormatTag = WAVE_FORMAT_PCM;
|
rlm@1
|
166 wfx.nChannels = 2;
|
rlm@1
|
167 switch (soundQuality)
|
rlm@1
|
168 {
|
rlm@1
|
169 case 2:
|
rlm@1
|
170 wfx.nSamplesPerSec = 22050;
|
rlm@1
|
171 soundBufferLen = 736 * 2;
|
rlm@1
|
172 soundBufferTotalLen = 7360 * 2;
|
rlm@1
|
173 break;
|
rlm@1
|
174 case 4:
|
rlm@1
|
175 wfx.nSamplesPerSec = 11025;
|
rlm@1
|
176 soundBufferLen = 368 * 2;
|
rlm@1
|
177 soundBufferTotalLen = 3680 * 2;
|
rlm@1
|
178 break;
|
rlm@1
|
179 default:
|
rlm@1
|
180 soundQuality = 1;
|
rlm@1
|
181 wfx.nSamplesPerSec = 44100;
|
rlm@1
|
182 soundBufferLen = 1470 * 2;
|
rlm@1
|
183 soundBufferTotalLen = 14700 * 2;
|
rlm@1
|
184 }
|
rlm@1
|
185 wfx.wBitsPerSample = 16;
|
rlm@1
|
186 wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels;
|
rlm@1
|
187 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
rlm@1
|
188
|
rlm@1
|
189 if (FAILED(hr = dsbPrimary->SetFormat(&wfx)))
|
rlm@1
|
190 {
|
rlm@1
|
191 // errorMessage(myLoadString(IDS_ERROR_SOUND_PRIMARY),hr);
|
rlm@1
|
192 systemMessage(IDS_CANNOT_SETFORMAT_PRIMARY,
|
rlm@1
|
193 "Cannot SetFormat for primary %08x", hr);
|
rlm@1
|
194 return false;
|
rlm@1
|
195 }
|
rlm@1
|
196
|
rlm@1
|
197 ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
|
rlm@1
|
198 dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
rlm@1
|
199 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS;
|
rlm@1
|
200 dsbdesc.dwBufferBytes = soundBufferTotalLen;
|
rlm@1
|
201 dsbdesc.lpwfxFormat = &wfx;
|
rlm@1
|
202
|
rlm@1
|
203 if (FAILED(hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL)))
|
rlm@1
|
204 {
|
rlm@1
|
205 bool ok = false;
|
rlm@1
|
206 while (dsbdesc.dwFlags != DSBCAPS_GETCURRENTPOSITION2)
|
rlm@1
|
207 {
|
rlm@1
|
208 if (dsbdesc.dwFlags & DSBCAPS_CTRLFREQUENCY)
|
rlm@1
|
209 dsbdesc.dwFlags ^= DSBCAPS_CTRLFREQUENCY;
|
rlm@1
|
210 else if (dsbdesc.dwFlags & DSBCAPS_GLOBALFOCUS)
|
rlm@1
|
211 dsbdesc.dwFlags ^= DSBCAPS_GLOBALFOCUS;
|
rlm@1
|
212 else if (dsbdesc.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY)
|
rlm@1
|
213 dsbdesc.dwFlags ^= DSBCAPS_CTRLPOSITIONNOTIFY;
|
rlm@1
|
214 if (SUCCEEDED(hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL)))
|
rlm@1
|
215 {
|
rlm@1
|
216 ok = true;
|
rlm@1
|
217 break;
|
rlm@1
|
218 }
|
rlm@1
|
219 }
|
rlm@1
|
220 if (!ok)
|
rlm@1
|
221 {
|
rlm@1
|
222 systemMessage(IDS_CANNOT_CREATESOUNDBUFFER_SEC, "Cannot CreateSoundBuffer secondary %08x", hr);
|
rlm@1
|
223 return false;
|
rlm@1
|
224 }
|
rlm@1
|
225
|
rlm@1
|
226 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
rlm@1
|
227 }
|
rlm@1
|
228
|
rlm@1
|
229 dsbSecondary->SetCurrentPosition(0);
|
rlm@1
|
230
|
rlm@1
|
231 if (!theApp.useOldSync)
|
rlm@1
|
232 {
|
rlm@1
|
233 hr = dsbSecondary->QueryInterface(IID_IDirectSoundNotify,
|
rlm@1
|
234 (void * *)&dsbNotify);
|
rlm@1
|
235 if (!FAILED(hr))
|
rlm@1
|
236 {
|
rlm@1
|
237 dsbEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
rlm@1
|
238
|
rlm@1
|
239 DSBPOSITIONNOTIFY notify[10];
|
rlm@1
|
240
|
rlm@1
|
241 for (int i = 0; i < 10; i++)
|
rlm@1
|
242 {
|
rlm@1
|
243 notify[i].dwOffset = i * soundBufferLen;
|
rlm@1
|
244 notify[i].hEventNotify = dsbEvent;
|
rlm@1
|
245 }
|
rlm@1
|
246 if (FAILED(dsbNotify->SetNotificationPositions(10, notify)))
|
rlm@1
|
247 {
|
rlm@1
|
248 dsbNotify->Release();
|
rlm@1
|
249 dsbNotify = NULL;
|
rlm@1
|
250 CloseHandle(dsbEvent);
|
rlm@1
|
251 dsbEvent = NULL;
|
rlm@1
|
252 }
|
rlm@1
|
253 }
|
rlm@1
|
254 }
|
rlm@1
|
255
|
rlm@1
|
256 hr = dsbPrimary->Play(0, 0, DSBPLAY_LOOPING);
|
rlm@1
|
257
|
rlm@1
|
258 if (FAILED(hr))
|
rlm@1
|
259 {
|
rlm@1
|
260 // errorMessage(myLoadString(IDS_ERROR_SOUND_PLAYPRIM), hr);
|
rlm@1
|
261 systemMessage(IDS_CANNOT_PLAY_PRIMARY, "Cannot Play primary %08x", hr);
|
rlm@1
|
262 return false;
|
rlm@1
|
263 }
|
rlm@1
|
264
|
rlm@1
|
265 systemSoundOn = true;
|
rlm@1
|
266
|
rlm@1
|
267 return true;
|
rlm@1
|
268 }
|
rlm@1
|
269
|
rlm@1
|
270 void DirectSound::setSpeed(float rate)
|
rlm@1
|
271 {
|
rlm@1
|
272 if (dsbSecondary == NULL || wfx.nSamplesPerSec <= 0)
|
rlm@1
|
273 return;
|
rlm@1
|
274
|
rlm@1
|
275 if (rate != curRate)
|
rlm@1
|
276 {
|
rlm@1
|
277 curRate = rate;
|
rlm@1
|
278
|
rlm@1
|
279 if (rate > 4.0f)
|
rlm@1
|
280 rate = 4.0f;
|
rlm@1
|
281 if (rate < 0.06f)
|
rlm@1
|
282 rate = 0.06f;
|
rlm@1
|
283
|
rlm@1
|
284 dsbSecondary->SetFrequency((DWORD)((float)wfx.nSamplesPerSec * rate));
|
rlm@1
|
285 }
|
rlm@1
|
286 }
|
rlm@1
|
287
|
rlm@1
|
288 void DirectSound::pause()
|
rlm@1
|
289 {
|
rlm@1
|
290 if (dsbSecondary != NULL)
|
rlm@1
|
291 {
|
rlm@1
|
292 DWORD status = 0;
|
rlm@1
|
293 dsbSecondary->GetStatus(&status);
|
rlm@1
|
294
|
rlm@1
|
295 if (status & DSBSTATUS_PLAYING)
|
rlm@1
|
296 {
|
rlm@1
|
297 //systemScreenMessage("sound stopped (pause)!", 3);
|
rlm@1
|
298 dsbSecondary->Stop();
|
rlm@1
|
299 }
|
rlm@1
|
300 }
|
rlm@1
|
301 }
|
rlm@1
|
302
|
rlm@1
|
303 bool DirectSound::isPlaying()
|
rlm@1
|
304 {
|
rlm@1
|
305 if (dsbSecondary != NULL)
|
rlm@1
|
306 {
|
rlm@1
|
307 DWORD status = 0;
|
rlm@1
|
308 dsbSecondary->GetStatus(&status);
|
rlm@1
|
309
|
rlm@1
|
310 if (status & DSBSTATUS_PLAYING)
|
rlm@1
|
311 {
|
rlm@1
|
312 return true;
|
rlm@1
|
313 }
|
rlm@1
|
314 }
|
rlm@1
|
315 return false;
|
rlm@1
|
316 }
|
rlm@1
|
317
|
rlm@1
|
318 void DirectSound::reset()
|
rlm@1
|
319 {
|
rlm@1
|
320 if (dsbSecondary)
|
rlm@1
|
321 {
|
rlm@1
|
322 //systemScreenMessage("sound stopped (reset)!", 3);
|
rlm@1
|
323 dsbSecondary->Stop();
|
rlm@1
|
324 dsbSecondary->SetCurrentPosition(0);
|
rlm@1
|
325 }
|
rlm@1
|
326 }
|
rlm@1
|
327
|
rlm@1
|
328 void DirectSound::resume()
|
rlm@1
|
329 {
|
rlm@1
|
330 if (dsbSecondary != NULL)
|
rlm@1
|
331 {
|
rlm@1
|
332 dsbSecondary->Play(0, 0, DSBPLAY_LOOPING);
|
rlm@1
|
333 }
|
rlm@1
|
334 }
|
rlm@1
|
335
|
rlm@1
|
336 long linearFrameCount = 0;
|
rlm@1
|
337 long linearSoundByteCount = 0;
|
rlm@1
|
338 long linearSoundFrameCount = 0;
|
rlm@1
|
339
|
rlm@1
|
340 void DirectSound::write()
|
rlm@1
|
341 {
|
rlm@1
|
342 int len = soundBufferLen;
|
rlm@1
|
343 LPVOID lpvPtr1;
|
rlm@1
|
344 DWORD dwBytes1;
|
rlm@1
|
345 LPVOID lpvPtr2;
|
rlm@1
|
346 DWORD dwBytes2;
|
rlm@1
|
347
|
rlm@1
|
348 do
|
rlm@1
|
349 {
|
rlm@1
|
350 linearSoundByteCount += len;
|
rlm@1
|
351 if (wfx.nAvgBytesPerSec)
|
rlm@1
|
352 linearSoundFrameCount = 60 * linearSoundByteCount / wfx.nAvgBytesPerSec;
|
rlm@1
|
353
|
rlm@1
|
354 if (pDirectSound != NULL)
|
rlm@1
|
355 {
|
rlm@1
|
356 if (theApp.soundRecording)
|
rlm@1
|
357 {
|
rlm@1
|
358 if (dsbSecondary)
|
rlm@1
|
359 {
|
rlm@1
|
360 if (theApp.soundRecorder == NULL)
|
rlm@1
|
361 {
|
rlm@1
|
362 theApp.soundRecorder = new WavWriter;
|
rlm@1
|
363 WAVEFORMATEX format;
|
rlm@1
|
364 dsbSecondary->GetFormat(&format, sizeof(format), NULL);
|
rlm@1
|
365 if (theApp.soundRecorder->Open(theApp.soundRecordName))
|
rlm@1
|
366 theApp.soundRecorder->SetFormat(&format);
|
rlm@1
|
367 }
|
rlm@1
|
368 }
|
rlm@1
|
369
|
rlm@1
|
370 if (theApp.soundRecorder)
|
rlm@1
|
371 {
|
rlm@1
|
372 theApp.soundRecorder->AddSound((u8 *)soundFinalWave, len);
|
rlm@1
|
373 }
|
rlm@1
|
374 }
|
rlm@1
|
375
|
rlm@1
|
376 if (theApp.nvAudioLog)
|
rlm@1
|
377 {
|
rlm@1
|
378 NESVideoLoggingAudio((u8 *)soundFinalWave, wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels, len /
|
rlm@1
|
379 (wfx.nChannels * (wfx.wBitsPerSample / 8)));
|
rlm@1
|
380 }
|
rlm@1
|
381
|
rlm@1
|
382 // alternate avi record routine has been added in VBA.cpp
|
rlm@1
|
383 if (!theApp.altAviRecordMethod && theApp.aviRecording)
|
rlm@1
|
384 {
|
rlm@1
|
385 if (theApp.aviRecorder && !theApp.aviRecorder->IsPaused())
|
rlm@1
|
386 {
|
rlm@1
|
387 if (dsbSecondary)
|
rlm@1
|
388 {
|
rlm@1
|
389 if (!theApp.aviRecorder->IsSoundAdded())
|
rlm@1
|
390 {
|
rlm@1
|
391 WAVEFORMATEX format;
|
rlm@1
|
392 dsbSecondary->GetFormat(&format, sizeof(format), NULL);
|
rlm@1
|
393 theApp.aviRecorder->SetSoundFormat(&format);
|
rlm@1
|
394 }
|
rlm@1
|
395 }
|
rlm@1
|
396
|
rlm@1
|
397 theApp.aviRecorder->AddSound((u8 *)soundFinalWave, len);
|
rlm@1
|
398 }
|
rlm@1
|
399 }
|
rlm@1
|
400 }
|
rlm@1
|
401 }
|
rlm@1
|
402 while (linearSoundFrameCount <= linearFrameCount);
|
rlm@1
|
403
|
rlm@1
|
404 // arbitrarily wrap counters at 10000 frames to avoid mismatching wrap-around freeze
|
rlm@1
|
405 if (linearSoundFrameCount > 10000 && linearFrameCount > 10000)
|
rlm@1
|
406 {
|
rlm@1
|
407 linearFrameCount -= 10000;
|
rlm@1
|
408 linearSoundByteCount -= wfx.nAvgBytesPerSec * 10000 / 60;
|
rlm@1
|
409 linearSoundFrameCount = 60 * linearSoundByteCount / wfx.nAvgBytesPerSec;
|
rlm@1
|
410 }
|
rlm@1
|
411
|
rlm@1
|
412 if (!pDirectSound)
|
rlm@1
|
413 return;
|
rlm@1
|
414
|
rlm@1
|
415 HRESULT hr;
|
rlm@1
|
416
|
rlm@1
|
417 bool fastForward = speedup;
|
rlm@1
|
418 #if (defined(WIN32) && !defined(SDL))
|
rlm@1
|
419 fastForward |= theApp.frameSearchSkipping;
|
rlm@1
|
420 #endif
|
rlm@1
|
421
|
rlm@1
|
422 // slows down emulator to match up with the sound speed
|
rlm@1
|
423 if (!fastForward && synchronize && !(theApp.throttle > 100 && theApp.accuratePitchThrottle)
|
rlm@1
|
424 && theApp.throttle >= 6 && theApp.throttle <= 400)
|
rlm@1
|
425 {
|
rlm@1
|
426 DWORD status = 0;
|
rlm@1
|
427 hr = dsbSecondary->GetStatus(&status);
|
rlm@1
|
428 if (status & DSBSTATUS_PLAYING)
|
rlm@1
|
429 {
|
rlm@1
|
430 if (!soundPaused)
|
rlm@1
|
431 {
|
rlm@1
|
432 DWORD play;
|
rlm@1
|
433 while (true)
|
rlm@1
|
434 {
|
rlm@1
|
435 dsbSecondary->GetCurrentPosition(&play, NULL);
|
rlm@1
|
436
|
rlm@1
|
437 if (soundNextPosition + soundBufferLen < soundBufferTotalLen)
|
rlm@1
|
438 {
|
rlm@1
|
439 if (play < soundNextPosition
|
rlm@1
|
440 || play > soundNextPosition + soundBufferLen)
|
rlm@1
|
441 break;
|
rlm@1
|
442 }
|
rlm@1
|
443 else
|
rlm@1
|
444 {
|
rlm@1
|
445 if (play < soundNextPosition
|
rlm@1
|
446 && play > (soundNextPosition + soundBufferLen) % soundBufferTotalLen)
|
rlm@1
|
447 break;
|
rlm@1
|
448 }
|
rlm@1
|
449
|
rlm@1
|
450 if (dsbEvent)
|
rlm@1
|
451 {
|
rlm@1
|
452 WaitForSingleObject(dsbEvent, 50);
|
rlm@1
|
453 }
|
rlm@1
|
454 }
|
rlm@1
|
455 }
|
rlm@1
|
456 }
|
rlm@1
|
457 else
|
rlm@1
|
458 {
|
rlm@1
|
459 soundPaused = 1;
|
rlm@1
|
460 }
|
rlm@1
|
461 }
|
rlm@1
|
462
|
rlm@1
|
463 // Obtain memory address of write block. This will be in two parts
|
rlm@1
|
464 // if the block wraps around.
|
rlm@1
|
465 hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen,
|
rlm@1
|
466 &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2,
|
rlm@1
|
467 0);
|
rlm@1
|
468
|
rlm@1
|
469 if (FAILED(hr))
|
rlm@1
|
470 {
|
rlm@1
|
471 char str [256];
|
rlm@1
|
472 sprintf(str, "Locking secondary failed with %d", hr);
|
rlm@1
|
473 systemScreenMessage(str);
|
rlm@1
|
474 }
|
rlm@1
|
475
|
rlm@1
|
476 // If DSERR_BUFFERLOST is returned, restore and retry lock.
|
rlm@1
|
477 if (DSERR_BUFFERLOST == hr)
|
rlm@1
|
478 {
|
rlm@1
|
479 dsbSecondary->Restore();
|
rlm@1
|
480 hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen,
|
rlm@1
|
481 &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2,
|
rlm@1
|
482 0);
|
rlm@1
|
483 }
|
rlm@1
|
484
|
rlm@1
|
485 if (SUCCEEDED(hr))
|
rlm@1
|
486 {
|
rlm@1
|
487 if (theApp.muteFrameAdvance && theApp.winPauseNextFrame || theApp.winMuteForNow)
|
rlm@1
|
488 {
|
rlm@1
|
489 // Write 0 to pointers.
|
rlm@1
|
490 if (NULL != lpvPtr1)
|
rlm@1
|
491 ZeroMemory(lpvPtr1, dwBytes1);
|
rlm@1
|
492 if (NULL != lpvPtr2)
|
rlm@1
|
493 ZeroMemory(lpvPtr2, dwBytes2);
|
rlm@1
|
494 }
|
rlm@1
|
495 else
|
rlm@1
|
496 {
|
rlm@1
|
497 // Write to pointers.
|
rlm@1
|
498 if (NULL != lpvPtr1)
|
rlm@1
|
499 CopyMemory(lpvPtr1, soundFinalWave, dwBytes1);
|
rlm@1
|
500 if (NULL != lpvPtr2)
|
rlm@1
|
501 CopyMemory(lpvPtr2, soundFinalWave + dwBytes1, dwBytes2);
|
rlm@1
|
502 }
|
rlm@1
|
503
|
rlm@1
|
504 // Release the data back to DirectSound.
|
rlm@1
|
505 hr = dsbSecondary->Unlock(lpvPtr1, dwBytes1, lpvPtr2,
|
rlm@1
|
506 dwBytes2);
|
rlm@1
|
507 }
|
rlm@1
|
508
|
rlm@1
|
509 soundNextPosition += soundBufferLen;
|
rlm@1
|
510 soundNextPosition %= soundBufferTotalLen;
|
rlm@1
|
511 }
|
rlm@1
|
512
|
rlm@1
|
513 void DirectSound::clearAudioBuffer()
|
rlm@1
|
514 {
|
rlm@1
|
515 LPVOID lpvPtr1;
|
rlm@1
|
516 DWORD dwBytes1;
|
rlm@1
|
517 LPVOID lpvPtr2;
|
rlm@1
|
518 DWORD dwBytes2;
|
rlm@1
|
519 HRESULT hr = dsbSecondary->Lock(0, soundBufferTotalLen, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
|
rlm@1
|
520 if (!FAILED(hr))
|
rlm@1
|
521 {
|
rlm@1
|
522 if (lpvPtr1)
|
rlm@1
|
523 memset(lpvPtr1, 0, dwBytes1);
|
rlm@1
|
524 if (lpvPtr2)
|
rlm@1
|
525 memset(lpvPtr2, 0, dwBytes2);
|
rlm@1
|
526 hr = dsbSecondary->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
|
rlm@1
|
527 }
|
rlm@1
|
528 }
|
rlm@1
|
529
|
rlm@1
|
530 ISound *newDirectSound()
|
rlm@1
|
531 {
|
rlm@1
|
532 return new DirectSound();
|
rlm@1
|
533 }
|
rlm@1
|
534
|