summaryrefslogtreecommitdiffhomepage
path: root/nGenEx/SoundD3D.cpp
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2021-09-30 16:46:36 +0200
committerAki <please@ignore.pl>2021-09-30 16:46:36 +0200
commit966fe28c59f59fc8be795c8215b9352435982445 (patch)
tree2979f8d30b63eb83310b78c62463915cb409989f /nGenEx/SoundD3D.cpp
parentc9b298cf8da03e6a9825eade5b764b0ed4804dc1 (diff)
downloadstarshatter-966fe28c59f59fc8be795c8215b9352435982445.zip
starshatter-966fe28c59f59fc8be795c8215b9352435982445.tar.gz
starshatter-966fe28c59f59fc8be795c8215b9352435982445.tar.bz2
Merged nGenEx and Parser into Stars45
Diffstat (limited to 'nGenEx/SoundD3D.cpp')
-rw-r--r--nGenEx/SoundD3D.cpp1321
1 files changed, 0 insertions, 1321 deletions
diff --git a/nGenEx/SoundD3D.cpp b/nGenEx/SoundD3D.cpp
deleted file mode 100644
index a148e69..0000000
--- a/nGenEx/SoundD3D.cpp
+++ /dev/null
@@ -1,1321 +0,0 @@
-/* Starshatter OpenSource Distribution
- Copyright (c) 1997-2004, Destroyer Studios LLC.
- All Rights Reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name "Destroyer Studios" nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- SUBSYSTEM: nGenEx.lib
- FILE: SoundD3D.cpp
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- DirectSound and DirectSound3D (sound card) class
-*/
-
-//#define INITGUID
-#include <objbase.h>
-#include <cguid.h>
-#include <mmsystem.h>
-#include <dsound.h>
-
-
-#include "MemDebug.h"
-#include "SoundD3D.h"
-#include "Game.h"
-
-#ifdef DIRECT_SOUND_3D
-#include "ia3d.h"
-#endif
-
-// +--------------------------------------------------------------------+
-
-void Print(const char* msg, ...);
-char* DSErrStr(HRESULT dserr);
-void SoundD3DError(const char* msg, HRESULT dserr);
-
-static int DS3D_report_errors = 1;
-
-#ifndef RELEASE
-#define RELEASE(x) if (x) { x->Release(); x=NULL; }
-#endif
-
-// +====================================================================+
-// | SOUND CARD D3D
-// +====================================================================+
-
-SoundCardD3D::SoundCardD3D(HWND hwnd)
-: soundcard(0), primary(0)
-{
- HRESULT err = 0;
- status = SC_ERROR;
-
- // 1) Get interface to DirectSound object:
-
-#ifdef DIRECT_SOUND_3D
- CoInitialize(NULL);
- err = CoCreateInstance(CLSID_A3d, NULL, CLSCTX_INPROC_SERVER,
- IID_IDirectSound, (VOID **)&soundcard);
-
- if (SUCCEEDED(err)) {
- soundcard->Initialize(NULL);
- SoundD3DError("Initialized Aureal3D Sound", 0);
- }
- else {
- SoundD3DError("Could not initialize Aureal3D Sound", err);
- SoundD3DError("Proceding with standard DirectSoundCreate", 0);
-#endif
-
- err = DirectSoundCreate(0, &soundcard, 0);
- if (FAILED(err)) {
- SoundD3DError("Could not create DirectSound object.", err);
- soundcard = 0;
- primary = 0;
- return;
- }
-
-#ifdef DIRECT_SOUND_3D
- }
-#endif
-
- // 2) Set the cooperative level:
- err = soundcard->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
- if (FAILED(err)) {
- SoundD3DError("Could not set cooperative level.", err);
- RELEASE(soundcard);
- return;
- }
-
- // Prepare to initialize the primary buffer:
- DSCAPS caps;
- memset(&caps, 0, sizeof(caps));
- caps.dwSize = sizeof(caps);
-
- err = soundcard->GetCaps(&caps);
- if (FAILED(err)) {
- SoundD3DError("Could not get soundcard caps.", err);
- RELEASE(soundcard);
- return;
- }
-
- if (caps.dwFlags & DSCAPS_EMULDRIVER)
- Print(" WARNING: using DirectSound emulated drivers\n");
-
- memset(&dsbd, 0, sizeof(dsbd));
- dsbd.dwSize = sizeof(dsbd);
-
-#ifdef DIRECT_SOUND_3D
- int use_ds3d = true;
-
- // 3) Set up the primary buffer (try to use DS3D):
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
-
- err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
- if (err == DSERR_CONTROLUNAVAIL) {
- use_ds3d = false;
-
- // try again, without using DS3D
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLDEFAULT;
-
- err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
- if (FAILED(err)) {
- SoundD3DError("Could not initialize primary buffer", err);
- RELEASE(soundcard);
- return;
- }
- else {
- Print(" WARNING: DirectSound3D is not available, simulating instead\n");
- }
- }
-
- // 4) Set up the listener:
- if (primary && use_ds3d) {
- err = primary->QueryInterface(IID_IDirectSound3DListener, (void**)&listener);
- if (FAILED(err)) {
- SoundD3DError("Could not get listener interface", err);
- }
- else {
- listener->SetPosition(0.0f, 0.0f, 0.0f, DS3D_IMMEDIATE);
- listener->SetOrientation(0.0f, 0.0f, 1.0f,
- 0.0f, 1.0f, 0.0f, DS3D_IMMEDIATE);
- }
- }
-
-#else
- // 3) Set up the primary buffer:
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
-
- err = soundcard->CreateSoundBuffer(&dsbd, &primary, 0);
- if (FAILED(err)) {
- SoundD3DError("Could not initialize primary buffer", err);
- RELEASE(soundcard);
- return;
- }
-#endif
-
- // 5) Set primary buffer parameters to 16 bit STEREO at 44kHz
- SetFormat(16, 2, 44100);
-
- // read back the result format and display to the log file:
- GetFormat(0);
- ShowFormat();
-
- status = SC_OK;
-}
-
-// +--------------------------------------------------------------------+
-
-SoundCardD3D::~SoundCardD3D()
-{
- ListIter<Sound> iter = sounds;
- while (++iter) {
- Sound* s = iter.value();
- s->Stop();
- }
-
- sounds.destroy();
-
-#ifdef DIRECT_SOUND_3D
- RELEASE(listener);
-#endif
-
- RELEASE(primary);
- RELEASE(soundcard);
-
- Print(" SoundCardD3D: shutdown\n");
-
- status = SC_UNINITIALIZED;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::SetFormat(int bits, int channels, int hertz)
-{
- if (!soundcard) return false;
-
- DSCAPS caps;
- memset(&caps, 0, sizeof(caps));
- caps.dwSize = sizeof(caps);
- soundcard->GetCaps(&caps);
-
- if (!(caps.dwFlags & DSCAPS_PRIMARY16BIT)) bits = 8;
- if (!(caps.dwFlags & DSCAPS_PRIMARYSTEREO)) channels = 1;
-
- memset(&wfex, 0, sizeof(wfex));
-
- wfex.wFormatTag = WAVE_FORMAT_PCM;
- wfex.nChannels = channels;
- wfex.nSamplesPerSec = hertz;
- wfex.nBlockAlign = (channels * bits) / 8;
- wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
- wfex.wBitsPerSample = bits;
-
- return SetFormat(&wfex);
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::SetFormat(LPWAVEFORMATEX format)
-{
- HRESULT err = E_FAIL;
-
- if (primary)
- err = primary->SetFormat(format);
-
- return SUCCEEDED(err);
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::GetFormat(LPWAVEFORMATEX format)
-{
- if (!format) format = &wfex;
-
- HRESULT err = E_FAIL;
-
- if (primary)
- err = primary->GetFormat(format, sizeof(WAVEFORMATEX), 0);
-
- return SUCCEEDED(err);
-}
-
-// +--------------------------------------------------------------------+
-
-void
-SoundCardD3D::ShowFormat()
-{
- Print(" SoundCardD3D Primary Buffer Format:\n");
- Print(" bits: %d\n", wfex.wBitsPerSample);
- Print(" chls: %d\n", wfex.nChannels);
- Print(" rate: %d\n\n", wfex.nSamplesPerSec);
-}
-
-// +--------------------------------------------------------------------+
-
-Sound*
-SoundCardD3D::CreateSound(DWORD flags, LPWAVEFORMATEX format)
-{
- if (!soundcard) return 0;
-
- Sound* result = new(__FILE__,__LINE__) SoundD3D(soundcard, flags, format);
- if (result) AddSound(result);
- return result;
-}
-
-// +--------------------------------------------------------------------+
-
-Sound*
-SoundCardD3D::CreateSound(DWORD flags, LPWAVEFORMATEX format, DWORD len, LPBYTE data)
-{
- if (!soundcard) return 0;
- Sound* result = new(__FILE__,__LINE__) SoundD3D(soundcard, flags, format, len, data);
-
- if (flags & (Sound::STREAMED | Sound::OGGVORBIS)) {
- if (result)
- AddSound(result);
- }
-
- return result;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-SoundCardD3D::SetListener(const Camera& cam, const Vec3& vel)
-{
- Point pos = cam.Pos();
-
-#ifdef DIRECT_SOUND_3D
- listener->SetPosition((float) pos.x, (float) pos.z, (float) pos.y, DS3D_IMMEDIATE);
- listener->SetOrientation((float) cam.vpn().x, (float) cam.vpn().y, (float) cam.vpn().z,
- (float) cam.vup().x, (float) cam.vup().y, (float) cam.vup().z,
- DS3D_IMMEDIATE);
- listener->SetVelocity(vel.x, vel.y, vel.z, DS3D_IMMEDIATE);
-#else
- listener.Clone(cam);
- listener.MoveTo(pos.x, pos.z, pos.y);
- velocity = vel;
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::Pause()
-{
- AutoThreadSync a(sync);
-
- ListIter<Sound> iter = sounds;
- while (++iter) {
- Sound* s = iter.value();
-
- if ((s->GetFlags() & Sound::INTERFACE) == 0)
- s->Pause();
- }
-
- return true;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::Resume()
-{
- AutoThreadSync a(sync);
-
- ListIter<Sound> iter = sounds;
- while (++iter) {
- Sound* s = iter.value();
-
- if (s->IsReady())
- s->Play();
- }
-
- return true;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-SoundCardD3D::StopSoundEffects()
-{
- AutoThreadSync a(sync);
-
- DWORD ok_sounds = (Sound::INTERFACE | Sound::OGGVORBIS | Sound::RESOURCE);
-
- ListIter<Sound> iter = sounds;
- while (++iter) {
- Sound* s = iter.value();
-
- if ((s->GetFlags() & ok_sounds) == 0)
- s->Stop();
- }
-
- return true;
-}
-
-// +====================================================================+
-// | SOUND D3D
-// +====================================================================+
-
-SoundD3D::SoundD3D(LPDIRECTSOUND card, DWORD flag_req, LPWAVEFORMATEX format)
-: soundcard(card), buffer(0), min_dist(1.0f), max_dist(100000.0f),
-stream(0), stream_left(0), min_safety(0), read_size(0), transfer(0), w(0), r(0),
-stream_offset(0), data_len(0), data(0), moved(false), eos_written(false), eos_latch(0),
-ov_file(0), total_time(0)
-{
- flags = flag_req;
-
- CopyMemory(&wfex, format, sizeof(wfex));
- ZeroMemory(&dsbd, sizeof(dsbd));
-
- dsbd.dwSize = sizeof(dsbd);
- dsbd.dwFlags = DSBCAPS_CTRLVOLUME /* | DSBCAPS_GETCURRENTPOSITION2 */;
- dsbd.lpwfxFormat = &wfex;
-
-#ifdef DIRECT_SOUND_3D
- sound3d = 0;
- if (flags & LOCALIZED)
- if (flags & LOC_3D)
- dsbd.dwFlags |= DSBCAPS_CTRL3D;
- else
- dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
-#else
- dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
-
- if (flags & LOCALIZED)
- dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
-#endif
-
-}
-
-// +--------------------------------------------------------------------+
-// SOUND RESOURCE CONSTRUCTOR:
-// (Now also used to create Ogg Vorbis streaming sound objects)
-
-SoundD3D::SoundD3D(LPDIRECTSOUND card, DWORD flag_req, LPWAVEFORMATEX format, DWORD len, LPBYTE pData)
-: soundcard(card), buffer(0), min_dist(1.0f), max_dist(100000.0f),
-stream(0), stream_left(0), min_safety(0), read_size(0), transfer(0), w(0), r(0),
-stream_offset(0), data_len(0), data(0), moved(false), eos_written(false), eos_latch(0),
-ov_file(0)
-{
- flags = flag_req;
-
- if (!(flags & (STREAMED | OGGVORBIS)))
- flags = flag_req | RESOURCE;
-
- CopyMemory(&wfex, format, sizeof(wfex));
- ZeroMemory(&dsbd, sizeof(dsbd));
-
- dsbd.dwSize = sizeof(dsbd);
- dsbd.dwFlags = DSBCAPS_CTRLVOLUME /* | DSBCAPS_GETCURRENTPOSITION2 */;
- dsbd.lpwfxFormat = &wfex;
-
-#ifdef DIRECT_SOUND_3D
- sound3d = 0;
- if (flags & LOCALIZED)
- if (flags & LOC_3D)
- dsbd.dwFlags |= DSBCAPS_CTRL3D;
- else
- dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
-#else
- if (flags & LOCALIZED)
- dsbd.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
-#endif
-
- if (len) {
- // If this is an OGG VORBIS streaming sound,
- // the parameter that normally points to the actual data
- // is used to pass in an Ogg Vorbis file structure instead:
-
- if (flags & OGGVORBIS) {
- ov_file = (OggVorbis_File*) pData;
- StreamOggFile();
- }
-
- else {
- data_len = len;
- data = new(__FILE__,__LINE__) BYTE[len];
-
- if (!data) {
- data_len = 0;
- }
-
- else {
- CopyMemory(data, pData, data_len);
- Load(data_len, data);
- }
- }
- }
-}
-
-// +--------------------------------------------------------------------+
-
-SoundD3D::~SoundD3D()
-{
- delete [] data;
- delete [] transfer;
-
- if (ov_file) {
- ov_clear(ov_file);
- delete ov_file;
- }
-
- else if (stream) {
- fclose(stream);
- }
-
- RELEASE(buffer);
-
-#ifdef DIRECT_SOUND_3D
- RELEASE(sound3d);
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-SoundD3D::Update()
-{
- if (!buffer || status != PLAYING) return; // nothing to do
-
- DWORD dstat;
- HRESULT hr = buffer->GetStatus(&dstat);
- if (FAILED(hr)) {
- SoundD3DError("Update: GetStatus failed", hr);
- return;
- }
-
- AutoThreadSync a(sync);
-
- if (sound_check) sound_check->Update(this);
-
- if (!Game::Paused() || flags & STREAMED) {
- // see if we are done:
- if (!(dstat & DSBSTATUS_PLAYING)) {
- status = DONE;
- buffer->Stop();
- return;
- }
-
- // if not done, see if we need to change location params:
- if (moved) {
- Localize();
- }
- }
-
- // if not done, see if we need to load more data
- // into the streaming buffer:
- if (flags & STREAMED) {
- buffer->GetCurrentPosition(&r, 0);
-
- DWORD data_left;
- if (w > r)
- data_left = w - r;
- else
- data_left = w + (read_size + min_safety) - r;
-
- // getting low, fill 'er up:
- if (eos_written || data_left <= min_safety) {
- StreamBlock();
-
- if (stream_left == 0) {
- // if this is the end of a looping stream,
- if (flags & LOOP) {
- RewindStream();
- looped++;
- }
- else {
- if (!eos_written) {
- eos_written = true;
- eos_latch = 3;
- }
-
- else if (--eos_latch == 0) {
- status = DONE;
- buffer->Stop();
- }
- }
- }
-
- status = PLAYING;
- }
- }
-}
-
-void
-SoundD3D::StreamBlock()
-{
- if (flags & OGGVORBIS) {
- StreamOggBlock();
- return;
- }
-
- if (!stream || !stream_left)
- return;
-
- if (stream_left < read_size) {
- if (stream_left > 0) {
- fread(transfer, stream_left, 1, stream);
- Load(stream_left, transfer);
- stream_left = 0;
- }
- }
-
- else if (read_size > 0) {
- fread(transfer, read_size, 1, stream);
- Load(read_size, transfer);
- stream_left -= read_size;
- }
-}
-
-int ogg_read_error_count = 0;
-
-void
-SoundD3D::StreamOggBlock()
-{
- int current_bitstream;
- DWORD bytes_read = 0;
- long retval = 0;
- char* p = (char*) transfer;
-
- while (stream_left && bytes_read < read_size) {
- retval = ov_read(ov_file, p, read_size-bytes_read, 0,2,1, &current_bitstream);
-
- if (retval == 0) {
- /* EOF */
- stream_left = 0;
- }
- else if (retval < 0) {
- /* error in the stream. Not a problem, just reporting it in
- case the app cares. In this case, we don't. */
- ogg_read_error_count++;
- }
- else {
- /* we don't bother dealing with sample rate changes, etc, but you'll have to ??? */
- bytes_read += retval;
- stream_left -= retval;
- p += retval;
- }
- }
-
- if (bytes_read)
- Load(bytes_read, transfer);
-}
-
-void
-SoundD3D::RewindStream()
-{
- if (flags & OGGVORBIS) {
- RewindOggStream();
- return;
- }
-
- if (!stream || !buffer)
- return;
-
- // rewind the stream and keep going...
- eos_written = false;
- eos_latch = 0;
- read_size = wfex.nAvgBytesPerSec / 2;
-
- // find the size of the file:
- fseek(stream, 0, SEEK_END);
- stream_left = ftell(stream) - stream_offset;
- fseek(stream, stream_offset, SEEK_SET);
-
- total_time = (double) stream_left /
- (double) wfex.nAvgBytesPerSec;
-
- if (stream_left < read_size) {
- status = DONE;
- buffer->Stop();
- }
-}
-
-void
-SoundD3D::RewindOggStream()
-{
- if (!ov_file || !buffer)
- return;
-
- // rewind the stream and keep going...
- eos_written = false;
- eos_latch = 0;
- read_size = wfex.nAvgBytesPerSec / 2;
-
- // set the stream pointer back to the beginning:
- ov_pcm_seek(ov_file, 0);
-
- // find the size of the file:
- stream_left = (DWORD) ov_pcm_total(ov_file,-1);
- stream_offset = 0;
-
- total_time = (double) stream_left /
- (double) wfex.nAvgBytesPerSec;
-
- if (stream_left < read_size) {
- status = DONE;
- buffer->Stop();
- }
-}
-
-void
-SoundD3D::Localize()
-{
-#ifdef DIRECT_SOUND_3D
- if (sound3d) {
- sound3d->SetMinDistance(min_dist, DS3D_IMMEDIATE);
- sound3d->SetMaxDistance(max_dist, DS3D_IMMEDIATE);
- sound3d->SetPosition(location.x, location.y, location.z, DS3D_IMMEDIATE);
- sound3d->SetVelocity(velocity.x, velocity.y, velocity.z, DS3D_IMMEDIATE);
- }
-
-#else
-
- // if no buffer, nothing to do:
- if (!buffer) {
- moved = false;
- return;
- }
-
- // Compute pan and volume from scratch:
-
- if ((flags & LOC_3D) && creator) {
- Vec3 loc = location;
-
- SoundCardD3D* ears = (SoundCardD3D*) creator;
- Camera& listener = ears->listener;
- Vec3 ear_loc = listener.Pos(); ear_loc.SwapYZ();
- Vec3 direction = loc - ear_loc;
-
- loc.x = direction * listener.vrt();
- loc.y = direction * listener.vup();
- loc.z = direction * listener.vpn();
-
- double pan = 10000;
- if (loc.z != 0.0f) pan = fabs(1000.0f * loc.x / loc.z);
- if (pan > 10000) pan = 10000;
- if (loc.x < 0) pan = -pan;
-
- if (volume > 0)
- volume = 0;
-
- double vol = volume;
- double mind2 = min_dist * min_dist;
- double maxd2 = max_dist * max_dist;
- double d2 = (loc.x*loc.x) + (loc.y*loc.y) + (loc.z*loc.z);
-
- if (d2 > maxd2)
- vol = -10000;
- else if (d2 > mind2)
- vol -= (d2-mind2)/(maxd2-mind2) * (vol+10000);
-
- // clamp volume to legal range:
- if (vol < -10000) vol = -10000;
- else if (vol > volume) vol = volume;
-
- /***
- Print("Localize: ears = (%f, %f, %f)\n", ear_loc.x, ear_loc.y, ear_loc.z);
- Print(" world = (%f, %f, %f)\n", location.x, location.y, location.z);
- Print(" view = (%f, %f, %f)\n", loc.x, loc.y, loc.z);
- Print(" Pan=%f Volume=%f\n", pan, vol);
- /***/
-
- HRESULT hr = buffer->SetPan((LONG) pan);
- if (!SUCCEEDED(hr)) {
- char warn[512];
- sprintf_s(warn, "Warning could not set pan on buffer to %f", pan);
- SoundD3DError(warn, hr);
- }
-
- hr = buffer->SetVolume((LONG) vol);
- if (!SUCCEEDED(hr)) {
- char warn[512];
- sprintf_s(warn, "Warning: could not set volume on buffer to %f", vol);
- SoundD3DError(warn, hr);
- }
-
- // if not too far to hear...
- if ((flags & DOPPLER) && (d2 < maxd2)) {
- // COMPUTE DOPPLER SHIFT:
- const float c = 10000.0f;
-
- direction.Normalize();
- float v_L = ears->velocity * direction;
- float v_S = velocity * direction;
-
- DWORD f_shift = wfex.nSamplesPerSec;
-
- if (v_L != v_S) {
- // towards listener:
- if (v_S < 0)
- f_shift = wfex.nSamplesPerSec + 20;
- else
- f_shift = wfex.nSamplesPerSec - 20;
- }
-
- // distance rolloff of high frequencies:
- double dist = sqrt(d2);
- DWORD roll_off = (DWORD) (80 * dist/max_dist);
-
- f_shift -= roll_off;
-
- if (f_shift < 100) f_shift = 100;
- if (f_shift > 100000) f_shift = 100000;
-
- hr = buffer->SetFrequency(f_shift);
- if (!SUCCEEDED(hr)) {
- char warn[512];
- sprintf_s(warn, "Warning: could not set Doppler frequency on buffer to %d", f_shift); //-V576
- SoundD3DError(warn, hr);
- }
- }
- }
- else {
- buffer->SetPan((LONG) location.x);
- buffer->SetVolume((LONG) volume);
- }
-#endif
-
- moved = false;
-}
-
-// +--------------------------------------------------------------------+
-
-Sound*
-SoundD3D::Duplicate()
-{
- Sound* sound = 0;
-
- if (flags & RESOURCE) {
- sound = Sound::Create(flags & ~RESOURCE, &wfex);
-
- if (sound && !(flags & STREAMED)) {
- sound->SetMinDistance(min_dist);
- sound->SetMaxDistance(max_dist);
-
- if (!buffer) {
- sound->Load(data_len, data);
- }
-
- else {
- SoundD3D* s3d = (SoundD3D*) sound;
- soundcard->DuplicateSoundBuffer(buffer, &s3d->buffer);
- sound->Rewind();
- }
- }
- }
-
- return sound;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::StreamFile(const char* name, DWORD offset)
-{
- DWORD buf_size = wfex.nAvgBytesPerSec / 2;
- DWORD safety_zone = buf_size * 2;
-
- if (stream) {
- delete[] transfer;
- transfer = 0;
- fclose(stream);
- }
-
- status = UNINITIALIZED;
- stream_left = 0;
- stream_offset = offset;
-
- eos_written = false;
- eos_latch = 0;
- min_safety = safety_zone;
- read_size = buf_size;
-
- fopen_s(&stream, name, "rb");
-
- // open the stream:
- if (stream == 0) {
- SoundD3DError("StreamFile: could not open stream", E_FAIL);
- return E_FAIL;
- }
-
- // find the size of the file:
- fseek(stream, 0, SEEK_END);
- stream_left = ftell(stream) - offset;
- fseek(stream, stream_offset, SEEK_SET);
-
- total_time = (double) stream_left /
- (double) wfex.nAvgBytesPerSec;
-
- if (stream_left < read_size) {
- read_size = stream_left;
- }
-
- HRESULT hr = AllocateBuffer(read_size + min_safety);
-
- if (FAILED(hr))
- return hr;
-
- flags |= STREAMED;
-
- // preload the buffer:
- w = r = 0;
- transfer = new(__FILE__,__LINE__) BYTE[read_size + 1024];
-
- if (!transfer) {
- hr = E_FAIL;
- }
-
- else {
- ZeroMemory(transfer, read_size+1024);
- StreamBlock();
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::StreamOggFile()
-{
- DWORD buf_size = wfex.nAvgBytesPerSec / 2;
- DWORD safety_zone = buf_size * 2;
-
- if (stream) {
- delete[] transfer;
- fclose(stream);
-
- transfer = 0;
- stream = 0;
- }
-
- status = UNINITIALIZED;
- stream_left = (DWORD) ov_pcm_total(ov_file,-1);
- stream_offset = 0;
-
- eos_written = false;
- eos_latch = 0;
- min_safety = safety_zone;
- read_size = buf_size;
-
- total_time = (double) stream_left /
- (double) wfex.nAvgBytesPerSec;
-
- if (stream_left < read_size) {
- read_size = stream_left;
- }
-
- HRESULT hr = AllocateBuffer(read_size + min_safety);
-
- if (FAILED(hr))
- return hr;
-
- flags |= STREAMED | OGGVORBIS;
-
- // preload the buffer:
- w = r = 0;
- transfer = new(__FILE__,__LINE__) BYTE[read_size + 1024];
-
- if (!transfer) {
- hr = E_FAIL;
- }
-
- else {
- ZeroMemory(transfer, read_size+1024);
- StreamOggBlock();
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::Load(DWORD bytes, BYTE* data)
-{
- status = UNINITIALIZED;
-
- HRESULT hr;
-
- if (!buffer) {
- hr = AllocateBuffer(bytes);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- LPVOID dest1, dest2;
- DWORD size1, size2;
-
- hr = buffer->Lock(w, bytes, &dest1, &size1, &dest2, &size2, 0);
-
- if (hr == DSERR_BUFFERLOST) {
- buffer->Restore();
- hr = buffer->Lock(w, bytes, &dest1, &size1, &dest2, &size2, 0);
- }
-
- if (SUCCEEDED(hr)) {
- CopyMemory(dest1, data, size1);
- if (dest2) {
- CopyMemory(dest2, data + size1, size2);
- }
-
- if (flags & STREAMED)
- w = (w + size1 + size2) % (read_size + min_safety);
- else
- w += size1 + size2;
-
- hr = buffer->Unlock(dest1, size1, dest2, size2);
- if (FAILED(hr)) {
- SoundD3DError("Load: could not unlock buffer", hr);
- }
- }
- else {
- SoundD3DError("Load: could not lock buffer", hr);
- }
-
- if (SUCCEEDED(hr)) {
- status = READY;
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::AllocateBuffer(DWORD bytes)
-{
- HRESULT hr = S_OK;
-
- if (!buffer) {
- dsbd.dwBufferBytes = bytes;
-
- if (soundcard) {
- hr = soundcard->CreateSoundBuffer(&dsbd, &buffer, NULL);
-
- if (FAILED(hr)) {
- SoundD3DError("AllocateBuffer: could not create buffer", hr);
-
- Print(" dsbd.dwSize = %8d\n", dsbd.dwSize);
- Print(" dsbd.dwFlags = %08x\n", dsbd.dwFlags);
- Print(" dsbd.dwBufferBytes = %8d\n", dsbd.dwBufferBytes);
- Print(" dsbd.lpwfxFormat = %08x\n", dsbd.lpwfxFormat);
-
- if (dsbd.lpwfxFormat) {
- Print(" wfex.wBitsPerSample = %8d\n", dsbd.lpwfxFormat->wBitsPerSample);
- Print(" wfex.nChannels = %8d\n", dsbd.lpwfxFormat->nChannels);
- Print(" wfex.nSamplesPerSec = %8d\n", dsbd.lpwfxFormat->nSamplesPerSec);
- }
- }
- }
- else {
- SoundD3DError("AllocateBuffer: soundcard is null", E_FAIL);
- }
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::Play()
-{
- if (IsPlaying()) return S_OK;
- if (!buffer) return E_FAIL;
-
- HRESULT hr = E_FAIL;
-
- if (IsDone())
- hr = Rewind();
-
- if (IsReady()) {
- if (moved)
- Localize();
-
- if (flags & LOOP || flags & STREAMED)
- hr = buffer->Play(0, 0, DSBPLAY_LOOPING);
- else
- hr = buffer->Play(0, 0, 0);
-
- if (SUCCEEDED(hr))
- status = PLAYING;
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::Rewind()
-{
- if (!buffer) return E_FAIL;
-
- HRESULT hr = S_OK;
-
- if (IsPlaying())
- hr = Stop();
-
- if (flags & STREAMED) {
- RewindStream();
- StreamBlock();
- }
-
- else {
- hr = buffer->SetCurrentPosition(0);
- }
-
- if (SUCCEEDED(hr)) {
- status = READY;
- looped = 0;
- }
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::Pause()
-{
- if (status == DONE)
- return S_OK;
-
- HRESULT hr = Stop();
-
- if (SUCCEEDED(hr))
- status = READY;
-
- return hr;
-}
-
-// +--------------------------------------------------------------------+
-
-HRESULT
-SoundD3D::Stop()
-{
- if (!buffer)
- return E_FAIL;
-
- if (!IsPlaying()) {
- status = DONE;
- return S_OK;
- }
-
- status = DONE;
- return buffer->Stop();
-}
-
-// +--------------------------------------------------------------------+
-
-double
-SoundD3D::GetTimeRemaining() const
-{
- double time_left = -1;
-
- if (IsPlaying() || IsReady()) {
- time_left = (double) stream_left /
- (double) wfex.nAvgBytesPerSec;
- }
-
- return time_left;
-}
-
-double
-SoundD3D::GetTimeElapsed() const
-{
- double time_elapsed = 0;
-
- if (IsPlaying()) {
- time_elapsed = total_time - GetTimeRemaining();
- }
-
- return time_elapsed;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-SoundD3D::SetVolume(long v)
-{
- if (v > 0) v = 0;
- else if (v < -10000) v = -10000;
-
- volume = v;
- moved = true;
-}
-
-// +--------------------------------------------------------------------+
-
-long
-SoundD3D::GetPan() const
-{
- long p = 10000;
-
- if (location.z) p = (long) fabs(location.x/location.z);
- if (p > 10000) p = 10000;
- if (location.x < 0) p = -p;
-
- return p;
-}
-
-void
-SoundD3D::SetPan(long p)
-{
- if (p > 10000) p = 10000;
- if (p < -10000) p = -10000;
-
- location.x = (float) p;
- location.y = 0.0f;
- location.z = 1.0f;
- moved = true;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-SoundD3D::SetLocation(const Vec3& l)
-{
- location = l;
- moved = true;
-}
-
-void
-SoundD3D::SetVelocity(const Vec3& v)
-{
- velocity = v;
- moved = true;
-}
-
-// +--------------------------------------------------------------------+
-
-float
-SoundD3D::GetMinDistance() const
-{
- return min_dist;
-}
-
-void
-SoundD3D::SetMinDistance(float f)
-{
- min_dist = f;
- moved = true;
-}
-
-// +--------------------------------------------------------------------+
-
-float
-SoundD3D::GetMaxDistance() const
-{
- return max_dist;
-}
-void
-SoundD3D::SetMaxDistance(float f)
-{
- max_dist = f;
- moved = true;
-}
-
-
-// +--------------------------------------------------------------------+
-
-void
-SoundD3DError(const char* msg, HRESULT err)
-{
- Print(" SoundD3D: %s. [%s]\n", msg, DSErrStr(err));
-}
-
-char*
-DSErrStr(HRESULT err)
-{
- switch (err) {
- case DS_OK: return "DS_OK";
-
- case DSERR_ALLOCATED: return
- "The call failed because resources (such as a priority level) "
- "were already being used by another caller.";
-
- case DSERR_CONTROLUNAVAIL: return
- "The control (vol,pan,etc.) requested by the caller is not available.";
-
- case DSERR_INVALIDPARAM: return
- "An invalid parameter was passed to the returning function.";
-
- case DSERR_INVALIDCALL: return
- "This call is not valid for the current state of this object";
-
- case DSERR_GENERIC: return
- "An undetermined error occured inside the DirectSound subsystem";
-
- case DSERR_PRIOLEVELNEEDED: return
- "The caller does not have the priority level required for the function to succeed.";
-
- case DSERR_OUTOFMEMORY: return
- "Not enough free memory is available to complete the operation";
-
- case DSERR_BADFORMAT: return
- "The specified WAVE format is not supported";
-
- case DSERR_UNSUPPORTED: return
- "The function called is not supported at this time";
-
- case DSERR_NODRIVER: return
- "No sound driver is available for use";
-
- case DSERR_ALREADYINITIALIZED: return
- "This object is already initialized";
-
- case DSERR_NOAGGREGATION: return
- "This object does not support aggregation";
-
- case DSERR_BUFFERLOST: return
- "The buffer memory has been lost, and must be restored.";
-
- case DSERR_OTHERAPPHASPRIO: return
- "Another app has a higher priority level, preventing this call from succeeding.";
-
- case DSERR_UNINITIALIZED: return
- "This object has not been initialized.";
-
-#ifdef DIRECT_SOUND_3D
- case DSERR_NOINTERFACE: return
- "The requested COM interface is not available.";
-#endif
-
- default: return "Unknown Error Code";
- }
-
- return "Internal Error";
-}
-