Permalink
Browse files

Audio System Overhaul (#1219)

* Adds DirectSound fixes for getters
* Fixes some zero-initialization
* Handles GetStatus returning a combination of flags
* Creates Audio_Systems/General/ASutil.h
* Implements `sound_replace` for DirectSound
* Fixes `new[]` - `delete` mixups
* Fixes waveHeader leak in DirectSound
* Fixes memory leak in DirectSound's `sound_allocate`
* Fixes memory leak in `sound_replace` in OpenAL
* Extracts `read_all_bytes` helper for `audio_add`
* Removes id clash check to fix `sound_replace`
* Fixes `sound_replace`, `sound_delete`, and `audio_delete` for OpenAL
* Fixes `sound_add_from_buffer` for `exe_loadsounds`
* Commits some partial code for DirectSound effect functions (requires newer header)
* Adds 3D sound functions to DirectSound
* Removes unused globals in DirectSound copied from AL system
* Makes use of `alureCreateBufferFromFile` & `alureBufferDataFromFile` instead of reading the entire file up front
* Removes `LOADSTATE_SOURCED` from DirectSound
* Fixes filename printing in internal sound add/replace routines
* Cleans up some unused includes
* Makes `sound_effect_set` restore looping status
* Add buffer garbage collection to fix `sound_replace`
* Fixes/updates some copyright headers
  • Loading branch information...
RobertBColton authored and JoshDreamland committed May 11, 2018
1 parent 6196449 commit cd7ffc26fbc16355599305848b6d1310aa9ecafb
@@ -1,4 +1,4 @@
/** Copyright (C) 2013 Robert B. Colton
/** Copyright (C) 2013, 2018 Robert B. Colton
***
*** This file is a part of the ENIGMA Development Environment.
***
@@ -66,7 +66,7 @@ void sound_pause_all()
{
for (size_t i = 0; i < sound_resources.size(); i++) {
get_soundv(snd, i);
snd->soundBuffer->Stop();
snd->soundBuffer->Stop();
}
}

@@ -79,7 +79,7 @@ void sound_stop_all()
{
for (size_t i = 0; i < sound_resources.size(); i++) {
get_soundv(snd, i);
snd->soundBuffer->Stop();
snd->soundBuffer->Stop();
}
}

@@ -109,19 +109,15 @@ void sound_resume_all()
{
for (size_t i = 0; i < sound_resources.size(); i++) {
get_soundv(snd, i);
snd->soundBuffer->Play(0, 0, 0);
snd->soundBuffer->Play(0, 0, 0);
}
}

bool sound_isplaying(int sound) {
get_sound(snd, sound, false);
LPDWORD ret = NULL;
snd->soundBuffer->GetStatus(ret);
if (*ret == DSBSTATUS_LOOPING || *ret == DSBSTATUS_LOOPING) {
return true;
} else {
return false;
}
DWORD ret = 0;
snd->soundBuffer->GetStatus(&ret);
return (ret & DSBSTATUS_PLAYING);
}

bool sound_ispaused(int sound) {
@@ -137,16 +133,16 @@ void sound_pan(int sound, float value)

float sound_get_pan(int sound) {
get_sound(snd, sound, -1);
LPLONG ret = NULL;
snd->soundBuffer->GetPan(ret);
return *ret;
LONG ret = 0;
snd->soundBuffer->GetPan(&ret);
return ret;
}

float sound_get_volume(int sound) {
get_sound(snd, sound, -1);
LPLONG ret = NULL;
snd->soundBuffer->GetVolume(ret);
return *ret;
LONG ret = 0;
snd->soundBuffer->GetVolume(&ret);
return ret;
}

float sound_get_length(int sound) { // Not for Streams
@@ -157,9 +153,9 @@ float sound_get_length(int sound) { // Not for Streams

float sound_get_position(int sound) { // Not for Streams
get_sound(snd, sound, -1);
LPDWORD ret = NULL;
snd->soundBuffer->GetCurrentPosition(ret, NULL);
return *ret;
DWORD ret = 0;
snd->soundBuffer->GetCurrentPosition(&ret, NULL);
return ret;
}

void sound_seek(int sound, float position) {
@@ -170,13 +166,13 @@ void sound_seek(int sound, float position) {
void sound_seek_all(float position) {
for (size_t i = 0; i < sound_resources.size(); i++) {
get_soundv(snd, i);
snd->soundBuffer->SetCurrentPosition(position);
snd->soundBuffer->SetCurrentPosition(position);
}
}

void action_sound(int snd, bool loop)
{
(loop ? sound_loop:sound_play)(snd);
(loop ? sound_loop:sound_play)(snd);
}

const char* sound_get_audio_error() {
@@ -185,6 +181,7 @@ const char* sound_get_audio_error() {

}

#include "../General/ASutil.h"
#include <string>
using namespace std;
extern void show_message(string);
@@ -195,108 +192,211 @@ namespace enigma_user
int sound_add(string fname, int kind, bool preload) //At the moment, the latter two arguments do nothing! =D
{
// Open sound
FILE *afile = fopen(fname.c_str(),"rb");
if (!afile)
return -1;

// Buffer sound
fseek(afile,0,SEEK_END);
const size_t flen = ftell(afile);
char *fdata = new char[flen];
fseek(afile,0,SEEK_SET);
if (fread(fdata,1,flen,afile) != flen)
puts("WARNING: Resource stream cut short while loading sound data");
fclose(afile);
size_t flen = 0;
char *fdata = enigma::read_all_bytes(fname, flen);
if (!fdata) return -1;

// Decode sound
int rid = enigma::sound_allocate();
bool fail = enigma::sound_add_from_buffer(rid,fdata,flen);
delete fdata;
delete [] fdata;

if (fail)
return -1;
return rid;
}

bool sound_replace(int sound, string fname, int kind, bool preload)
{
return false;
if (sound >= 0 && sound < sound_resources.size() && sound_resources[sound]) {
get_sound(snd,sound,false);
delete snd;
}

// Open sound
size_t flen = 0;
char *fdata = enigma::read_all_bytes(fname, flen);
if (!fdata) return -1;

// Decode sound
bool fail = enigma::sound_add_from_buffer(sound,fdata,flen);
delete [] fdata;
return fail;
}

void sound_3d_set_sound_cone(int sound, float x, float y, float z, double anglein, double angleout, long voloutside) {
get_soundv(snd, sound);

// query for the 3d buffer interface
IDirectSound3DBuffer8* sound3DBuffer8 = 0;
snd->soundBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void**) &sound3DBuffer8);

sound3DBuffer8->SetConeOrientation(x, y, z, DS3D_IMMEDIATE);
sound3DBuffer8->SetConeAngles(anglein, angleout, DS3D_IMMEDIATE);
sound3DBuffer8->SetConeOutsideVolume(voloutside, DS3D_IMMEDIATE);
}

void sound_3d_set_sound_distance(int sound, float mindist, float maxdist) {
get_soundv(snd, sound);

// query for the 3d buffer interface
IDirectSound3DBuffer8* sound3DBuffer8 = 0;
snd->soundBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void**) &sound3DBuffer8);

sound3DBuffer8->SetMinDistance(mindist, DS3D_IMMEDIATE);
sound3DBuffer8->SetMaxDistance(maxdist, DS3D_IMMEDIATE);
}

void sound_3d_set_sound_position(int sound, float x, float y, float z) {
get_soundv(snd, sound);

// query for the 3d buffer interface
IDirectSound3DBuffer8* sound3DBuffer8 = 0;
snd->soundBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void**) &sound3DBuffer8);

sound3DBuffer8->SetPosition(x, y, z, DS3D_IMMEDIATE);
}

void sound_3d_set_sound_velocity(int sound, float x, float y, float z) {
}
get_soundv(snd, sound);

void sound_effect_chorus(int sound, float wetdry, float depth, float feedback, float frequency, long wave, float delay, long phase) {
/*
DSFXChorus pcDsFxChorus;
IDirectSoundFXChorus::SetAllParameters(pcDsFxChorus);
*/
}
// query for the 3d buffer interface
IDirectSound3DBuffer8* sound3DBuffer8 = 0;
snd->soundBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void**) &sound3DBuffer8);

void sound_effect_compressor(int sound, float gain, float attack, float release, float threshold, float ratio, float delay) {
sound3DBuffer8->SetVelocity(x, y, z, DS3D_IMMEDIATE);
}

void sound_effect_echo(int sound, float wetdry, float feedback, float leftdelay, float rightdelay, long pandelay) {
void sound_effect_chorus(int sound, float wetdry, float depth, float feedback, float frequency, long wave, float delay, long phase) {
/*
DSFXChorus effectParams = { };
effectParams.fWetDryMix = wetdry;
effectParams.fDepth = depth;
effectParams.fFeedback = Feedback;
effectParams.fFrequency = frequency;
effectParams.lWaveform = wave;
effectParams.fDelay = delay;
effectParams.lPhase = phase;
*/
}

void sound_effect_equalizer(int sound, float center, float bandwidth, float gain) {
void sound_effect_echo(int sound, float wetdry, float feedback, float leftdelay, float rightdelay, long pandelay) {
/*
DSFXEcho effectParams = { };
effectParams.fWetDryMix = wetdry;
effectParams.fFeedback = feedback;
effectParams.fLeftDelay = leftdelay;
effectParams.fRightDelay = rightdelay;
effectParams.lPanDelay = pandelay;
*/
}

void sound_effect_flanger(int sound, float wetdry, float depth, float feedback, float frequency, long wave, float delay, long phase) {
/*
DSFXFlanger effectParams = { };
effectParams.fWetDryMix = wetdry;
effectParams.fDepth = depth;
effectParams.fFeedback = feedback;
effectParams.fFrequency = frequency;
effectParams.lWaveform = wave;
effectParams.fDelay = delay;
effectParams.lPhase = phase;
*/
}

void sound_effect_gargle(int sound, unsigned rate, unsigned wave) {
/*
DSFXGargle effectParams = { };
effectParams.dwRateHz = rate;
effectParams.dwWaveShape = wave;
*/
}

void sound_effect_reverb(int sound, float gain, float mix, float time, float ratio) {
/*
DSFXWavesReverb effectParams = { };
effectParams.fInGain = gain;
effectParams.fReverbMix = mix;
effectParams.fReverbTime = time;
effectParams.fHighFreqRTRatio = ratio;
*/
}

void sound_effect_compressor(int sound, float gain, float attack, float release, float threshold, float ratio, float delay) {
/*
DSFXCompressor effectParams = { };
effectParams.fGain = gain;
effectParams.fAttack = attack;
effectParams.fRelease = release;
effectParams.fThreshold = threshold;
effectParams.fRatio = ratio;
effectParams.fPredelay = delay;
*/
}

//const _GUID& sound_effect_types[8] = { GUID_DSFX_STANDARD_CHORUS, GUID_DSFX_STANDARD_ECHO, GUID_DSFX_STANDARD_FLANGER, GUID_DSFX_STANDARD_GARGLE,
//GUID_DSFX_WAVES_REVERB, GUID_DSFX_STANDARD_COMPRESSOR, GUID_DSFX_STANDARD_PARAMEQ };

void sound_effect_equalizer(int sound, float center, float bandwidth, float gain) {
/*
DSFXParamEq effectParams = { };
effectParams.fCenter = center;
effectParams.fBandwidth = bandwidth;
effectParams.fGain = gain;
*/
}

static const GUID sound_effect_guids[7] = { GUID_DSFX_STANDARD_CHORUS, GUID_DSFX_STANDARD_ECHO, GUID_DSFX_STANDARD_FLANGER, GUID_DSFX_STANDARD_GARGLE,
GUID_DSFX_WAVES_REVERB, GUID_DSFX_STANDARD_COMPRESSOR, GUID_DSFX_STANDARD_PARAMEQ };

void sound_effect_set(int sound, int effect) {
/*
HRESULT hr;
DWORD dwResults[1]; // One element for each effect.
// Describe the effect.
DSEFFECTDESC dsEffect;
memset(&dsEffect, 0, sizeof(DSEFFECTDESC));
dsEffect.dwSize = sizeof(DSEFFECTDESC);
dsEffect.dwFlags = 0;
dsEffect.guidDSFXClass = sound_effect_types[effect];
get_sound(snd, sound, 0);
// Set the effect
if (SUCCEEDED(hr = snd->soundBuffer->SetFX(1, &dsEffect, dwResults)))
{
#ifdef DEBUG_MODE
switch (dwResults[0])
{
case DSFXR_LOCHARDWARE:
printf("Effect was placed in hardware.");
break;
case DSFXR_LOCSOFTWARE:
printf("Effect was placed in software.");
break;
case DSFXR_UNALLOCATED:
printf("Effect is not yet allocated to hardware or software.");
break;
size_t numOfEffects = 0;

DWORD* dwResults = 0;
DSEFFECTDESC* dsEffects = 0;

if (effect != 0) {
// count the number of effect flags that were set
for (size_t i = 0; i < 7; ++i) {
if ((effect >> i) & 1U) {
++numOfEffects;
}
}

// allocate an array of effect descriptions and results
dwResults = new DWORD[numOfEffects];
dsEffects = new DSEFFECTDESC[numOfEffects];

size_t eff = 0;
// loop all the bits of the effect parameter to see which of the flags were set
// and fill in the effect descriptions based on that
for (size_t i = 0; i < 7; ++i) {
if ((effect >> i) & 1U) {
memset(&dsEffects[eff], 0, sizeof(DSEFFECTDESC));
dsEffects[eff].dwSize = sizeof(DSEFFECTDESC);
dsEffects[eff].dwFlags = 0;
dsEffects[eff].guidDSFXClass = sound_effect_guids[i];
++eff;
}
}
#endif
}
return;
*/

get_soundv(snd, sound);

// GM8 allows changing the effect flags in the middle of a sound playing
// but this doesn't work unless we follow the Microsoft documentation
// and temporarily pause the sound
// "Additionally, the buffer must not be playing or locked."
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectsoundbuffer8.idirectsoundbuffer8.setfx%28v=vs.85%29.aspx
DWORD status = 0;
snd->soundBuffer->GetStatus(&status);
bool wasPlaying = (status & DSBSTATUS_PLAYING);
bool wasLooping = (status & DSBSTATUS_LOOPING);
if (wasPlaying) snd->soundBuffer->Stop(); // pause

// query for the effect interface and set the effects on the sound buffer
IDirectSoundBuffer8* soundBuffer8 = 0;
snd->soundBuffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &soundBuffer8);
soundBuffer8->SetFX(numOfEffects, dsEffects, dwResults);

if (wasPlaying) snd->soundBuffer->Play(0, 0, wasLooping ? DSBPLAY_LOOPING : 0); // resume
}

}
Oops, something went wrong.

0 comments on commit cd7ffc2

Please sign in to comment.