26 #ifdef DIRECT_SOUND_3D
32 void Print(
const char* msg, ...);
36 static int DS3D_report_errors = 1;
39 #define RELEASE(x) if (x) { x->Release(); x=NULL; }
47 : soundcard(0), primary(0)
54 #ifdef DIRECT_SOUND_3D
56 err = CoCreateInstance(CLSID_A3d, NULL, CLSCTX_INPROC_SERVER,
65 SoundD3DError(
"Proceding with standard DirectSoundCreate", 0);
68 err = DirectSoundCreate(0, &
soundcard, 0);
76 #ifdef DIRECT_SOUND_3D
81 err =
soundcard->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
90 memset(&caps, 0,
sizeof(caps));
91 caps.dwSize =
sizeof(caps);
100 if (caps.dwFlags & DSCAPS_EMULDRIVER)
101 Print(
" WARNING: using DirectSound emulated drivers\n");
106 #ifdef DIRECT_SOUND_3D
110 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
113 if (err == DSERR_CONTROLUNAVAIL) {
117 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLDEFAULT;
126 Print(
" WARNING: DirectSound3D is not available, simulating instead\n");
132 err =
primary->QueryInterface(IID_IDirectSound3DListener, (
void**)&
listener);
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);
145 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
177 #ifdef DIRECT_SOUND_3D
184 Print(
" SoundCardD3D: shutdown\n");
197 memset(&caps, 0,
sizeof(caps));
198 caps.dwSize =
sizeof(caps);
201 if (!(caps.dwFlags & DSCAPS_PRIMARY16BIT)) bits = 8;
202 if (!(caps.dwFlags & DSCAPS_PRIMARYSTEREO)) channels = 1;
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;
221 HRESULT
err = E_FAIL;
224 err =
primary->SetFormat(format);
226 return SUCCEEDED(err);
234 if (!format) format = &
wfex;
236 HRESULT
err = E_FAIL;
239 err =
primary->GetFormat(format,
sizeof(WAVEFORMATEX), 0);
241 return SUCCEEDED(err);
249 Print(
" SoundCardD3D Primary Buffer Format:\n");
250 Print(
" bits: %d\n",
wfex.wBitsPerSample);
252 Print(
" rate: %d\n\n",
wfex.nSamplesPerSec);
290 #ifdef DIRECT_SOUND_3D
291 listener->SetPosition((
float) pos.
x, (
float) pos.
z, (
float) pos.
y, DS3D_IMMEDIATE);
293 (float) cam.
vup().
x, (float) cam.
vup().
y, (float) cam.
vup().
z,
295 listener->SetVelocity(vel.
x, vel.
y, vel.
z, DS3D_IMMEDIATE);
352 if ((s->
GetFlags() & ok_sounds) == 0)
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)
371 CopyMemory(&
wfex, format,
sizeof(
wfex));
375 dsbd.dwFlags = DSBCAPS_CTRLVOLUME ;
378 #ifdef DIRECT_SOUND_3D
382 dsbd.dwFlags |= DSBCAPS_CTRL3D;
384 dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
386 dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
388 if (
flags & LOCALIZED)
389 dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
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),
409 CopyMemory(&
wfex, format,
sizeof(
wfex));
413 dsbd.dwFlags = DSBCAPS_CTRLVOLUME ;
416 #ifdef DIRECT_SOUND_3D
420 dsbd.dwFlags |= DSBCAPS_CTRL3D;
422 dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
424 if (
flags & LOCALIZED)
425 dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
434 ov_file = (OggVorbis_File*) pData;
440 data =
new(__FILE__,__LINE__) BYTE[len];
472 #ifdef DIRECT_SOUND_3D
485 HRESULT hr =
buffer->GetStatus(&dstat);
497 if (!(dstat & DSBSTATUS_PLAYING)) {
511 if (
flags & STREAMED) {
512 buffer->GetCurrentPosition(&
r, 0);
579 int current_bitstream;
580 DWORD bytes_read = 0;
585 retval = ov_read(
ov_file, p,
read_size-bytes_read, 0,2,1, ¤t_bitstream);
591 else if (retval < 0) {
598 bytes_read += retval;
625 fseek(
stream, 0, SEEK_END);
630 (
double)
wfex.nAvgBytesPerSec;
657 (
double)
wfex.nAvgBytesPerSec;
668 #ifdef DIRECT_SOUND_3D
670 sound3d->SetMinDistance(
min_dist, DS3D_IMMEDIATE);
671 sound3d->SetMaxDistance(
max_dist, DS3D_IMMEDIATE);
692 Vec3 direction = loc - ear_loc;
694 loc.
x = direction * listener.
vrt();
695 loc.
y = direction * listener.
vup();
696 loc.
z = direction * listener.
vpn();
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;
709 double d2 = (loc.
x*loc.
x) + (loc.
y*loc.
y) + (loc.
z*loc.
z);
714 vol -= (d2-mind2)/(maxd2-mind2) * (vol+10000);
717 if (vol < -10000) vol = -10000;
727 HRESULT hr =
buffer->SetPan((LONG) pan);
728 if (!SUCCEEDED(hr)) {
730 sprintf_s(warn,
"Warning could not set pan on buffer to %f", pan);
734 hr =
buffer->SetVolume((LONG) vol);
735 if (!SUCCEEDED(hr)) {
737 sprintf_s(warn,
"Warning: could not set volume on buffer to %f", vol);
744 const float c = 10000.0f;
747 float v_L = ears->
velocity * direction;
750 DWORD f_shift =
wfex.nSamplesPerSec;
755 f_shift =
wfex.nSamplesPerSec + 20;
757 f_shift =
wfex.nSamplesPerSec - 20;
761 double dist = sqrt(d2);
762 DWORD roll_off = (DWORD) (80 * dist/max_dist);
766 if (f_shift < 100) f_shift = 100;
767 if (f_shift > 100000) f_shift = 100000;
769 hr =
buffer->SetFrequency(f_shift);
770 if (!SUCCEEDED(hr)) {
772 sprintf_s(warn,
"Warning: could not set Doppler frequency on buffer to %d", f_shift);
820 DWORD buf_size =
wfex.nAvgBytesPerSec / 2;
821 DWORD safety_zone = buf_size * 2;
838 fopen_s(&
stream, name,
"rb");
847 fseek(
stream, 0, SEEK_END);
852 (
double)
wfex.nAvgBytesPerSec;
886 DWORD buf_size =
wfex.nAvgBytesPerSec / 2;
887 DWORD safety_zone = buf_size * 2;
907 (
double)
wfex.nAvgBytesPerSec;
955 hr =
buffer->Lock(
w, bytes, &dest1, &size1, &dest2, &size2, 0);
957 if (hr == DSERR_BUFFERLOST) {
959 hr =
buffer->Lock(
w, bytes, &dest1, &size1, &dest2, &size2, 0);
963 CopyMemory(dest1, data, size1);
965 CopyMemory(dest2, data + size1, size2);
973 hr =
buffer->Unlock(dest1, size1, dest2, size2);
997 dsbd.dwBufferBytes = bytes;
1003 SoundD3DError(
"AllocateBuffer: could not create buffer", hr);
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);
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);
1031 if (!
buffer)
return E_FAIL;
1033 HRESULT hr = E_FAIL;
1043 hr =
buffer->Play(0, 0, DSBPLAY_LOOPING);
1045 hr =
buffer->Play(0, 0, 0);
1059 if (!
buffer)
return E_FAIL;
1072 hr =
buffer->SetCurrentPosition(0);
1075 if (SUCCEEDED(hr)) {
1091 HRESULT hr =
Stop();
1121 double time_left = -1;
1125 (
double)
wfex.nAvgBytesPerSec;
1134 double time_elapsed = 0;
1140 return time_elapsed;
1149 else if (v < -10000) v = -10000;
1163 if (p > 10000) p = 10000;
1172 if (p > 10000) p = 10000;
1173 if (p < -10000) p = -10000;
1239 case DS_OK:
return "DS_OK";
1241 case DSERR_ALLOCATED:
return
1242 "The call failed because resources (such as a priority level) "
1243 "were already being used by another caller.";
1245 case DSERR_CONTROLUNAVAIL:
return
1246 "The control (vol,pan,etc.) requested by the caller is not available.";
1248 case DSERR_INVALIDPARAM:
return
1249 "An invalid parameter was passed to the returning function.";
1251 case DSERR_INVALIDCALL:
return
1252 "This call is not valid for the current state of this object";
1254 case DSERR_GENERIC:
return
1255 "An undetermined error occured inside the DirectSound subsystem";
1257 case DSERR_PRIOLEVELNEEDED:
return
1258 "The caller does not have the priority level required for the function to succeed.";
1260 case DSERR_OUTOFMEMORY:
return
1261 "Not enough free memory is available to complete the operation";
1263 case DSERR_BADFORMAT:
return
1264 "The specified WAVE format is not supported";
1266 case DSERR_UNSUPPORTED:
return
1267 "The function called is not supported at this time";
1269 case DSERR_NODRIVER:
return
1270 "No sound driver is available for use";
1272 case DSERR_ALREADYINITIALIZED:
return
1273 "This object is already initialized";
1275 case DSERR_NOAGGREGATION:
return
1276 "This object does not support aggregation";
1278 case DSERR_BUFFERLOST:
return
1279 "The buffer memory has been lost, and must be restored.";
1281 case DSERR_OTHERAPPHASPRIO:
return
1282 "Another app has a higher priority level, preventing this call from succeeding.";
1284 case DSERR_UNINITIALIZED:
return
1285 "This object has not been initialized.";
1287 #ifdef DIRECT_SOUND_3D
1288 case DSERR_NOINTERFACE:
return
1289 "The requested COM interface is not available.";
1292 default:
return "Unknown Error Code";
1295 return "Internal Error";