mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-07-17 21:35:21 +00:00
Merge branch 'posaudio'
This commit is contained in:
commit
9e1e4264ee
14 changed files with 601 additions and 199 deletions
|
@ -3466,7 +3466,7 @@ void Avatar::lockToWallCommon()
|
||||||
dsq->spawnParticleEffect("LockToWall", position);
|
dsq->spawnParticleEffect("LockToWall", position);
|
||||||
stopBurst();
|
stopBurst();
|
||||||
stopRoll();
|
stopRoll();
|
||||||
core->sound->playSfx("LockToWall", 1.0, 0);//, (1000+rand()%100)/1000.0f);
|
core->sound->playSfx("LockToWall", 1.0);
|
||||||
//bursting = false;
|
//bursting = false;
|
||||||
this->burst = 1;
|
this->burst = 1;
|
||||||
//lastLockToWallPos = position;
|
//lastLockToWallPos = position;
|
||||||
|
|
|
@ -2293,58 +2293,23 @@ void DSQ::playMenuSelectSfx()
|
||||||
core->sound->playSfx("MenuSelect");
|
core->sound->playSfx("MenuSelect");
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaySfx DSQ::calcPositionalSfx(const Vector &position, float maxdist)
|
void DSQ::playPositionalSfx(const std::string &name, const Vector &position, float f, float fadeOut, SoundHolder *holder)
|
||||||
{
|
{
|
||||||
PlaySfx sfx;
|
PlaySfx sfx;
|
||||||
sfx.vol = 0;
|
|
||||||
if (dsq->game && dsq->game->avatar)
|
|
||||||
{
|
|
||||||
Vector diff = position - dsq->game->avatar->position;
|
|
||||||
|
|
||||||
// Aspect-ratio-adjustment:
|
|
||||||
// Just multiplying the cut-off distance with aspect increases it too much on widescreen,
|
|
||||||
// so only a part of it is aspect-corrected to make it sound better.
|
|
||||||
// Aspect is most likely >= 5/4 here, which results in a higher value than
|
|
||||||
// the default of 1024; this is intended. -- FG
|
|
||||||
if (maxdist <= 0)
|
|
||||||
maxdist = 724 + (300 * aspect);
|
|
||||||
|
|
||||||
float dist = diff.getLength2D();
|
|
||||||
if (dist < maxdist)
|
|
||||||
{
|
|
||||||
sfx.vol = 1.0f - (dist / maxdist);
|
|
||||||
sfx.pan = (diff.x / maxdist) * 2.0f;
|
|
||||||
if (sfx.pan < -1)
|
|
||||||
sfx.pan = -1;
|
|
||||||
if (sfx.pan > 1)
|
|
||||||
sfx.pan = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sfx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DSQ::playPositionalSfx(const std::string &name, const Vector &position, float f, float fadeOut)
|
|
||||||
{
|
|
||||||
PlaySfx sfx = calcPositionalSfx(position);
|
|
||||||
|
|
||||||
// FIXME: Right now, positional sound effects never update their relative position to the
|
|
||||||
// listener, which means that if they are spawned too far away to be audible, it is not possible
|
|
||||||
// that they ever get audible at all. Additionally, the current scripting API only provides
|
|
||||||
// functions to fade sounds OUT, not to set their volume arbitrarily.
|
|
||||||
// Because audio thread creation is costly, drop sounds that can not be heard.
|
|
||||||
// This needs to be removed once proper audio source/listener positioning is implemented,
|
|
||||||
// or the scripting interface gets additional functions to mess with sound. -- FG
|
|
||||||
if (sfx.vol <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sfx.freq = f;
|
sfx.freq = f;
|
||||||
sfx.name = name;
|
sfx.name = name;
|
||||||
|
sfx.relative = false;
|
||||||
|
sfx.positional = true;
|
||||||
|
sfx.x = position.x;
|
||||||
|
sfx.y = position.y;
|
||||||
|
|
||||||
void *c = sound->playSfx(sfx);
|
void *c = sound->playSfx(sfx);
|
||||||
|
|
||||||
if (fadeOut != 0)
|
if (fadeOut != 0)
|
||||||
{
|
|
||||||
sound->fadeSfx(c, SFT_OUT, fadeOut);
|
sound->fadeSfx(c, SFT_OUT, fadeOut);
|
||||||
}
|
|
||||||
|
if (holder)
|
||||||
|
holder->linkSound(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSQ::shutdown()
|
void DSQ::shutdown()
|
||||||
|
|
|
@ -1426,8 +1426,7 @@ public:
|
||||||
bool voiceOversEnabled;
|
bool voiceOversEnabled;
|
||||||
int recentSaveSlot;
|
int recentSaveSlot;
|
||||||
|
|
||||||
PlaySfx calcPositionalSfx(const Vector &position, float maxdist = 0);
|
void playPositionalSfx(const std::string &name, const Vector &position, float freq=1.0f, float fadeOut=0, SoundHolder *holder = 0);
|
||||||
void playPositionalSfx(const std::string &name, const Vector &position, float freq=1.0f, float fadeOut=0);
|
|
||||||
|
|
||||||
void playMenuSelectSfx();
|
void playMenuSelectSfx();
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,8 @@ Entity::Entity()
|
||||||
setDamageTarget(DT_AVATAR_BUBBLE, false);
|
setDamageTarget(DT_AVATAR_BUBBLE, false);
|
||||||
setDamageTarget(DT_AVATAR_SEED, false);
|
setDamageTarget(DT_AVATAR_SEED, false);
|
||||||
|
|
||||||
|
stopSoundsOnDeath = false;
|
||||||
|
|
||||||
|
|
||||||
//debugLog("End Entity::Entity()");
|
//debugLog("End Entity::Entity()");
|
||||||
}
|
}
|
||||||
|
@ -573,6 +575,10 @@ void Entity::watchEntity(Entity *e)
|
||||||
|
|
||||||
void Entity::destroy()
|
void Entity::destroy()
|
||||||
{
|
{
|
||||||
|
if (stopSoundsOnDeath)
|
||||||
|
this->stopAllSounds();
|
||||||
|
this->unlinkAllSounds();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (hair)
|
if (hair)
|
||||||
{
|
{
|
||||||
|
@ -1231,6 +1237,8 @@ void Entity::update(float dt)
|
||||||
position = backupPos;
|
position = backupPos;
|
||||||
if (vel.isNan())
|
if (vel.isNan())
|
||||||
vel = backupVel;
|
vel = backupVel;
|
||||||
|
|
||||||
|
updateSoundPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::postUpdate(float dt)
|
void Entity::postUpdate(float dt)
|
||||||
|
@ -2239,7 +2247,8 @@ void Entity::songNoteDone(int note, float len)
|
||||||
|
|
||||||
void Entity::sound(const std::string &sound, float freq, float fadeOut)
|
void Entity::sound(const std::string &sound, float freq, float fadeOut)
|
||||||
{
|
{
|
||||||
dsq->playPositionalSfx(sound, position, freq, fadeOut);
|
dsq->playPositionalSfx(sound, position, freq, fadeOut, this);
|
||||||
|
updateSoundPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector Entity::getEnergyShotTargetPosition()
|
Vector Entity::getEnergyShotTargetPosition()
|
||||||
|
@ -3139,3 +3148,8 @@ bool Entity::isEntityInside()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entity::updateSoundPosition()
|
||||||
|
{
|
||||||
|
SoundHolder::updateSoundPosition(position.x + offset.x, position.y + offset.y);
|
||||||
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ enum BounceType
|
||||||
BOUNCE_REAL = 1
|
BOUNCE_REAL = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
class Entity : public Quad, public StateMachine
|
class Entity : public Quad, public StateMachine, public SoundHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Entity();
|
Entity();
|
||||||
|
@ -276,6 +276,7 @@ public:
|
||||||
|
|
||||||
void popBubble();
|
void popBubble();
|
||||||
void sound(const std::string &sound, float freq=1, float fadeOut=0);
|
void sound(const std::string &sound, float freq=1, float fadeOut=0);
|
||||||
|
void setStopSoundsOnDeath(bool stop) { stopSoundsOnDeath = stop; }
|
||||||
|
|
||||||
void freeze(float time);
|
void freeze(float time);
|
||||||
|
|
||||||
|
@ -492,6 +493,8 @@ public:
|
||||||
|
|
||||||
bool isEntityInside();
|
bool isEntityInside();
|
||||||
|
|
||||||
|
void updateSoundPosition();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool calledEntityDied;
|
bool calledEntityDied;
|
||||||
Path *waterBubble;
|
Path *waterBubble;
|
||||||
|
@ -602,6 +605,8 @@ private:
|
||||||
int maxSpeed;
|
int maxSpeed;
|
||||||
int oldMaxSpeed;
|
int oldMaxSpeed;
|
||||||
|
|
||||||
|
bool stopSoundsOnDeath;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8134,13 +8134,13 @@ void Game::playBurstSound(bool wallJump)
|
||||||
int freqBase = 950;
|
int freqBase = 950;
|
||||||
if (wallJump)
|
if (wallJump)
|
||||||
freqBase += 100;
|
freqBase += 100;
|
||||||
sound->playSfx("Burst", 1, 0);//, (freqBase+rand()%25)/1000.0f);
|
sound->playSfx("Burst", 1);
|
||||||
if (chance(50))
|
if (chance(50))
|
||||||
{
|
{
|
||||||
switch (dsq->continuity.form)
|
switch (dsq->continuity.form)
|
||||||
{
|
{
|
||||||
case FORM_BEAST:
|
case FORM_BEAST:
|
||||||
sound->playSfx("BeastBurst", (128+rand()%64)/256.0f, 0);//, (freqBase+rand()%25)/1000.0f);
|
sound->playSfx("BeastBurst", (128+rand()%64)/256.0f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2763,28 +2763,39 @@ luaFunc(entity_playSfx)
|
||||||
void *h = NULL;
|
void *h = NULL;
|
||||||
if (e && !dsq->isSkippingCutscene())
|
if (e && !dsq->isSkippingCutscene())
|
||||||
{
|
{
|
||||||
PlaySfx sfx = dsq->calcPositionalSfx(e->position, lua_tonumber(L, 7));
|
PlaySfx sfx;
|
||||||
sfx.name = getString(L, 2);
|
sfx.name = getString(L, 2);
|
||||||
sfx.freq = lua_tonumber(L, 3);
|
sfx.freq = lua_tonumber(L, 3);
|
||||||
float vol = lua_tonumber(L, 4);
|
sfx.vol = lua_tonumber(L, 4);
|
||||||
|
if(sfx.vol <= 0)
|
||||||
|
sfx.vol = 1;
|
||||||
sfx.loops = lua_tonumber(L, 5);
|
sfx.loops = lua_tonumber(L, 5);
|
||||||
float fadeOut = lua_tonumber(L, 6);
|
|
||||||
if(vol > 0)
|
|
||||||
sfx.vol *= vol;
|
|
||||||
|
|
||||||
// FIXME: See comment in DSQ::playPositionalSfx() -- FG
|
float fadeOut = lua_tonumber(L, 6);
|
||||||
if (sfx.vol <= 0)
|
sfx.maxdist = lua_tonumber(L, 7);
|
||||||
luaReturnPtr(NULL);
|
sfx.relative = false;
|
||||||
|
sfx.positional = true;
|
||||||
|
|
||||||
h = core->sound->playSfx(sfx);
|
h = core->sound->playSfx(sfx);
|
||||||
if (fadeOut != 0)
|
if (fadeOut != 0)
|
||||||
{
|
{
|
||||||
sound->fadeSfx(h, SFT_OUT, fadeOut);
|
sound->fadeSfx(h, SFT_OUT, fadeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e->linkSound(h);
|
||||||
|
e->updateSoundPosition();
|
||||||
}
|
}
|
||||||
luaReturnPtr(h);
|
luaReturnPtr(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luaFunc(entity_setStopSoundsOnDeath)
|
||||||
|
{
|
||||||
|
Entity *e = entity(L);
|
||||||
|
if (e)
|
||||||
|
e->setStopSoundsOnDeath(getBool(L, 2));
|
||||||
|
luaReturnNil();
|
||||||
|
}
|
||||||
|
|
||||||
luaFunc(entity_setSpiritFreeze)
|
luaFunc(entity_setSpiritFreeze)
|
||||||
{
|
{
|
||||||
Entity *e = entity(L);
|
Entity *e = entity(L);
|
||||||
|
@ -5927,32 +5938,24 @@ luaFunc(emote)
|
||||||
|
|
||||||
luaFunc(playSfx)
|
luaFunc(playSfx)
|
||||||
{
|
{
|
||||||
float freq = lua_tonumber(L, 2);
|
|
||||||
float vol = lua_tonumber(L, 3);
|
|
||||||
int loops = lua_tointeger(L, 4);
|
|
||||||
if (vol <= 0)
|
|
||||||
vol = 1;
|
|
||||||
|
|
||||||
PlaySfx sfx;
|
PlaySfx sfx;
|
||||||
|
|
||||||
if (lua_isnumber(L, 5) && lua_isnumber(L, 6))
|
|
||||||
{
|
|
||||||
const Vector pos(lua_tonumber(L, 5), lua_tonumber(L, 6));
|
|
||||||
sfx = dsq->calcPositionalSfx(pos, lua_tonumber(L, 7));
|
|
||||||
sfx.vol *= vol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sfx.vol = vol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: See comment in DSQ::playPositionalSfx() -- FG
|
|
||||||
if (sfx.vol <= 0)
|
|
||||||
luaReturnPtr(NULL);
|
|
||||||
|
|
||||||
sfx.name = getString(L, 1);
|
sfx.name = getString(L, 1);
|
||||||
sfx.freq = freq;
|
sfx.freq = lua_tonumber(L, 2);
|
||||||
sfx.loops = loops;
|
sfx.vol = lua_tonumber(L, 3);
|
||||||
|
if (sfx.vol <= 0)
|
||||||
|
sfx.vol = 1;
|
||||||
|
sfx.loops = lua_tointeger(L, 4);
|
||||||
|
if(lua_isnumber(L, 6) && lua_isnumber(L, 7))
|
||||||
|
{
|
||||||
|
sfx.x = lua_tonumber(L, 5);
|
||||||
|
sfx.y = lua_tonumber(L, 6);
|
||||||
|
sfx.positional = true;
|
||||||
|
}
|
||||||
|
sfx.maxdist = lua_tonumber(L, 7);
|
||||||
|
if(lua_isnoneornil(L, 8))
|
||||||
|
sfx.relative = (sfx.x == 0 && sfx.y == 0);
|
||||||
|
else
|
||||||
|
sfx.relative = getBool(L, 8);
|
||||||
|
|
||||||
void *handle = NULL;
|
void *handle = NULL;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#ifdef BBGE_BUILD_WINDOWS
|
#ifdef BBGE_BUILD_WINDOWS
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
@ -3138,6 +3138,8 @@ void Core::main(float runTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sound->setListenerPos(screenCenter.x, screenCenter.y);
|
||||||
|
|
||||||
if (doScreenshot)
|
if (doScreenshot)
|
||||||
{
|
{
|
||||||
if (verbose) debugLog("screenshot");
|
if (verbose) debugLog("screenshot");
|
||||||
|
|
|
@ -49,6 +49,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
//#define _DEBUG 1
|
//#define _DEBUG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
// HACK: global because OpenAL has only one listener anyway
|
||||||
|
static FMOD_VECTOR s_listenerPos;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Decoder implementation for streamed Ogg Vorbis audio.
|
// Decoder implementation for streamed Ogg Vorbis audio.
|
||||||
|
@ -63,8 +69,12 @@ public:
|
||||||
|
|
||||||
~OggDecoder();
|
~OggDecoder();
|
||||||
|
|
||||||
// Start playing on the given channel, with optional looping.
|
// Prepare playing on the given channel.
|
||||||
bool start(ALuint source, bool loop);
|
bool preStart(ALuint source);
|
||||||
|
|
||||||
|
// Decodes the first few buffers, starts the actual playback and detaches the decoder
|
||||||
|
// from the main thread, with optional looping.
|
||||||
|
void start(bool loop);
|
||||||
|
|
||||||
// Decode audio into any free buffers. Must be called periodically
|
// Decode audio into any free buffers. Must be called periodically
|
||||||
// on systems without threads; may be called without harm on systems
|
// on systems without threads; may be called without harm on systems
|
||||||
|
@ -85,6 +95,10 @@ public:
|
||||||
static void startDecoderThread();
|
static void startDecoderThread();
|
||||||
static void stopDecoderThread();
|
static void stopDecoderThread();
|
||||||
|
|
||||||
|
int getNumChannels() const { return channels; }
|
||||||
|
|
||||||
|
void setForceMono(bool mono) { forcemono = mono; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void _stop();
|
void _stop();
|
||||||
|
@ -114,7 +128,9 @@ private:
|
||||||
|
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
ALenum format;
|
ALenum format;
|
||||||
|
int channels;
|
||||||
int freq;
|
int freq;
|
||||||
|
bool forcemono;
|
||||||
|
|
||||||
bool thread; // true if played by background thread
|
bool thread; // true if played by background thread
|
||||||
|
|
||||||
|
@ -272,6 +288,9 @@ OggDecoder::OggDecoder(VFILE *fp)
|
||||||
this->eof = false;
|
this->eof = false;
|
||||||
this->samples_done = 0;
|
this->samples_done = 0;
|
||||||
this->stopped = false;
|
this->stopped = false;
|
||||||
|
this->format = 0;
|
||||||
|
this->channels = 0;
|
||||||
|
this->forcemono = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OggDecoder::OggDecoder(const void *data, long data_size)
|
OggDecoder::OggDecoder(const void *data, long data_size)
|
||||||
|
@ -291,6 +310,9 @@ OggDecoder::OggDecoder(const void *data, long data_size)
|
||||||
this->eof = false;
|
this->eof = false;
|
||||||
this->samples_done = 0;
|
this->samples_done = 0;
|
||||||
this->stopped = false;
|
this->stopped = false;
|
||||||
|
this->format = 0;
|
||||||
|
this->channels = 0;
|
||||||
|
this->forcemono = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OggDecoder::~OggDecoder()
|
OggDecoder::~OggDecoder()
|
||||||
|
@ -304,10 +326,9 @@ OggDecoder::~OggDecoder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OggDecoder::start(ALuint source, bool loop)
|
bool OggDecoder::preStart(ALuint source)
|
||||||
{
|
{
|
||||||
this->source = source;
|
this->source = source;
|
||||||
this->loop = loop;
|
|
||||||
|
|
||||||
if (fp) {
|
if (fp) {
|
||||||
if (ov_open_callbacks(fp, &vf, NULL, 0, local_OV_CALLBACKS_NOCLOSE) != 0)
|
if (ov_open_callbacks(fp, &vf, NULL, 0, local_OV_CALLBACKS_NOCLOSE) != 0)
|
||||||
|
@ -333,6 +354,7 @@ bool OggDecoder::start(ALuint source, bool loop)
|
||||||
ov_clear(&vf);
|
ov_clear(&vf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
channels = info->channels;
|
||||||
if (info->channels == 1)
|
if (info->channels == 1)
|
||||||
format = AL_FORMAT_MONO16;
|
format = AL_FORMAT_MONO16;
|
||||||
else if (info->channels == 2)
|
else if (info->channels == 2)
|
||||||
|
@ -368,6 +390,13 @@ bool OggDecoder::start(ALuint source, bool loop)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OggDecoder::start(bool loop)
|
||||||
|
{
|
||||||
|
this->loop = loop;
|
||||||
|
|
||||||
playing = true;
|
playing = true;
|
||||||
eof = false;
|
eof = false;
|
||||||
samples_done = 0;
|
samples_done = 0;
|
||||||
|
@ -375,8 +404,6 @@ bool OggDecoder::start(ALuint source, bool loop)
|
||||||
queue(buffers[i]);
|
queue(buffers[i]);
|
||||||
|
|
||||||
detachDecoder(this);
|
detachDecoder(this);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OggDecoder::update()
|
void OggDecoder::update()
|
||||||
|
@ -493,7 +520,22 @@ void OggDecoder::queue(ALuint buffer)
|
||||||
|
|
||||||
if (pcm_size > 0)
|
if (pcm_size > 0)
|
||||||
{
|
{
|
||||||
alBufferData(buffer, format, pcm_buffer, pcm_size, freq);
|
ALuint fmt = format;
|
||||||
|
if(channels == 2 && forcemono)
|
||||||
|
{
|
||||||
|
signed short *buf = (short*)&pcm_buffer[0];
|
||||||
|
int numSamples = pcm_size / 2; // 16 bit samples
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < numSamples ; i += 2)
|
||||||
|
{
|
||||||
|
// This is in theory not quite correct, but it doesn't add any artifacts or clipping.
|
||||||
|
// FIXME: Seems that simple and stupid is the method of choice, then... -- FG
|
||||||
|
buf[j++] = (buf[i] + buf[i+1]) / 2;
|
||||||
|
}
|
||||||
|
pcm_size = numSamples;
|
||||||
|
fmt = AL_FORMAT_MONO16;
|
||||||
|
}
|
||||||
|
alBufferData(buffer, fmt, pcm_buffer, pcm_size, freq);
|
||||||
alSourceQueueBuffers(source, 1, &buffer);
|
alSourceQueueBuffers(source, 1, &buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,8 +639,11 @@ public:
|
||||||
bool isLooping() const { return looping; }
|
bool isLooping() const { return looping; }
|
||||||
bool isRaw() const { return raw; }
|
bool isRaw() const { return raw; }
|
||||||
FMOD_RESULT release();
|
FMOD_RESULT release();
|
||||||
|
FMOD_RESULT getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits);
|
||||||
void reference() { refcount++; }
|
void reference() { refcount++; }
|
||||||
ALuint getBufferName() const { return bid; }
|
ALuint getBufferName() const { return bid; }
|
||||||
|
int getNumChannels() const { return numChannels; }
|
||||||
|
void setNumChannels(int c) { numChannels = c; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VFILE * const fp;
|
VFILE * const fp;
|
||||||
|
@ -608,6 +653,7 @@ private:
|
||||||
int refcount;
|
int refcount;
|
||||||
const bool raw; // true if buffer holds raw PCM data
|
const bool raw; // true if buffer holds raw PCM data
|
||||||
ALuint bid; // only used if raw == true
|
ALuint bid; // only used if raw == true
|
||||||
|
int numChannels;
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
||||||
|
@ -618,6 +664,7 @@ OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
||||||
, refcount(1)
|
, refcount(1)
|
||||||
, raw(false)
|
, raw(false)
|
||||||
, bid(0)
|
, bid(0)
|
||||||
|
, numChannels(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,6 +676,7 @@ OpenALSound::OpenALSound(void *_data, long _size, const bool _looping)
|
||||||
, refcount(1)
|
, refcount(1)
|
||||||
, raw(false)
|
, raw(false)
|
||||||
, bid(0)
|
, bid(0)
|
||||||
|
, numChannels(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,6 +688,7 @@ OpenALSound::OpenALSound(ALuint _bid, const bool _looping)
|
||||||
, refcount(1)
|
, refcount(1)
|
||||||
, raw(true)
|
, raw(true)
|
||||||
, bid(_bid)
|
, bid(_bid)
|
||||||
|
, numChannels(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,6 +714,14 @@ FMOD_RESULT OpenALSound::release()
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Sound,getFormat,(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits),(type, format, channels, bits))
|
||||||
|
FMOD_RESULT OpenALSound::getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits)
|
||||||
|
{
|
||||||
|
if(channels)
|
||||||
|
*channels = getNumChannels();
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class OpenALChannelGroup;
|
class OpenALChannelGroup;
|
||||||
|
|
||||||
|
@ -672,7 +729,7 @@ class OpenALChannel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenALChannel();
|
OpenALChannel();
|
||||||
FMOD_RESULT setVolume(const float _volume, const bool setstate=true);
|
FMOD_RESULT setVolume(const float _volume);
|
||||||
FMOD_RESULT setPaused(const bool _paused, const bool setstate=true);
|
FMOD_RESULT setPaused(const bool _paused, const bool setstate=true);
|
||||||
FMOD_RESULT setFrequency(const float _frequency);
|
FMOD_RESULT setFrequency(const float _frequency);
|
||||||
FMOD_RESULT setPriority(int _priority);
|
FMOD_RESULT setPriority(int _priority);
|
||||||
|
@ -681,8 +738,16 @@ public:
|
||||||
FMOD_RESULT isPlaying(bool *isplaying);
|
FMOD_RESULT isPlaying(bool *isplaying);
|
||||||
FMOD_RESULT setChannelGroup(ChannelGroup *channelgroup);
|
FMOD_RESULT setChannelGroup(ChannelGroup *channelgroup);
|
||||||
FMOD_RESULT stop();
|
FMOD_RESULT stop();
|
||||||
FMOD_RESULT setPan(const float pan);
|
FMOD_RESULT setCallback(FMOD_CHANNEL_CALLBACK callback);
|
||||||
|
FMOD_RESULT getUserData(void **userdata);
|
||||||
|
FMOD_RESULT setUserData(void *userdata);
|
||||||
|
FMOD_RESULT set3DAttributes(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel);
|
||||||
|
FMOD_RESULT set3DMinMaxDistance(float mindistance, float maxdistance);
|
||||||
|
FMOD_RESULT setMode(FMOD_MODE mode);
|
||||||
|
FMOD_RESULT getMode(FMOD_MODE *mode);
|
||||||
|
|
||||||
void setGroupVolume(const float _volume);
|
void setGroupVolume(const float _volume);
|
||||||
|
void setDistanceVolume(float _volume);
|
||||||
void setSourceName(const ALuint _sid) { sid = _sid; }
|
void setSourceName(const ALuint _sid) { sid = _sid; }
|
||||||
ALuint getSourceName() const { return sid; }
|
ALuint getSourceName() const { return sid; }
|
||||||
bool start(OpenALSound *sound);
|
bool start(OpenALSound *sound);
|
||||||
|
@ -692,9 +757,12 @@ public:
|
||||||
void setSound(OpenALSound *sound);
|
void setSound(OpenALSound *sound);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void applyVolume();
|
||||||
|
|
||||||
ALuint sid; // source id.
|
ALuint sid; // source id.
|
||||||
float groupvolume;
|
float groupvolume;
|
||||||
float volume;
|
float volume;
|
||||||
|
float distvolume;
|
||||||
bool paused;
|
bool paused;
|
||||||
int priority;
|
int priority;
|
||||||
float frequency;
|
float frequency;
|
||||||
|
@ -703,6 +771,12 @@ private:
|
||||||
OggDecoder *decoder;
|
OggDecoder *decoder;
|
||||||
bool inuse;
|
bool inuse;
|
||||||
bool initial;
|
bool initial;
|
||||||
|
FMOD_CHANNEL_CALLBACK callback;
|
||||||
|
void *userdata;
|
||||||
|
FMOD_MODE _mode;
|
||||||
|
float mindist;
|
||||||
|
float maxdist;
|
||||||
|
bool relative;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -735,6 +809,7 @@ OpenALChannel::OpenALChannel()
|
||||||
: sid(0)
|
: sid(0)
|
||||||
, groupvolume(1.0f)
|
, groupvolume(1.0f)
|
||||||
, volume(1.0f)
|
, volume(1.0f)
|
||||||
|
, distvolume(1.0f)
|
||||||
, paused(false)
|
, paused(false)
|
||||||
, priority(0)
|
, priority(0)
|
||||||
, frequency(1.0f)
|
, frequency(1.0f)
|
||||||
|
@ -743,6 +818,10 @@ OpenALChannel::OpenALChannel()
|
||||||
, decoder(NULL)
|
, decoder(NULL)
|
||||||
, inuse(false)
|
, inuse(false)
|
||||||
, initial(true)
|
, initial(true)
|
||||||
|
, _mode(FMOD_DEFAULT)
|
||||||
|
, mindist(0.0f)
|
||||||
|
, maxdist(0.0f)
|
||||||
|
, relative(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,18 +830,21 @@ void OpenALChannel::reacquire()
|
||||||
assert(!inuse);
|
assert(!inuse);
|
||||||
inuse = true;
|
inuse = true;
|
||||||
volume = 1.0f;
|
volume = 1.0f;
|
||||||
|
distvolume = 1.0f;
|
||||||
paused = true;
|
paused = true;
|
||||||
priority = 0;
|
priority = 0;
|
||||||
frequency = 1.0f;
|
frequency = 1.0f;
|
||||||
sound = NULL;
|
sound = NULL;
|
||||||
initial = true;
|
initial = true;
|
||||||
|
mindist = 0.0f;
|
||||||
|
maxdist = 0.0f;
|
||||||
|
relative = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALChannel::setGroupVolume(const float _volume)
|
void OpenALChannel::setGroupVolume(const float _volume)
|
||||||
{
|
{
|
||||||
groupvolume = _volume;
|
groupvolume = _volume;
|
||||||
alSourcef(sid, AL_GAIN, volume * groupvolume);
|
applyVolume();
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenALChannel::start(OpenALSound *sound)
|
bool OpenALChannel::start(OpenALSound *sound)
|
||||||
|
@ -780,12 +862,13 @@ bool OpenALChannel::start(OpenALSound *sound)
|
||||||
decoder = new OggDecoder(sound->getFile());
|
decoder = new OggDecoder(sound->getFile());
|
||||||
else
|
else
|
||||||
decoder = new OggDecoder(sound->getData(), sound->getSize());
|
decoder = new OggDecoder(sound->getData(), sound->getSize());
|
||||||
if (!decoder->start(sid, sound->isLooping()))
|
if (!decoder->preStart(sid))
|
||||||
{
|
{
|
||||||
delete decoder;
|
delete decoder;
|
||||||
decoder = NULL;
|
decoder = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
sound->setNumChannels(decoder->getNumChannels());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -805,12 +888,10 @@ void OpenALChannel::update()
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,setVolume,(float volume),(volume))
|
ALBRIDGE(Channel,setVolume,(float volume),(volume))
|
||||||
FMOD_RESULT OpenALChannel::setVolume(const float _volume, const bool setstate)
|
FMOD_RESULT OpenALChannel::setVolume(const float _volume)
|
||||||
{
|
{
|
||||||
if (setstate)
|
|
||||||
volume = _volume;
|
volume = _volume;
|
||||||
alSourcef(sid, AL_GAIN, _volume * groupvolume);
|
applyVolume();
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,6 +977,11 @@ FMOD_RESULT OpenALChannel::setPaused(const bool _paused, const bool setstate)
|
||||||
}
|
}
|
||||||
else if ((!_paused) && (initial || ((state == AL_INITIAL) || (state == AL_PAUSED))))
|
else if ((!_paused) && (initial || ((state == AL_INITIAL) || (state == AL_PAUSED))))
|
||||||
{
|
{
|
||||||
|
if (initial && decoder)
|
||||||
|
{
|
||||||
|
decoder->setForceMono(mindist || maxdist); // HACK: this is set for positional sounds.
|
||||||
|
decoder->start(sound->isLooping());
|
||||||
|
}
|
||||||
alSourcePlay(sid);
|
alSourcePlay(sid);
|
||||||
initial = false;
|
initial = false;
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
@ -914,15 +1000,161 @@ FMOD_RESULT OpenALChannel::setPriority(int _priority)
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,setPan,(float volume),(volume))
|
ALBRIDGE(Channel,stop,(),())
|
||||||
FMOD_RESULT OpenALChannel::setPan(const float pan)
|
FMOD_RESULT OpenALChannel::stop()
|
||||||
{
|
{
|
||||||
alSource3f(sid, AL_POSITION, pan, 0, 0);
|
if (decoder)
|
||||||
|
{
|
||||||
|
decoder->stop();
|
||||||
|
decoder = NULL;
|
||||||
|
}
|
||||||
|
alSourceStop(sid);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
alSourcei(sid, AL_BUFFER, 0);
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
if (sound)
|
||||||
|
{
|
||||||
|
sound->release();
|
||||||
|
sound = NULL;
|
||||||
|
}
|
||||||
|
if (inuse && callback)
|
||||||
|
callback(this, FMOD_CHANNEL_CALLBACKTYPE_END, NULL, NULL); // HACK: commanddata missing (but they are not used by the callback)
|
||||||
|
paused = false;
|
||||||
|
inuse = false;
|
||||||
|
initial = false;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,setCallback,(FMOD_CHANNEL_CALLBACK callback),(callback))
|
||||||
|
FMOD_RESULT OpenALChannel::setCallback(FMOD_CHANNEL_CALLBACK callback)
|
||||||
|
{
|
||||||
|
this->callback = callback;
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,getUserData,(void **userdata),(userdata))
|
||||||
|
FMOD_RESULT OpenALChannel::getUserData(void **userdata)
|
||||||
|
{
|
||||||
|
*userdata = this->userdata;
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,setUserData,(void *userdata),(userdata))
|
||||||
|
FMOD_RESULT OpenALChannel::setUserData(void *userdata)
|
||||||
|
{
|
||||||
|
this->userdata = userdata;
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,set3DAttributes,(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel),(pos, vel))
|
||||||
|
FMOD_RESULT OpenALChannel::set3DAttributes(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel)
|
||||||
|
{
|
||||||
|
if (pos)
|
||||||
|
{
|
||||||
|
alSource3f(sid, AL_POSITION, pos->x, pos->y, pos->z);
|
||||||
|
|
||||||
|
if(maxdist == mindist)
|
||||||
|
setDistanceVolume(1.0f);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is where custom distance attenuation starts.
|
||||||
|
float dx, dy, dz;
|
||||||
|
if(relative)
|
||||||
|
{
|
||||||
|
dx = pos->x;
|
||||||
|
dy = pos->y;
|
||||||
|
dz = pos->z;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dx = s_listenerPos.x - pos->x;
|
||||||
|
dy = s_listenerPos.y - pos->y;
|
||||||
|
dz = s_listenerPos.z - pos->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d2 = dx*dx + dy*dy + dz*dz;
|
||||||
|
|
||||||
|
if(d2 < mindist*mindist)
|
||||||
|
setDistanceVolume(1.0f);
|
||||||
|
else if(d2 > maxdist*maxdist)
|
||||||
|
setDistanceVolume(0.0f);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Replacement method for AL_INVERSE_DISTANCE_CLAMPED.
|
||||||
|
// The problem with this distance model is that the volume never goes down
|
||||||
|
// to 0, no matter how far sound sources are away from the listener.
|
||||||
|
// This could be fixed by using AL_LINEAR_DISTANCE_CLAMPED, but this model does not sound
|
||||||
|
// natural (as the gain/volume/decibels is a logarithmic measure).
|
||||||
|
// As a remedy, use a simplified quadratic 1D-bezier curve to model
|
||||||
|
// a decay similar to AL_INVERSE_DISTANCE_CLAMPED, but that actually reaches 0.
|
||||||
|
// (The formula is simplified, as the control points (1, 0, 0) cause some math to vanish.) -- FG
|
||||||
|
const float t = ((sqrtf(d2) - mindist) / (maxdist - mindist)); // [0 .. 1]
|
||||||
|
const float t1 = 1.0f - t;
|
||||||
|
const float a = t1 * t1;
|
||||||
|
const float w = 2.0f; // weight; the higher this is, the steeper is the initial falloff, and the slower the final decay before reaching 0
|
||||||
|
const float gain = a / (a + (2.0f * w * t * t1) + (t * t));
|
||||||
|
setDistanceVolume(gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vel)
|
||||||
|
alSource3f(sid, AL_VELOCITY, vel->x, vel->y, vel->z);
|
||||||
|
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,set3DMinMaxDistance,(float mindistance, float maxdistance),(mindistance, maxdistance))
|
||||||
|
FMOD_RESULT OpenALChannel::set3DMinMaxDistance(float mindistance, float maxdistance)
|
||||||
|
{
|
||||||
|
alSourcef(sid, AL_REFERENCE_DISTANCE, mindistance);
|
||||||
|
alSourcef(sid, AL_MAX_DISTANCE, maxdistance);
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
mindist = mindistance;
|
||||||
|
maxdist = maxdistance;
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,setMode,(FMOD_MODE mode),(mode))
|
||||||
|
FMOD_RESULT OpenALChannel::setMode(FMOD_MODE mode)
|
||||||
|
{
|
||||||
|
_mode = mode;
|
||||||
|
|
||||||
|
if(mode & FMOD_3D_HEADRELATIVE)
|
||||||
|
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
else // FMOD_3D_WORLDRELATIVE is the default according to FMOD docs
|
||||||
|
alSourcei(sid, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(Channel,getMode,(FMOD_MODE *mode),(mode))
|
||||||
|
FMOD_RESULT OpenALChannel::getMode(FMOD_MODE *mode)
|
||||||
|
{
|
||||||
|
*mode = _mode;
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenALChannel::setDistanceVolume(float _volume)
|
||||||
|
{
|
||||||
|
distvolume = _volume;
|
||||||
|
applyVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenALChannel::applyVolume()
|
||||||
|
{
|
||||||
|
alSourcef(sid, AL_GAIN, volume * groupvolume * distvolume);
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FMOD::ChannelGroup implementation...
|
// FMOD::ChannelGroup implementation...
|
||||||
|
|
||||||
OpenALChannelGroup::OpenALChannelGroup(const char *_name)
|
OpenALChannelGroup::OpenALChannelGroup(const char *_name)
|
||||||
|
@ -1066,29 +1298,6 @@ void OpenALChannel::setSound(OpenALSound *_sound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ALBRIDGE(Channel,stop,(),())
|
|
||||||
FMOD_RESULT OpenALChannel::stop()
|
|
||||||
{
|
|
||||||
if (decoder)
|
|
||||||
{
|
|
||||||
decoder->stop();
|
|
||||||
decoder = NULL;
|
|
||||||
}
|
|
||||||
alSourceStop(sid);
|
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
|
||||||
alSourcei(sid, AL_BUFFER, 0);
|
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
|
||||||
if (sound)
|
|
||||||
{
|
|
||||||
sound->release();
|
|
||||||
sound = NULL;
|
|
||||||
}
|
|
||||||
paused = false;
|
|
||||||
inuse = false;
|
|
||||||
initial = false;
|
|
||||||
return FMOD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FMOD::System implementation ...
|
// FMOD::System implementation ...
|
||||||
|
@ -1112,6 +1321,7 @@ public:
|
||||||
FMOD_RESULT getDriverCaps(const int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode);
|
FMOD_RESULT getDriverCaps(const int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode);
|
||||||
FMOD_RESULT getMasterChannelGroup(ChannelGroup **channelgroup);
|
FMOD_RESULT getMasterChannelGroup(ChannelGroup **channelgroup);
|
||||||
FMOD_RESULT playSound(FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel);
|
FMOD_RESULT playSound(FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel);
|
||||||
|
FMOD_RESULT set3DListenerAttributes(int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up);
|
||||||
|
|
||||||
FMOD_RESULT getNumChannels(int *maxchannels_ret);
|
FMOD_RESULT getNumChannels(int *maxchannels_ret);
|
||||||
|
|
||||||
|
@ -1247,8 +1457,11 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
|
||||||
alGenBuffers(1, &bid);
|
alGenBuffers(1, &bid);
|
||||||
if (bid != 0)
|
if (bid != 0)
|
||||||
{
|
{
|
||||||
|
// FIXME: This needs to stored seperately and fed to the AL on demand,
|
||||||
|
// converting stereo to mono when it's known whether to do so or not.
|
||||||
alBufferData(bid, format, data, size, freq);
|
alBufferData(bid, format, data, size, freq);
|
||||||
*sound = (Sound *) new OpenALSound(bid, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
|
*sound = (Sound *) new OpenALSound(bid, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
|
||||||
|
((OpenALSound*)*sound)->setNumChannels(format == AL_FORMAT_STEREO16 ? 2 : 1);
|
||||||
retval = FMOD_OK;
|
retval = FMOD_OK;
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -1415,7 +1628,7 @@ FMOD_RESULT OpenALSystem::init(int maxchannels, const FMOD_INITFLAGS flags, cons
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
|
alSourcei(sid, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
alSource3f(sid, AL_POSITION, 0.0f, 0.0f, 0.0f); // no panning or spatialization in Aquaria.
|
alSource3f(sid, AL_POSITION, 0.0f, 0.0f, 0.0f); // no panning or spatialization in Aquaria.
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
@ -1426,6 +1639,15 @@ FMOD_RESULT OpenALSystem::init(int maxchannels, const FMOD_INITFLAGS flags, cons
|
||||||
ss << "Using " << num_channels << " sound channels.";
|
ss << "Using " << num_channels << " sound channels.";
|
||||||
debugLog(ss.str());
|
debugLog(ss.str());
|
||||||
|
|
||||||
|
// HACK: FMOD doesn't do this.
|
||||||
|
// For completeness, we pass FMOD_3D_LINEARROLLOFF to createSound().
|
||||||
|
// We do our own non-standard distance attenuation model, as the modes offered by OpenAL
|
||||||
|
// are not sufficient. See OpenALChannel::set3DMinMaxDistance() for the gain control code. -- FG
|
||||||
|
alDistanceModel(AL_NONE);
|
||||||
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
s_listenerPos.x = s_listenerPos.y = s_listenerPos.z = 0.0f;
|
||||||
|
|
||||||
|
|
||||||
OggDecoder::startDecoderThread();
|
OggDecoder::startDecoderThread();
|
||||||
|
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
|
@ -1539,6 +1761,46 @@ FMOD_RESULT OpenALSystem::update()
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALBRIDGE(System, set3DListenerAttributes, (int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up),
|
||||||
|
(listener, pos, vel, forward, up));
|
||||||
|
FMOD_RESULT OpenALSystem::set3DListenerAttributes(int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up)
|
||||||
|
{
|
||||||
|
// ignore listener parameter; there is only one listener in OpenAL.
|
||||||
|
|
||||||
|
if(up || forward)
|
||||||
|
{
|
||||||
|
ALfloat orientation[6];
|
||||||
|
alGetListenerfv(AL_ORIENTATION, &orientation[0]);
|
||||||
|
|
||||||
|
if(forward)
|
||||||
|
{
|
||||||
|
orientation[0] = forward->x;
|
||||||
|
orientation[1] = forward->y;
|
||||||
|
orientation[2] = forward->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(up)
|
||||||
|
{
|
||||||
|
orientation[3] = up->x;
|
||||||
|
orientation[4] = up->y;
|
||||||
|
orientation[5] = up->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
alListenerfv(AL_ORIENTATION, &orientation[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pos)
|
||||||
|
{
|
||||||
|
s_listenerPos = *pos;
|
||||||
|
alListener3f(AL_POSITION, pos->x, pos->y, pos->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vel)
|
||||||
|
alListener3f(AL_VELOCITY, vel->x, vel->y, vel->z);
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// misc FMOD bits...
|
// misc FMOD bits...
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,24 @@ typedef enum
|
||||||
FMOD_DSP_TYPE_REVERB,
|
FMOD_DSP_TYPE_REVERB,
|
||||||
} FMOD_DSP_TYPE;
|
} FMOD_DSP_TYPE;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_END, /* Called when a sound ends. */
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_VIRTUALVOICE, /* Called when a voice is swapped out or swapped in. */
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_SYNCPOINT, /* Called when a syncpoint is encountered. Can be from wav file markers. */
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_OCCLUSION, /* Called when the channel has its geometry occlusion value calculated. Can be used to clamp or change the value. */
|
||||||
|
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_MAX, /* Maximum number of callback types supported. */
|
||||||
|
FMOD_CHANNEL_CALLBACKTYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */
|
||||||
|
} FMOD_CHANNEL_CALLBACKTYPE;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float x; /* X co-ordinate in 3D space. */
|
||||||
|
float y; /* Y co-ordinate in 3D space. */
|
||||||
|
float z; /* Z co-ordinate in 3D space. */
|
||||||
|
} FMOD_VECTOR;
|
||||||
|
|
||||||
#define F_CALLBACK
|
#define F_CALLBACK
|
||||||
|
|
||||||
typedef int FMOD_CAPS;
|
typedef int FMOD_CAPS;
|
||||||
|
@ -77,8 +95,15 @@ typedef int FMOD_MODE;
|
||||||
#define FMOD_LOOP_OFF (1<<4)
|
#define FMOD_LOOP_OFF (1<<4)
|
||||||
#define FMOD_LOOP_NORMAL (1<<5)
|
#define FMOD_LOOP_NORMAL (1<<5)
|
||||||
#define FMOD_LOWMEM (1<<6)
|
#define FMOD_LOWMEM (1<<6)
|
||||||
|
#define FMOD_3D (1<<7)
|
||||||
|
#define FMOD_3D_HEADRELATIVE (1<<8)
|
||||||
|
#define FMOD_3D_WORLDRELATIVE (1<<9)
|
||||||
|
#define FMOD_3D_LINEARROLLOFF (1<<10)
|
||||||
#define FMOD_DEFAULT (FMOD_2D | FMOD_HARDWARE)
|
#define FMOD_DEFAULT (FMOD_2D | FMOD_HARDWARE)
|
||||||
|
|
||||||
|
typedef int FMOD_SOUND_FORMAT;
|
||||||
|
typedef int FMOD_SOUND_TYPE;
|
||||||
|
|
||||||
typedef int FMOD_CREATESOUNDEXINFO;
|
typedef int FMOD_CREATESOUNDEXINFO;
|
||||||
|
|
||||||
#define FMOD_INIT_NORMAL 0
|
#define FMOD_INIT_NORMAL 0
|
||||||
|
@ -92,6 +117,8 @@ typedef FMOD_RESULT (*FMOD_FILE_CLOSECALLBACK)(void *,void *);
|
||||||
typedef FMOD_RESULT (*FMOD_FILE_READCALLBACK)(void *,void *,unsigned int,unsigned int *,void *);
|
typedef FMOD_RESULT (*FMOD_FILE_READCALLBACK)(void *,void *,unsigned int,unsigned int *,void *);
|
||||||
typedef FMOD_RESULT (*FMOD_FILE_SEEKCALLBACK)(void *,unsigned int,void *);
|
typedef FMOD_RESULT (*FMOD_FILE_SEEKCALLBACK)(void *,unsigned int,void *);
|
||||||
|
|
||||||
|
typedef FMOD_RESULT (*FMOD_CHANNEL_CALLBACK)(void *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2);
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -112,6 +139,7 @@ namespace FMOD
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FMOD_RESULT release();
|
FMOD_RESULT release();
|
||||||
|
FMOD_RESULT getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits); // only *channels implemented
|
||||||
};
|
};
|
||||||
|
|
||||||
class DSP
|
class DSP
|
||||||
|
@ -145,7 +173,13 @@ namespace FMOD
|
||||||
FMOD_RESULT setPriority(int priority);
|
FMOD_RESULT setPriority(int priority);
|
||||||
FMOD_RESULT stop();
|
FMOD_RESULT stop();
|
||||||
FMOD_RESULT setPaused(bool paused);
|
FMOD_RESULT setPaused(bool paused);
|
||||||
FMOD_RESULT setPan(float pan);
|
FMOD_RESULT setCallback(FMOD_CHANNEL_CALLBACK callback);
|
||||||
|
FMOD_RESULT getUserData(void **userdata);
|
||||||
|
FMOD_RESULT setUserData(void *userdata);
|
||||||
|
FMOD_RESULT set3DAttributes(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel);
|
||||||
|
FMOD_RESULT set3DMinMaxDistance(float mindistance, float maxdistance);
|
||||||
|
FMOD_RESULT setMode(FMOD_MODE mode);
|
||||||
|
FMOD_RESULT getMode(FMOD_MODE *mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
class System
|
class System
|
||||||
|
@ -165,6 +199,7 @@ namespace FMOD
|
||||||
FMOD_RESULT setFileSystem(FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek, int blockalign);
|
FMOD_RESULT setFileSystem(FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek, int blockalign);
|
||||||
FMOD_RESULT setSpeakerMode(FMOD_SPEAKERMODE speakermode);
|
FMOD_RESULT setSpeakerMode(FMOD_SPEAKERMODE speakermode);
|
||||||
FMOD_RESULT update();
|
FMOD_RESULT update();
|
||||||
|
FMOD_RESULT set3DListenerAttributes(int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up);
|
||||||
|
|
||||||
// BBGE-specific...
|
// BBGE-specific...
|
||||||
FMOD_RESULT getNumChannels(int *maxchannels_ret);
|
FMOD_RESULT getNumChannels(int *maxchannels_ret);
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
#include "Localization.h"
|
#include "Localization.h"
|
||||||
|
|
||||||
#ifdef BBGE_BUILD_WINDOWS
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BBGE_BUILD_UNIX
|
#ifdef BBGE_BUILD_UNIX
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
|
@ -1055,8 +1055,12 @@ bool SoundManager::playVoice(const std::string &name, SoundVoiceType svt, float
|
||||||
checkError();
|
checkError();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
voiceChannel->setPan(0);
|
|
||||||
voiceChannel->setFrequency(1);
|
voiceChannel->setFrequency(1);
|
||||||
|
voiceChannel->setCallback(NULL);
|
||||||
|
voiceChannel->setUserData(NULL);
|
||||||
|
voiceChannel->set3DMinMaxDistance(0.0f, 0.0f);
|
||||||
|
setSoundRelative(voiceChannel, true);
|
||||||
|
setSoundPos(voiceChannel, 0, 0);
|
||||||
|
|
||||||
result = voiceChannel->setPaused(false);
|
result = voiceChannel->setPaused(false);
|
||||||
checkError();
|
checkError();
|
||||||
|
@ -1143,13 +1147,30 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
||||||
checkError();
|
checkError();
|
||||||
}
|
}
|
||||||
|
|
||||||
channel->setPan(play.pan);
|
|
||||||
|
|
||||||
float freq = play.freq;
|
float freq = play.freq;
|
||||||
if (freq <= 0)
|
if (freq <= 0)
|
||||||
freq = 1;
|
freq = 1;
|
||||||
channel->setFrequency(freq);
|
channel->setFrequency(freq);
|
||||||
|
|
||||||
|
channel->setCallback(NULL);
|
||||||
|
channel->setUserData(NULL);
|
||||||
|
|
||||||
|
// distance gain attenuation: stereo separation + silence at further away than maxdist
|
||||||
|
float maxdist = play.maxdist;
|
||||||
|
if (!maxdist)
|
||||||
|
maxdist = 1800;
|
||||||
|
|
||||||
|
if(maxdist > 0 && play.positional)
|
||||||
|
channel->set3DMinMaxDistance(maxdist * 0.3, maxdist); // HACK: this works reasonably well
|
||||||
|
else
|
||||||
|
channel->set3DMinMaxDistance(0, 0); // no attenuation
|
||||||
|
|
||||||
|
// position in space
|
||||||
|
setSoundRelative(channel, play.relative);
|
||||||
|
setSoundPos(channel, play.x, play.y); // must be set after everything else (See hack in OpenALChannel::set3DAttributes())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
result = channel->setPaused(false);
|
result = channel->setPaused(false);
|
||||||
checkError();
|
checkError();
|
||||||
|
|
||||||
|
@ -1160,23 +1181,11 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *SoundManager::playSfx(const std::string &name, float vol, float pan, float freq)
|
void *SoundManager::playSfx(const std::string &name, float vol)
|
||||||
{
|
{
|
||||||
PlaySfx play;
|
PlaySfx play;
|
||||||
play.name = name;
|
play.name = name;
|
||||||
play.vol = vol;
|
play.vol = vol;
|
||||||
play.pan = pan;
|
|
||||||
play.freq = freq;
|
|
||||||
return playSfx(play);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *SoundManager::playSfx(int handle, float vol, float pan, float freq)
|
|
||||||
{
|
|
||||||
PlaySfx play;
|
|
||||||
play.handle = handle;
|
|
||||||
play.vol = vol;
|
|
||||||
play.pan = pan;
|
|
||||||
play.freq = freq;
|
|
||||||
return playSfx(play);
|
return playSfx(play);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1205,49 +1214,6 @@ bool SoundManager::isPlayingMusic(const std::string &name)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoundManager::playMod(const std::string &name)
|
|
||||||
{
|
|
||||||
std::string fn;
|
|
||||||
|
|
||||||
fn = musicPath + name;
|
|
||||||
stringToLower(fn);
|
|
||||||
|
|
||||||
FMOD_MODE mode=0;
|
|
||||||
|
|
||||||
//FMOD_CREATESOUNDEXINFO exinfo;
|
|
||||||
|
|
||||||
//mode = FMOD_2D | FMOD_SOFTWARE | FMOD_CREATESAMPLE;//FMOD_CREATESTREAM;
|
|
||||||
mode = FMOD_HARDWARE | FMOD_2D | FMOD_CREATESTREAM;
|
|
||||||
|
|
||||||
debugLog("createSound: " + fn);
|
|
||||||
result = SoundCore::system->createSound(fn.c_str(), mode, 0, &modSound);
|
|
||||||
if (checkError())
|
|
||||||
{
|
|
||||||
debugLog("createSound failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugLog("playSound");
|
|
||||||
result = SoundCore::system->playSound(FMOD_CHANNEL_FREE, modSound, false, &modChannel);
|
|
||||||
checkError();
|
|
||||||
|
|
||||||
debugLog("setChannelGroup");
|
|
||||||
result = modChannel->setChannelGroup(group_mus);
|
|
||||||
checkError();
|
|
||||||
|
|
||||||
debugLog("setPriority");
|
|
||||||
result = modChannel->setPriority(0); // should be highest priority (according to the docs)
|
|
||||||
checkError();
|
|
||||||
|
|
||||||
debugLog("setPaused");
|
|
||||||
result = modChannel->setPaused(false);
|
|
||||||
checkError();
|
|
||||||
|
|
||||||
debugLog("returning");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SoundManager::playMusic(const std::string &name, SoundLoopType slt, SoundFadeType sft, float trans, SoundConditionType sct)
|
bool SoundManager::playMusic(const std::string &name, SoundLoopType slt, SoundFadeType sft, float trans, SoundConditionType sct)
|
||||||
{
|
{
|
||||||
debugLog("playMusic: " + name);
|
debugLog("playMusic: " + name);
|
||||||
|
@ -1372,7 +1338,11 @@ bool SoundManager::playMusic(const std::string &name, SoundLoopType slt, SoundFa
|
||||||
}
|
}
|
||||||
|
|
||||||
musicChannel->setFrequency(1); // in case the channel was used by a pitch-shifted sound before
|
musicChannel->setFrequency(1); // in case the channel was used by a pitch-shifted sound before
|
||||||
musicChannel->setPan(0);
|
musicChannel->setCallback(NULL);
|
||||||
|
musicChannel->setUserData(NULL);
|
||||||
|
musicChannel->set3DMinMaxDistance(0.0f, 0.0f); // disable attenuation
|
||||||
|
setSoundRelative(musicChannel, true);
|
||||||
|
setSoundPos(musicChannel, 0, 0);
|
||||||
|
|
||||||
result = musicChannel->setPaused(false); // This is where the sound really starts.
|
result = musicChannel->setPaused(false); // This is where the sound really starts.
|
||||||
checkError();
|
checkError();
|
||||||
|
@ -1557,7 +1527,7 @@ Buffer SoundManager::loadSoundIntoBank(const std::string &filename, const std::s
|
||||||
if (sound)
|
if (sound)
|
||||||
return sound;
|
return sound;
|
||||||
|
|
||||||
FMOD_MODE mode = FMOD_DEFAULT | FMOD_LOWMEM;
|
FMOD_MODE mode = FMOD_DEFAULT | FMOD_LOWMEM | FMOD_3D | FMOD_3D_LINEARROLLOFF;
|
||||||
if (loop)
|
if (loop)
|
||||||
mode |= FMOD_LOOP_NORMAL;
|
mode |= FMOD_LOOP_NORMAL;
|
||||||
|
|
||||||
|
@ -1680,3 +1650,122 @@ bool SoundManager::checkError()
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundManager::setListenerPos(float x, float y)
|
||||||
|
{
|
||||||
|
FMOD_VECTOR pos;
|
||||||
|
pos.x = x;
|
||||||
|
pos.y = y;
|
||||||
|
pos.z = 0.0f;
|
||||||
|
|
||||||
|
FMOD_VECTOR forward;
|
||||||
|
forward.x = 0.0f;
|
||||||
|
forward.y = 0.0f;
|
||||||
|
forward.z = -1.0f;
|
||||||
|
|
||||||
|
FMOD_VECTOR up;
|
||||||
|
up.x = 0.0f;
|
||||||
|
up.y = 1.0f;
|
||||||
|
up.z = 0.0f;
|
||||||
|
|
||||||
|
SoundCore::system->set3DListenerAttributes(0, &pos, NULL, &forward, &up);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::setSoundPos(void *channel, float x, float y)
|
||||||
|
{
|
||||||
|
if (!channel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FMOD::Channel *pChannel = (FMOD::Channel*)channel;
|
||||||
|
FMOD_VECTOR pos;
|
||||||
|
pos.x = x;
|
||||||
|
pos.y = y;
|
||||||
|
pos.z = 0.0f;
|
||||||
|
|
||||||
|
pChannel->set3DAttributes(&pos, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::setSoundRelative(void *channel, bool relative)
|
||||||
|
{
|
||||||
|
if (!channel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FMOD::Channel *pChannel = (FMOD::Channel*)channel;
|
||||||
|
|
||||||
|
FMOD_MODE mode = 0;
|
||||||
|
pChannel->getMode(&mode);
|
||||||
|
FMOD_MODE newmode = mode & ~(FMOD_3D_WORLDRELATIVE | FMOD_3D_HEADRELATIVE);
|
||||||
|
if(relative)
|
||||||
|
newmode |= (FMOD_3D_HEADRELATIVE | FMOD_3D);
|
||||||
|
else
|
||||||
|
newmode |= (FMOD_3D_WORLDRELATIVE | FMOD_3D);
|
||||||
|
|
||||||
|
if (mode != newmode)
|
||||||
|
pChannel->setMode(newmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FMOD_RESULT s_soundHolderCallback(void *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2)
|
||||||
|
{
|
||||||
|
if (!channel)
|
||||||
|
return FMOD_ERR_INVALID_PARAM;
|
||||||
|
|
||||||
|
SoundHolder *holder = NULL;
|
||||||
|
FMOD::Channel *pChannel = (FMOD::Channel*)channel;
|
||||||
|
pChannel->getUserData((void**)&holder);
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case FMOD_CHANNEL_CALLBACKTYPE_END:
|
||||||
|
holder->unlinkSound(channel);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FMOD_ERR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SoundHolder::~SoundHolder()
|
||||||
|
{
|
||||||
|
unlinkAllSounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHolder::updateSoundPosition(float x, float y)
|
||||||
|
{
|
||||||
|
if (activeSounds.size())
|
||||||
|
for(std::set<void*>::iterator it = activeSounds.begin(); it != activeSounds.end(); ++it)
|
||||||
|
sound->setSoundPos(*it, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHolder::stopAllSounds()
|
||||||
|
{
|
||||||
|
// activeSounds is modified by SoundManager::stopSfx(), which calls unkinkSound(), can't use iterator here
|
||||||
|
while(activeSounds.size())
|
||||||
|
sound->stopSfx(*activeSounds.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHolder::unlinkSound(void *channel)
|
||||||
|
{
|
||||||
|
FMOD::Channel *pChannel = (FMOD::Channel*)channel;
|
||||||
|
pChannel->setUserData(NULL);
|
||||||
|
pChannel->setCallback(NULL);
|
||||||
|
activeSounds.erase(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHolder::linkSound(void *channel)
|
||||||
|
{
|
||||||
|
if (!channel)
|
||||||
|
return;
|
||||||
|
FMOD::Channel *pChannel = (FMOD::Channel*)channel;
|
||||||
|
pChannel->setUserData(this);
|
||||||
|
pChannel->setCallback(s_soundHolderCallback);
|
||||||
|
activeSounds.insert(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundHolder::unlinkAllSounds()
|
||||||
|
{
|
||||||
|
while(activeSounds.size())
|
||||||
|
unlinkSound(*activeSounds.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
// if using SDL_MIXER
|
// if using SDL_MIXER
|
||||||
|
@ -103,20 +104,27 @@ enum SoundLoadType
|
||||||
|
|
||||||
struct PlaySfx
|
struct PlaySfx
|
||||||
{
|
{
|
||||||
PlaySfx() : priority(0.5), handle(0), pan(0), vol(1), fade(SFT_NONE), time(0), freq(1), loops(0), channel(BBGE_AUDIO_NOCHANNEL) {}
|
PlaySfx() : priority(0.5), handle(0), vol(1), fade(SFT_NONE),
|
||||||
|
time(0), freq(1), loops(0), channel(BBGE_AUDIO_NOCHANNEL),
|
||||||
|
maxdist(0), x(0), y(0), relative(true), positional(false) {}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
intptr_t handle;
|
intptr_t handle;
|
||||||
float pan;
|
|
||||||
float vol;
|
float vol;
|
||||||
float time;
|
float time;
|
||||||
float freq;
|
float freq;
|
||||||
int loops;
|
int loops;
|
||||||
int channel;
|
int channel;
|
||||||
float priority;
|
float priority;
|
||||||
|
float maxdist; // distance gain attenuation. if 0: use default value, -1: don't attenuate at all
|
||||||
SoundFadeType fade;
|
SoundFadeType fade;
|
||||||
|
float x, y;
|
||||||
|
bool relative; // relative to listener?
|
||||||
|
bool positional; // if true, this indicates that we want positional sound (stereo will be downmixed to mono to make OpenAL happy)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SoundHolder; // defined below
|
||||||
|
|
||||||
class SoundManager
|
class SoundManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -140,16 +148,18 @@ public:
|
||||||
SoundCore::Buffer getBuffer(const std::string &name);
|
SoundCore::Buffer getBuffer(const std::string &name);
|
||||||
|
|
||||||
void *playSfx(const PlaySfx &play);
|
void *playSfx(const PlaySfx &play);
|
||||||
void *playSfx(const std::string &name, float vol=1, float pan=0, float freq=1);
|
void *playSfx(const std::string &name, float vol=1);
|
||||||
void *playSfx(int handle, float vol=1, float pan=0, float freq=1);
|
|
||||||
|
|
||||||
bool playMod(const std::string &name);
|
|
||||||
bool playMusic(const std::string &name, SoundLoopType=SLT_NORMAL, SoundFadeType sft=SFT_NONE, float trans=0, SoundConditionType sct=SCT_NORMAL);
|
bool playMusic(const std::string &name, SoundLoopType=SLT_NORMAL, SoundFadeType sft=SFT_NONE, float trans=0, SoundConditionType sct=SCT_NORMAL);
|
||||||
bool playVoice(const std::string &name, SoundVoiceType=SVT_QUEUE, float vmod=-1);
|
bool playVoice(const std::string &name, SoundVoiceType=SVT_QUEUE, float vmod=-1);
|
||||||
|
|
||||||
float getMusicFader();
|
float getMusicFader();
|
||||||
float getVoxFader();
|
float getVoxFader();
|
||||||
|
|
||||||
|
void setListenerPos(float x, float y);
|
||||||
|
void setSoundPos(void *channel, float x, float y);
|
||||||
|
void setSoundRelative(void *channel, bool relative);
|
||||||
|
|
||||||
std::string getVolumeString();
|
std::string getVolumeString();
|
||||||
|
|
||||||
void toggleEffectMusic(SoundEffectType effect, bool on);
|
void toggleEffectMusic(SoundEffectType effect, bool on);
|
||||||
|
@ -248,6 +258,28 @@ private:
|
||||||
void (*loadProgressCallback)();
|
void (*loadProgressCallback)();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SoundHolder
|
||||||
|
{
|
||||||
|
friend class SoundManager;
|
||||||
|
public:
|
||||||
|
void updateSoundPosition(float x, float y);
|
||||||
|
void stopAllSounds();
|
||||||
|
void unlinkSound(void *channel);
|
||||||
|
void linkSound(void *channel);
|
||||||
|
void unlinkAllSounds();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~SoundHolder();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<void*> activeSounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
extern SoundManager *sound;
|
extern SoundManager *sound;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue