From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_sound_d3_d_8cpp_source.html | 1414 +++++++++++++++++++++++++ 1 file changed, 1414 insertions(+) create mode 100644 Doc/doxygen/html/_sound_d3_d_8cpp_source.html (limited to 'Doc/doxygen/html/_sound_d3_d_8cpp_source.html') diff --git a/Doc/doxygen/html/_sound_d3_d_8cpp_source.html b/Doc/doxygen/html/_sound_d3_d_8cpp_source.html new file mode 100644 index 0000000..d54776b --- /dev/null +++ b/Doc/doxygen/html/_sound_d3_d_8cpp_source.html @@ -0,0 +1,1414 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/nGenEx/SoundD3D.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
SoundD3D.cpp
+
+
+Go to the documentation of this file.
1 /* Project nGenEx
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: nGenEx.lib
+
6  FILE: SoundD3D.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  DirectSound and DirectSound3D (sound card) class
+
13 */
+
14 
+
15 //#define INITGUID
+
16 #include <objbase.h>
+
17 #include <cguid.h>
+
18 #include <mmsystem.h>
+
19 #include <dsound.h>
+
20 
+
21 
+
22 #include "MemDebug.h"
+
23 #include "SoundD3D.h"
+
24 #include "Game.h"
+
25 
+
26 #ifdef DIRECT_SOUND_3D
+
27 #include "ia3d.h"
+
28 #endif
+
29 
+
30 // +--------------------------------------------------------------------+
+
31 
+
32 void Print(const char* msg, ...);
+
33 char* DSErrStr(HRESULT dserr);
+
34 void SoundD3DError(const char* msg, HRESULT dserr);
+
35 
+
36 static int DS3D_report_errors = 1;
+
37 
+
38 #ifndef RELEASE
+
39 #define RELEASE(x) if (x) { x->Release(); x=NULL; }
+
40 #endif
+
41 
+
42 // +====================================================================+
+
43 // | SOUND CARD D3D
+
44 // +====================================================================+
+
45 
+ +
47 : soundcard(0), primary(0)
+
48 {
+
49  HRESULT err = 0;
+
50  status = SC_ERROR;
+
51 
+
52  // 1) Get interface to DirectSound object:
+
53 
+
54 #ifdef DIRECT_SOUND_3D
+
55  CoInitialize(NULL);
+
56  err = CoCreateInstance(CLSID_A3d, NULL, CLSCTX_INPROC_SERVER,
+
57  IID_IDirectSound, (VOID **)&soundcard);
+
58 
+
59  if (SUCCEEDED(err)) {
+
60  soundcard->Initialize(NULL);
+
61  SoundD3DError("Initialized Aureal3D Sound", 0);
+
62  }
+
63  else {
+
64  SoundD3DError("Could not initialize Aureal3D Sound", err);
+
65  SoundD3DError("Proceding with standard DirectSoundCreate", 0);
+
66 #endif
+
67 
+
68  err = DirectSoundCreate(0, &soundcard, 0);
+
69  if (FAILED(err)) {
+
70  SoundD3DError("Could not create DirectSound object.", err);
+
71  soundcard = 0;
+
72  primary = 0;
+
73  return;
+
74  }
+
75 
+
76 #ifdef DIRECT_SOUND_3D
+
77  }
+
78 #endif
+
79 
+
80  // 2) Set the cooperative level:
+
81  err = soundcard->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
+
82  if (FAILED(err)) {
+
83  SoundD3DError("Could not set cooperative level.", err);
+ +
85  return;
+
86  }
+
87 
+
88  // Prepare to initialize the primary buffer:
+
89  DSCAPS caps;
+
90  memset(&caps, 0, sizeof(caps));
+
91  caps.dwSize = sizeof(caps);
+
92 
+
93  err = soundcard->GetCaps(&caps);
+
94  if (FAILED(err)) {
+
95  SoundD3DError("Could not get soundcard caps.", err);
+ +
97  return;
+
98  }
+
99 
+
100  if (caps.dwFlags & DSCAPS_EMULDRIVER)
+
101  Print(" WARNING: using DirectSound emulated drivers\n");
+
102 
+
103  memset(&dsbd, 0, sizeof(dsbd));
+
104  dsbd.dwSize = sizeof(dsbd);
+
105 
+
106 #ifdef DIRECT_SOUND_3D
+
107  int use_ds3d = true;
+
108 
+
109  // 3) Set up the primary buffer (try to use DS3D):
+
110  dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
+
111 
+
112  err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
+
113  if (err == DSERR_CONTROLUNAVAIL) {
+
114  use_ds3d = false;
+
115 
+
116  // try again, without using DS3D
+
117  dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLDEFAULT;
+
118 
+
119  err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
+
120  if (FAILED(err)) {
+
121  SoundD3DError("Could not initialize primary buffer", err);
+ +
123  return;
+
124  }
+
125  else {
+
126  Print(" WARNING: DirectSound3D is not available, simulating instead\n");
+
127  }
+
128  }
+
129 
+
130  // 4) Set up the listener:
+
131  if (primary && use_ds3d) {
+
132  err = primary->QueryInterface(IID_IDirectSound3DListener, (void**)&listener);
+
133  if (FAILED(err)) {
+
134  SoundD3DError("Could not get listener interface", err);
+
135  }
+
136  else {
+
137  listener->SetPosition(0.0f, 0.0f, 0.0f, DS3D_IMMEDIATE);
+
138  listener->SetOrientation(0.0f, 0.0f, 1.0f,
+
139  0.0f, 1.0f, 0.0f, DS3D_IMMEDIATE);
+
140  }
+
141  }
+
142 
+
143 #else
+
144  // 3) Set up the primary buffer:
+
145  dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
+
146 
+
147  err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
+
148  if (FAILED(err)) {
+
149  SoundD3DError("Could not initialize primary buffer", err);
+ +
151  return;
+
152  }
+
153 #endif
+
154 
+
155  // 5) Set primary buffer parameters to 16 bit STEREO at 44kHz
+
156  SetFormat(16, 2, 44100);
+
157 
+
158  // read back the result format and display to the log file:
+
159  GetFormat(0);
+
160  ShowFormat();
+
161 
+
162  status = SC_OK;
+
163 }
+
164 
+
165 // +--------------------------------------------------------------------+
+
166 
+ +
168 {
+
169  ListIter<Sound> iter = sounds;
+
170  while (++iter) {
+
171  Sound* s = iter.value();
+
172  s->Stop();
+
173  }
+
174 
+
175  sounds.destroy();
+
176 
+
177 #ifdef DIRECT_SOUND_3D
+
178  RELEASE(listener);
+
179 #endif
+
180 
+
181  RELEASE(primary);
+ +
183 
+
184  Print(" SoundCardD3D: shutdown\n");
+
185 
+ +
187 }
+
188 
+
189 // +--------------------------------------------------------------------+
+
190 
+
191 bool
+
192 SoundCardD3D::SetFormat(int bits, int channels, int hertz)
+
193 {
+
194  if (!soundcard) return false;
+
195 
+
196  DSCAPS caps;
+
197  memset(&caps, 0, sizeof(caps));
+
198  caps.dwSize = sizeof(caps);
+
199  soundcard->GetCaps(&caps);
+
200 
+
201  if (!(caps.dwFlags & DSCAPS_PRIMARY16BIT)) bits = 8;
+
202  if (!(caps.dwFlags & DSCAPS_PRIMARYSTEREO)) channels = 1;
+
203 
+
204  memset(&wfex, 0, sizeof(wfex));
+
205 
+
206  wfex.wFormatTag = WAVE_FORMAT_PCM;
+
207  wfex.nChannels = channels;
+
208  wfex.nSamplesPerSec = hertz;
+
209  wfex.nBlockAlign = (channels * bits) / 8;
+
210  wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
+
211  wfex.wBitsPerSample = bits;
+
212 
+
213  return SetFormat(&wfex);
+
214 }
+
215 
+
216 // +--------------------------------------------------------------------+
+
217 
+
218 bool
+
219 SoundCardD3D::SetFormat(LPWAVEFORMATEX format)
+
220 {
+
221  HRESULT err = E_FAIL;
+
222 
+
223  if (primary)
+
224  err = primary->SetFormat(format);
+
225 
+
226  return SUCCEEDED(err);
+
227 }
+
228 
+
229 // +--------------------------------------------------------------------+
+
230 
+
231 bool
+
232 SoundCardD3D::GetFormat(LPWAVEFORMATEX format)
+
233 {
+
234  if (!format) format = &wfex;
+
235 
+
236  HRESULT err = E_FAIL;
+
237 
+
238  if (primary)
+
239  err = primary->GetFormat(format, sizeof(WAVEFORMATEX), 0);
+
240 
+
241  return SUCCEEDED(err);
+
242 }
+
243 
+
244 // +--------------------------------------------------------------------+
+
245 
+
246 void
+ +
248 {
+
249  Print(" SoundCardD3D Primary Buffer Format:\n");
+
250  Print(" bits: %d\n", wfex.wBitsPerSample);
+
251  Print(" chls: %d\n", wfex.nChannels);
+
252  Print(" rate: %d\n\n", wfex.nSamplesPerSec);
+
253 }
+
254 
+
255 // +--------------------------------------------------------------------+
+
256 
+
257 Sound*
+
258 SoundCardD3D::CreateSound(DWORD flags, LPWAVEFORMATEX format)
+
259 {
+
260  if (!soundcard) return 0;
+
261 
+
262  Sound* result = new(__FILE__,__LINE__) SoundD3D(soundcard, flags, format);
+
263  if (result) AddSound(result);
+
264  return result;
+
265 }
+
266 
+
267 // +--------------------------------------------------------------------+
+
268 
+
269 Sound*
+
270 SoundCardD3D::CreateSound(DWORD flags, LPWAVEFORMATEX format, DWORD len, LPBYTE data)
+
271 {
+
272  if (!soundcard) return 0;
+
273  Sound* result = new(__FILE__,__LINE__) SoundD3D(soundcard, flags, format, len, data);
+
274 
+
275  if (flags & (Sound::STREAMED | Sound::OGGVORBIS)) {
+
276  if (result)
+
277  AddSound(result);
+
278  }
+
279 
+
280  return result;
+
281 }
+
282 
+
283 // +--------------------------------------------------------------------+
+
284 
+
285 void
+
286 SoundCardD3D::SetListener(const Camera& cam, const Vec3& vel)
+
287 {
+
288  Point pos = cam.Pos();
+
289 
+
290 #ifdef DIRECT_SOUND_3D
+
291  listener->SetPosition((float) pos.x, (float) pos.z, (float) pos.y, DS3D_IMMEDIATE);
+
292  listener->SetOrientation((float) cam.vpn().x, (float) cam.vpn().y, (float) cam.vpn().z,
+
293  (float) cam.vup().x, (float) cam.vup().y, (float) cam.vup().z,
+
294  DS3D_IMMEDIATE);
+
295  listener->SetVelocity(vel.x, vel.y, vel.z, DS3D_IMMEDIATE);
+
296 #else
+
297  listener.Clone(cam);
+
298  listener.MoveTo(pos.x, pos.z, pos.y);
+
299  velocity = vel;
+
300 #endif
+
301 }
+
302 
+
303 // +--------------------------------------------------------------------+
+
304 
+
305 bool
+ +
307 {
+
308  AutoThreadSync a(sync);
+
309 
+
310  ListIter<Sound> iter = sounds;
+
311  while (++iter) {
+
312  Sound* s = iter.value();
+
313 
+
314  if ((s->GetFlags() & Sound::INTERFACE) == 0)
+
315  s->Pause();
+
316  }
+
317 
+
318  return true;
+
319 }
+
320 
+
321 // +--------------------------------------------------------------------+
+
322 
+
323 bool
+ +
325 {
+
326  AutoThreadSync a(sync);
+
327 
+
328  ListIter<Sound> iter = sounds;
+
329  while (++iter) {
+
330  Sound* s = iter.value();
+
331 
+
332  if (s->IsReady())
+
333  s->Play();
+
334  }
+
335 
+
336  return true;
+
337 }
+
338 
+
339 // +--------------------------------------------------------------------+
+
340 
+
341 bool
+ +
343 {
+
344  AutoThreadSync a(sync);
+
345 
+
346  DWORD ok_sounds = (Sound::INTERFACE | Sound::OGGVORBIS | Sound::RESOURCE);
+
347 
+
348  ListIter<Sound> iter = sounds;
+
349  while (++iter) {
+
350  Sound* s = iter.value();
+
351 
+
352  if ((s->GetFlags() & ok_sounds) == 0)
+
353  s->Stop();
+
354  }
+
355 
+
356  return true;
+
357 }
+
358 
+
359 // +====================================================================+
+
360 // | SOUND D3D
+
361 // +====================================================================+
+
362 
+
363 SoundD3D::SoundD3D(LPDIRECTSOUND card, DWORD flag_req, LPWAVEFORMATEX format)
+
364 : soundcard(card), buffer(0), min_dist(1.0f), max_dist(100000.0f),
+
365 stream(0), stream_left(0), min_safety(0), read_size(0), transfer(0), w(0), r(0),
+
366 stream_offset(0), data_len(0), data(0), moved(false), eos_written(false), eos_latch(0),
+
367 ov_file(0), total_time(0)
+
368 {
+
369  flags = flag_req;
+
370 
+
371  CopyMemory(&wfex, format, sizeof(wfex));
+
372  ZeroMemory(&dsbd, sizeof(dsbd));
+
373 
+
374  dsbd.dwSize = sizeof(dsbd);
+
375  dsbd.dwFlags = DSBCAPS_CTRLVOLUME /* | DSBCAPS_GETCURRENTPOSITION2 */;
+
376  dsbd.lpwfxFormat = &wfex;
+
377 
+
378 #ifdef DIRECT_SOUND_3D
+
379  sound3d = 0;
+
380  if (flags & LOCALIZED)
+
381  if (flags & LOC_3D)
+
382  dsbd.dwFlags |= DSBCAPS_CTRL3D;
+
383  else
+
384  dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
+
385 #else
+
386  dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
+
387 
+
388  if (flags & LOCALIZED)
+
389  dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
+
390 #endif
+
391 
+
392 }
+
393 
+
394 // +--------------------------------------------------------------------+
+
395 // SOUND RESOURCE CONSTRUCTOR:
+
396 // (Now also used to create Ogg Vorbis streaming sound objects)
+
397 
+
398 SoundD3D::SoundD3D(LPDIRECTSOUND card, DWORD flag_req, LPWAVEFORMATEX format, DWORD len, LPBYTE pData)
+
399 : soundcard(card), buffer(0), min_dist(1.0f), max_dist(100000.0f),
+
400 stream(0), stream_left(0), min_safety(0), read_size(0), transfer(0), w(0), r(0),
+
401 stream_offset(0), data_len(0), data(0), moved(false), eos_written(false), eos_latch(0),
+
402 ov_file(0)
+
403 {
+
404  flags = flag_req;
+
405 
+
406  if (!(flags & (STREAMED | OGGVORBIS)))
+
407  flags = flag_req | RESOURCE;
+
408 
+
409  CopyMemory(&wfex, format, sizeof(wfex));
+
410  ZeroMemory(&dsbd, sizeof(dsbd));
+
411 
+
412  dsbd.dwSize = sizeof(dsbd);
+
413  dsbd.dwFlags = DSBCAPS_CTRLVOLUME /* | DSBCAPS_GETCURRENTPOSITION2 */;
+
414  dsbd.lpwfxFormat = &wfex;
+
415 
+
416 #ifdef DIRECT_SOUND_3D
+
417  sound3d = 0;
+
418  if (flags & LOCALIZED)
+
419  if (flags & LOC_3D)
+
420  dsbd.dwFlags |= DSBCAPS_CTRL3D;
+
421  else
+
422  dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
+
423 #else
+
424  if (flags & LOCALIZED)
+
425  dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
+
426 #endif
+
427 
+
428  if (len) {
+
429  // If this is an OGG VORBIS streaming sound,
+
430  // the parameter that normally points to the actual data
+
431  // is used to pass in an Ogg Vorbis file structure instead:
+
432 
+
433  if (flags & OGGVORBIS) {
+
434  ov_file = (OggVorbis_File*) pData;
+
435  StreamOggFile();
+
436  }
+
437 
+
438  else {
+
439  data_len = len;
+
440  data = new(__FILE__,__LINE__) BYTE[len];
+
441 
+
442  if (!data) {
+
443  data_len = 0;
+
444  }
+
445 
+
446  else {
+
447  CopyMemory(data, pData, data_len);
+
448  Load(data_len, data);
+
449  }
+
450  }
+
451  }
+
452 }
+
453 
+
454 // +--------------------------------------------------------------------+
+
455 
+ +
457 {
+
458  delete [] data;
+
459  delete [] transfer;
+
460 
+
461  if (ov_file) {
+
462  ov_clear(ov_file);
+
463  delete ov_file;
+
464  }
+
465 
+
466  else if (stream) {
+
467  fclose(stream);
+
468  }
+
469 
+
470  RELEASE(buffer);
+
471 
+
472 #ifdef DIRECT_SOUND_3D
+
473  RELEASE(sound3d);
+
474 #endif
+
475 }
+
476 
+
477 // +--------------------------------------------------------------------+
+
478 
+
479 void
+ +
481 {
+
482  if (!buffer || status != PLAYING) return; // nothing to do
+
483 
+
484  DWORD dstat;
+
485  HRESULT hr = buffer->GetStatus(&dstat);
+
486  if (FAILED(hr)) {
+
487  SoundD3DError("Update: GetStatus failed", hr);
+
488  return;
+
489  }
+
490 
+
491  AutoThreadSync a(sync);
+
492 
+
493  if (sound_check) sound_check->Update(this);
+
494 
+
495  if (!Game::Paused() || flags & STREAMED) {
+
496  // see if we are done:
+
497  if (!(dstat & DSBSTATUS_PLAYING)) {
+
498  status = DONE;
+
499  buffer->Stop();
+
500  return;
+
501  }
+
502 
+
503  // if not done, see if we need to change location params:
+
504  if (moved) {
+
505  Localize();
+
506  }
+
507  }
+
508 
+
509  // if not done, see if we need to load more data
+
510  // into the streaming buffer:
+
511  if (flags & STREAMED) {
+
512  buffer->GetCurrentPosition(&r, 0);
+
513 
+
514  DWORD data_left;
+
515  if (w > r)
+
516  data_left = w - r;
+
517  else
+
518  data_left = w + (read_size + min_safety) - r;
+
519 
+
520  // getting low, fill 'er up:
+
521  if (eos_written || data_left <= min_safety) {
+
522  StreamBlock();
+
523 
+
524  if (stream_left == 0) {
+
525  // if this is the end of a looping stream,
+
526  if (flags & LOOP) {
+
527  RewindStream();
+
528  looped++;
+
529  }
+
530  else {
+
531  if (!eos_written) {
+
532  eos_written = true;
+
533  eos_latch = 3;
+
534  }
+
535 
+
536  else if (--eos_latch == 0) {
+
537  status = DONE;
+
538  buffer->Stop();
+
539  }
+
540  }
+
541  }
+
542 
+
543  status = PLAYING;
+
544  }
+
545  }
+
546 }
+
547 
+
548 void
+ +
550 {
+
551  if (flags & OGGVORBIS) {
+
552  StreamOggBlock();
+
553  return;
+
554  }
+
555 
+
556  if (!stream || !stream_left)
+
557  return;
+
558 
+
559  if (stream_left < read_size) {
+
560  if (stream_left > 0) {
+
561  fread(transfer, stream_left, 1, stream);
+ +
563  stream_left = 0;
+
564  }
+
565  }
+
566 
+
567  else if (read_size > 0) {
+
568  fread(transfer, read_size, 1, stream);
+ + +
571  }
+
572 }
+
573 
+ +
575 
+
576 void
+ +
578 {
+
579  int current_bitstream;
+
580  DWORD bytes_read = 0;
+
581  long retval = 0;
+
582  char* p = (char*) transfer;
+
583 
+
584  while (stream_left && bytes_read < read_size) {
+
585  retval = ov_read(ov_file, p, read_size-bytes_read, 0,2,1, &current_bitstream);
+
586 
+
587  if (retval == 0) {
+
588  /* EOF */
+
589  stream_left = 0;
+
590  }
+
591  else if (retval < 0) {
+
592  /* error in the stream. Not a problem, just reporting it in
+
593  case the app cares. In this case, we don't. */
+ +
595  }
+
596  else {
+
597  /* we don't bother dealing with sample rate changes, etc, but you'll have to ??? */
+
598  bytes_read += retval;
+
599  stream_left -= retval;
+
600  p += retval;
+
601  }
+
602  }
+
603 
+
604  if (bytes_read)
+
605  Load(bytes_read, transfer);
+
606 }
+
607 
+
608 void
+ +
610 {
+
611  if (flags & OGGVORBIS) {
+
612  RewindOggStream();
+
613  return;
+
614  }
+
615 
+
616  if (!stream || !buffer)
+
617  return;
+
618 
+
619  // rewind the stream and keep going...
+
620  eos_written = false;
+
621  eos_latch = 0;
+
622  read_size = wfex.nAvgBytesPerSec / 2;
+
623 
+
624  // find the size of the file:
+
625  fseek(stream, 0, SEEK_END);
+
626  stream_left = ftell(stream) - stream_offset;
+
627  fseek(stream, stream_offset, SEEK_SET);
+
628 
+
629  total_time = (double) stream_left /
+
630  (double) wfex.nAvgBytesPerSec;
+
631 
+
632  if (stream_left < read_size) {
+
633  status = DONE;
+
634  buffer->Stop();
+
635  }
+
636 }
+
637 
+
638 void
+ +
640 {
+
641  if (!ov_file || !buffer)
+
642  return;
+
643 
+
644  // rewind the stream and keep going...
+
645  eos_written = false;
+
646  eos_latch = 0;
+
647  read_size = wfex.nAvgBytesPerSec / 2;
+
648 
+
649  // set the stream pointer back to the beginning:
+
650  ov_pcm_seek(ov_file, 0);
+
651 
+
652  // find the size of the file:
+
653  stream_left = (DWORD) ov_pcm_total(ov_file,-1);
+
654  stream_offset = 0;
+
655 
+
656  total_time = (double) stream_left /
+
657  (double) wfex.nAvgBytesPerSec;
+
658 
+
659  if (stream_left < read_size) {
+
660  status = DONE;
+
661  buffer->Stop();
+
662  }
+
663 }
+
664 
+
665 void
+ +
667 {
+
668 #ifdef DIRECT_SOUND_3D
+
669  if (sound3d) {
+
670  sound3d->SetMinDistance(min_dist, DS3D_IMMEDIATE);
+
671  sound3d->SetMaxDistance(max_dist, DS3D_IMMEDIATE);
+
672  sound3d->SetPosition(location.x, location.y, location.z, DS3D_IMMEDIATE);
+
673  sound3d->SetVelocity(velocity.x, velocity.y, velocity.z, DS3D_IMMEDIATE);
+
674  }
+
675 
+
676 #else
+
677 
+
678  // if no buffer, nothing to do:
+
679  if (!buffer) {
+
680  moved = false;
+
681  return;
+
682  }
+
683 
+
684  // Compute pan and volume from scratch:
+
685 
+
686  if ((flags & LOC_3D) && creator) {
+
687  Vec3 loc = location;
+
688 
+
689  SoundCardD3D* ears = (SoundCardD3D*) creator;
+
690  Camera& listener = ears->listener;
+
691  Vec3 ear_loc = listener.Pos(); ear_loc.SwapYZ();
+
692  Vec3 direction = loc - ear_loc;
+
693 
+
694  loc.x = direction * listener.vrt();
+
695  loc.y = direction * listener.vup();
+
696  loc.z = direction * listener.vpn();
+
697 
+
698  double pan = 10000;
+
699  if (loc.z != 0.0f) pan = fabs(1000.0f * loc.x / loc.z);
+
700  if (pan > 10000) pan = 10000;
+
701  if (loc.x < 0) pan = -pan;
+
702 
+
703  if (volume > 0)
+
704  volume = 0;
+
705 
+
706  double vol = volume;
+
707  double mind2 = min_dist * min_dist;
+
708  double maxd2 = max_dist * max_dist;
+
709  double d2 = (loc.x*loc.x) + (loc.y*loc.y) + (loc.z*loc.z);
+
710 
+
711  if (d2 > maxd2)
+
712  vol = -10000;
+
713  else if (d2 > mind2)
+
714  vol -= (d2-mind2)/(maxd2-mind2) * (vol+10000);
+
715 
+
716  // clamp volume to legal range:
+
717  if (vol < -10000) vol = -10000;
+
718  else if (vol > volume) vol = volume;
+
719 
+
720  /***
+
721  Print("Localize: ears = (%f, %f, %f)\n", ear_loc.x, ear_loc.y, ear_loc.z);
+
722  Print(" world = (%f, %f, %f)\n", location.x, location.y, location.z);
+
723  Print(" view = (%f, %f, %f)\n", loc.x, loc.y, loc.z);
+
724  Print(" Pan=%f Volume=%f\n", pan, vol);
+
725  /***/
+
726 
+
727  HRESULT hr = buffer->SetPan((LONG) pan);
+
728  if (!SUCCEEDED(hr)) {
+
729  char warn[512];
+
730  sprintf_s(warn, "Warning could not set pan on buffer to %f", pan);
+
731  SoundD3DError(warn, hr);
+
732  }
+
733 
+
734  hr = buffer->SetVolume((LONG) vol);
+
735  if (!SUCCEEDED(hr)) {
+
736  char warn[512];
+
737  sprintf_s(warn, "Warning: could not set volume on buffer to %f", vol);
+
738  SoundD3DError(warn, hr);
+
739  }
+
740 
+
741  // if not too far to hear...
+
742  if ((flags & DOPPLER) && (d2 < maxd2)) {
+
743  // COMPUTE DOPPLER SHIFT:
+
744  const float c = 10000.0f;
+
745 
+
746  direction.Normalize();
+
747  float v_L = ears->velocity * direction;
+
748  float v_S = velocity * direction;
+
749 
+
750  DWORD f_shift = wfex.nSamplesPerSec;
+
751 
+
752  if (v_L != v_S) {
+
753  // towards listener:
+
754  if (v_S < 0)
+
755  f_shift = wfex.nSamplesPerSec + 20;
+
756  else
+
757  f_shift = wfex.nSamplesPerSec - 20;
+
758  }
+
759 
+
760  // distance rolloff of high frequencies:
+
761  double dist = sqrt(d2);
+
762  DWORD roll_off = (DWORD) (80 * dist/max_dist);
+
763 
+
764  f_shift -= roll_off;
+
765 
+
766  if (f_shift < 100) f_shift = 100;
+
767  if (f_shift > 100000) f_shift = 100000;
+
768 
+
769  hr = buffer->SetFrequency(f_shift);
+
770  if (!SUCCEEDED(hr)) {
+
771  char warn[512];
+
772  sprintf_s(warn, "Warning: could not set Doppler frequency on buffer to %d", f_shift);
+
773  SoundD3DError(warn, hr);
+
774  }
+
775  }
+
776  }
+
777  else {
+
778  buffer->SetPan((LONG) location.x);
+
779  buffer->SetVolume((LONG) volume);
+
780  }
+
781 #endif
+
782 
+
783  moved = false;
+
784 }
+
785 
+
786 // +--------------------------------------------------------------------+
+
787 
+
788 Sound*
+ +
790 {
+
791  Sound* sound = 0;
+
792 
+
793  if (flags & RESOURCE) {
+
794  sound = Sound::Create(flags & ~RESOURCE, &wfex);
+
795 
+
796  if (sound && !(flags & STREAMED)) {
+
797  sound->SetMinDistance(min_dist);
+
798  sound->SetMaxDistance(max_dist);
+
799 
+
800  if (!buffer) {
+
801  sound->Load(data_len, data);
+
802  }
+
803 
+
804  else {
+
805  SoundD3D* s3d = (SoundD3D*) sound;
+
806  soundcard->DuplicateSoundBuffer(buffer, &s3d->buffer);
+
807  sound->Rewind();
+
808  }
+
809  }
+
810  }
+
811 
+
812  return sound;
+
813 }
+
814 
+
815 // +--------------------------------------------------------------------+
+
816 
+
817 HRESULT
+
818 SoundD3D::StreamFile(const char* name, DWORD offset)
+
819 {
+
820  DWORD buf_size = wfex.nAvgBytesPerSec / 2;
+
821  DWORD safety_zone = buf_size * 2;
+
822 
+
823  if (stream) {
+
824  delete[] transfer;
+
825  transfer = 0;
+
826  fclose(stream);
+
827  }
+
828 
+ +
830  stream_left = 0;
+
831  stream_offset = offset;
+
832 
+
833  eos_written = false;
+
834  eos_latch = 0;
+
835  min_safety = safety_zone;
+
836  read_size = buf_size;
+
837 
+
838  fopen_s(&stream, name, "rb");
+
839 
+
840  // open the stream:
+
841  if (stream == 0) {
+
842  SoundD3DError("StreamFile: could not open stream", E_FAIL);
+
843  return E_FAIL;
+
844  }
+
845 
+
846  // find the size of the file:
+
847  fseek(stream, 0, SEEK_END);
+
848  stream_left = ftell(stream) - offset;
+
849  fseek(stream, stream_offset, SEEK_SET);
+
850 
+
851  total_time = (double) stream_left /
+
852  (double) wfex.nAvgBytesPerSec;
+
853 
+
854  if (stream_left < read_size) {
+ +
856  }
+
857 
+
858  HRESULT hr = AllocateBuffer(read_size + min_safety);
+
859 
+
860  if (FAILED(hr))
+
861  return hr;
+
862 
+
863  flags |= STREAMED;
+
864 
+
865  // preload the buffer:
+
866  w = r = 0;
+
867  transfer = new(__FILE__,__LINE__) BYTE[read_size + 1024];
+
868 
+
869  if (!transfer) {
+
870  hr = E_FAIL;
+
871  }
+
872 
+
873  else {
+
874  ZeroMemory(transfer, read_size+1024);
+
875  StreamBlock();
+
876  }
+
877 
+
878  return hr;
+
879 }
+
880 
+
881 // +--------------------------------------------------------------------+
+
882 
+
883 HRESULT
+ +
885 {
+
886  DWORD buf_size = wfex.nAvgBytesPerSec / 2;
+
887  DWORD safety_zone = buf_size * 2;
+
888 
+
889  if (stream) {
+
890  delete[] transfer;
+
891  fclose(stream);
+
892 
+
893  transfer = 0;
+
894  stream = 0;
+
895  }
+
896 
+ +
898  stream_left = (DWORD) ov_pcm_total(ov_file,-1);
+
899  stream_offset = 0;
+
900 
+
901  eos_written = false;
+
902  eos_latch = 0;
+
903  min_safety = safety_zone;
+
904  read_size = buf_size;
+
905 
+
906  total_time = (double) stream_left /
+
907  (double) wfex.nAvgBytesPerSec;
+
908 
+
909  if (stream_left < read_size) {
+ +
911  }
+
912 
+
913  HRESULT hr = AllocateBuffer(read_size + min_safety);
+
914 
+
915  if (FAILED(hr))
+
916  return hr;
+
917 
+
918  flags |= STREAMED | OGGVORBIS;
+
919 
+
920  // preload the buffer:
+
921  w = r = 0;
+
922  transfer = new(__FILE__,__LINE__) BYTE[read_size + 1024];
+
923 
+
924  if (!transfer) {
+
925  hr = E_FAIL;
+
926  }
+
927 
+
928  else {
+
929  ZeroMemory(transfer, read_size+1024);
+
930  StreamOggBlock();
+
931  }
+
932 
+
933  return hr;
+
934 }
+
935 
+
936 // +--------------------------------------------------------------------+
+
937 
+
938 HRESULT
+
939 SoundD3D::Load(DWORD bytes, BYTE* data)
+
940 {
+ +
942 
+
943  HRESULT hr;
+
944 
+
945  if (!buffer) {
+
946  hr = AllocateBuffer(bytes);
+
947  if (FAILED(hr)) {
+
948  return hr;
+
949  }
+
950  }
+
951 
+
952  LPVOID dest1, dest2;
+
953  DWORD size1, size2;
+
954 
+
955  hr = buffer->Lock(w, bytes, &dest1, &size1, &dest2, &size2, 0);
+
956 
+
957  if (hr == DSERR_BUFFERLOST) {
+
958  buffer->Restore();
+
959  hr = buffer->Lock(w, bytes, &dest1, &size1, &dest2, &size2, 0);
+
960  }
+
961 
+
962  if (SUCCEEDED(hr)) {
+
963  CopyMemory(dest1, data, size1);
+
964  if (dest2) {
+
965  CopyMemory(dest2, data + size1, size2);
+
966  }
+
967 
+
968  if (flags & STREAMED)
+
969  w = (w + size1 + size2) % (read_size + min_safety);
+
970  else
+
971  w += size1 + size2;
+
972 
+
973  hr = buffer->Unlock(dest1, size1, dest2, size2);
+
974  if (FAILED(hr)) {
+
975  SoundD3DError("Load: could not unlock buffer", hr);
+
976  }
+
977  }
+
978  else {
+
979  SoundD3DError("Load: could not lock buffer", hr);
+
980  }
+
981 
+
982  if (SUCCEEDED(hr)) {
+
983  status = READY;
+
984  }
+
985 
+
986  return hr;
+
987 }
+
988 
+
989 // +--------------------------------------------------------------------+
+
990 
+
991 HRESULT
+ +
993 {
+
994  HRESULT hr = S_OK;
+
995 
+
996  if (!buffer) {
+
997  dsbd.dwBufferBytes = bytes;
+
998 
+
999  if (soundcard) {
+
1000  hr = soundcard->CreateSoundBuffer(&dsbd, &buffer, NULL);
+
1001 
+
1002  if (FAILED(hr)) {
+
1003  SoundD3DError("AllocateBuffer: could not create buffer", hr);
+
1004 
+
1005  Print(" dsbd.dwSize = %8d\n", dsbd.dwSize);
+
1006  Print(" dsbd.dwFlags = %08x\n", dsbd.dwFlags);
+
1007  Print(" dsbd.dwBufferBytes = %8d\n", dsbd.dwBufferBytes);
+
1008  Print(" dsbd.lpwfxFormat = %08x\n", dsbd.lpwfxFormat);
+
1009 
+
1010  if (dsbd.lpwfxFormat) {
+
1011  Print(" wfex.wBitsPerSample = %8d\n", dsbd.lpwfxFormat->wBitsPerSample);
+
1012  Print(" wfex.nChannels = %8d\n", dsbd.lpwfxFormat->nChannels);
+
1013  Print(" wfex.nSamplesPerSec = %8d\n", dsbd.lpwfxFormat->nSamplesPerSec);
+
1014  }
+
1015  }
+
1016  }
+
1017  else {
+
1018  SoundD3DError("AllocateBuffer: soundcard is null", E_FAIL);
+
1019  }
+
1020  }
+
1021 
+
1022  return hr;
+
1023 }
+
1024 
+
1025 // +--------------------------------------------------------------------+
+
1026 
+
1027 HRESULT
+ +
1029 {
+
1030  if (IsPlaying()) return S_OK;
+
1031  if (!buffer) return E_FAIL;
+
1032 
+
1033  HRESULT hr = E_FAIL;
+
1034 
+
1035  if (IsDone())
+
1036  hr = Rewind();
+
1037 
+
1038  if (IsReady()) {
+
1039  if (moved)
+
1040  Localize();
+
1041 
+
1042  if (flags & LOOP || flags & STREAMED)
+
1043  hr = buffer->Play(0, 0, DSBPLAY_LOOPING);
+
1044  else
+
1045  hr = buffer->Play(0, 0, 0);
+
1046 
+
1047  if (SUCCEEDED(hr))
+
1048  status = PLAYING;
+
1049  }
+
1050 
+
1051  return hr;
+
1052 }
+
1053 
+
1054 // +--------------------------------------------------------------------+
+
1055 
+
1056 HRESULT
+ +
1058 {
+
1059  if (!buffer) return E_FAIL;
+
1060 
+
1061  HRESULT hr = S_OK;
+
1062 
+
1063  if (IsPlaying())
+
1064  hr = Stop();
+
1065 
+
1066  if (flags & STREAMED) {
+
1067  RewindStream();
+
1068  StreamBlock();
+
1069  }
+
1070 
+
1071  else {
+
1072  hr = buffer->SetCurrentPosition(0);
+
1073  }
+
1074 
+
1075  if (SUCCEEDED(hr)) {
+
1076  status = READY;
+
1077  looped = 0;
+
1078  }
+
1079 
+
1080  return hr;
+
1081 }
+
1082 
+
1083 // +--------------------------------------------------------------------+
+
1084 
+
1085 HRESULT
+ +
1087 {
+
1088  if (status == DONE)
+
1089  return S_OK;
+
1090 
+
1091  HRESULT hr = Stop();
+
1092 
+
1093  if (SUCCEEDED(hr))
+
1094  status = READY;
+
1095 
+
1096  return hr;
+
1097 }
+
1098 
+
1099 // +--------------------------------------------------------------------+
+
1100 
+
1101 HRESULT
+ +
1103 {
+
1104  if (!buffer)
+
1105  return E_FAIL;
+
1106 
+
1107  if (!IsPlaying()) {
+
1108  status = DONE;
+
1109  return S_OK;
+
1110  }
+
1111 
+
1112  status = DONE;
+
1113  return buffer->Stop();
+
1114 }
+
1115 
+
1116 // +--------------------------------------------------------------------+
+
1117 
+
1118 double
+ +
1120 {
+
1121  double time_left = -1;
+
1122 
+
1123  if (IsPlaying() || IsReady()) {
+
1124  time_left = (double) stream_left /
+
1125  (double) wfex.nAvgBytesPerSec;
+
1126  }
+
1127 
+
1128  return time_left;
+
1129 }
+
1130 
+
1131 double
+ +
1133 {
+
1134  double time_elapsed = 0;
+
1135 
+
1136  if (IsPlaying()) {
+
1137  time_elapsed = total_time - GetTimeRemaining();
+
1138  }
+
1139 
+
1140  return time_elapsed;
+
1141 }
+
1142 
+
1143 // +--------------------------------------------------------------------+
+
1144 
+
1145 void
+ +
1147 {
+
1148  if (v > 0) v = 0;
+
1149  else if (v < -10000) v = -10000;
+
1150 
+
1151  volume = v;
+
1152  moved = true;
+
1153 }
+
1154 
+
1155 // +--------------------------------------------------------------------+
+
1156 
+
1157 long
+ +
1159 {
+
1160  long p = 10000;
+
1161 
+
1162  if (location.z) p = (long) fabs(location.x/location.z);
+
1163  if (p > 10000) p = 10000;
+
1164  if (location.x < 0) p = -p;
+
1165 
+
1166  return p;
+
1167 }
+
1168 
+
1169 void
+ +
1171 {
+
1172  if (p > 10000) p = 10000;
+
1173  if (p < -10000) p = -10000;
+
1174 
+
1175  location.x = (float) p;
+
1176  location.y = 0.0f;
+
1177  location.z = 1.0f;
+
1178  moved = true;
+
1179 }
+
1180 
+
1181 // +--------------------------------------------------------------------+
+
1182 
+
1183 void
+ +
1185 {
+
1186  location = l;
+
1187  moved = true;
+
1188 }
+
1189 
+
1190 void
+ +
1192 {
+
1193  velocity = v;
+
1194  moved = true;
+
1195 }
+
1196 
+
1197 // +--------------------------------------------------------------------+
+
1198 
+
1199 float
+ +
1201 {
+
1202  return min_dist;
+
1203 }
+
1204 
+
1205 void
+ +
1207 {
+
1208  min_dist = f;
+
1209  moved = true;
+
1210 }
+
1211 
+
1212 // +--------------------------------------------------------------------+
+
1213 
+
1214 float
+ +
1216 {
+
1217  return max_dist;
+
1218 }
+
1219 void
+ +
1221 {
+
1222  max_dist = f;
+
1223  moved = true;
+
1224 }
+
1225 
+
1226 
+
1227 // +--------------------------------------------------------------------+
+
1228 
+
1229 void
+
1230 SoundD3DError(const char* msg, HRESULT err)
+
1231 {
+
1232  Print(" SoundD3D: %s. [%s]\n", msg, DSErrStr(err));
+
1233 }
+
1234 
+
1235 char*
+
1236 DSErrStr(HRESULT err)
+
1237 {
+
1238  switch (err) {
+
1239  case DS_OK: return "DS_OK";
+
1240 
+
1241  case DSERR_ALLOCATED: return
+
1242  "The call failed because resources (such as a priority level) "
+
1243  "were already being used by another caller.";
+
1244 
+
1245  case DSERR_CONTROLUNAVAIL: return
+
1246  "The control (vol,pan,etc.) requested by the caller is not available.";
+
1247 
+
1248  case DSERR_INVALIDPARAM: return
+
1249  "An invalid parameter was passed to the returning function.";
+
1250 
+
1251  case DSERR_INVALIDCALL: return
+
1252  "This call is not valid for the current state of this object";
+
1253 
+
1254  case DSERR_GENERIC: return
+
1255  "An undetermined error occured inside the DirectSound subsystem";
+
1256 
+
1257  case DSERR_PRIOLEVELNEEDED: return
+
1258  "The caller does not have the priority level required for the function to succeed.";
+
1259 
+
1260  case DSERR_OUTOFMEMORY: return
+
1261  "Not enough free memory is available to complete the operation";
+
1262 
+
1263  case DSERR_BADFORMAT: return
+
1264  "The specified WAVE format is not supported";
+
1265 
+
1266  case DSERR_UNSUPPORTED: return
+
1267  "The function called is not supported at this time";
+
1268 
+
1269  case DSERR_NODRIVER: return
+
1270  "No sound driver is available for use";
+
1271 
+
1272  case DSERR_ALREADYINITIALIZED: return
+
1273  "This object is already initialized";
+
1274 
+
1275  case DSERR_NOAGGREGATION: return
+
1276  "This object does not support aggregation";
+
1277 
+
1278  case DSERR_BUFFERLOST: return
+
1279  "The buffer memory has been lost, and must be restored.";
+
1280 
+
1281  case DSERR_OTHERAPPHASPRIO: return
+
1282  "Another app has a higher priority level, preventing this call from succeeding.";
+
1283 
+
1284  case DSERR_UNINITIALIZED: return
+
1285  "This object has not been initialized.";
+
1286 
+
1287 #ifdef DIRECT_SOUND_3D
+
1288  case DSERR_NOINTERFACE: return
+
1289  "The requested COM interface is not available.";
+
1290 #endif
+
1291 
+
1292  default: return "Unknown Error Code";
+
1293  }
+
1294 
+
1295  return "Internal Error";
+
1296 }
+
1297 
+
+
+ + + + -- cgit v1.1