mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-15 14:09:06 +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);
|
||||
stopBurst();
|
||||
stopRoll();
|
||||
core->sound->playSfx("LockToWall", 1.0, 0);//, (1000+rand()%100)/1000.0f);
|
||||
core->sound->playSfx("LockToWall", 1.0);
|
||||
//bursting = false;
|
||||
this->burst = 1;
|
||||
//lastLockToWallPos = position;
|
||||
|
|
|
@ -2293,58 +2293,23 @@ void DSQ::playMenuSelectSfx()
|
|||
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;
|
||||
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.name = name;
|
||||
sfx.relative = false;
|
||||
sfx.positional = true;
|
||||
sfx.x = position.x;
|
||||
sfx.y = position.y;
|
||||
|
||||
void *c = sound->playSfx(sfx);
|
||||
|
||||
if (fadeOut != 0)
|
||||
{
|
||||
sound->fadeSfx(c, SFT_OUT, fadeOut);
|
||||
}
|
||||
|
||||
if (holder)
|
||||
holder->linkSound(c);
|
||||
}
|
||||
|
||||
void DSQ::shutdown()
|
||||
|
|
|
@ -1426,8 +1426,7 @@ public:
|
|||
bool voiceOversEnabled;
|
||||
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);
|
||||
void playPositionalSfx(const std::string &name, const Vector &position, float freq=1.0f, float fadeOut=0, SoundHolder *holder = 0);
|
||||
|
||||
void playMenuSelectSfx();
|
||||
|
||||
|
|
|
@ -284,6 +284,8 @@ Entity::Entity()
|
|||
setDamageTarget(DT_AVATAR_BUBBLE, false);
|
||||
setDamageTarget(DT_AVATAR_SEED, false);
|
||||
|
||||
stopSoundsOnDeath = false;
|
||||
|
||||
|
||||
//debugLog("End Entity::Entity()");
|
||||
}
|
||||
|
@ -573,6 +575,10 @@ void Entity::watchEntity(Entity *e)
|
|||
|
||||
void Entity::destroy()
|
||||
{
|
||||
if (stopSoundsOnDeath)
|
||||
this->stopAllSounds();
|
||||
this->unlinkAllSounds();
|
||||
|
||||
/*
|
||||
if (hair)
|
||||
{
|
||||
|
@ -1231,6 +1237,8 @@ void Entity::update(float dt)
|
|||
position = backupPos;
|
||||
if (vel.isNan())
|
||||
vel = backupVel;
|
||||
|
||||
updateSoundPosition();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
dsq->playPositionalSfx(sound, position, freq, fadeOut);
|
||||
dsq->playPositionalSfx(sound, position, freq, fadeOut, this);
|
||||
updateSoundPosition();
|
||||
}
|
||||
|
||||
Vector Entity::getEnergyShotTargetPosition()
|
||||
|
@ -3139,3 +3148,8 @@ bool Entity::isEntityInside()
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::updateSoundPosition()
|
||||
{
|
||||
SoundHolder::updateSoundPosition(position.x + offset.x, position.y + offset.y);
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ enum BounceType
|
|||
BOUNCE_REAL = 1
|
||||
};
|
||||
|
||||
class Entity : public Quad, public StateMachine
|
||||
class Entity : public Quad, public StateMachine, public SoundHolder
|
||||
{
|
||||
public:
|
||||
Entity();
|
||||
|
@ -276,6 +276,7 @@ public:
|
|||
|
||||
void popBubble();
|
||||
void sound(const std::string &sound, float freq=1, float fadeOut=0);
|
||||
void setStopSoundsOnDeath(bool stop) { stopSoundsOnDeath = stop; }
|
||||
|
||||
void freeze(float time);
|
||||
|
||||
|
@ -492,6 +493,8 @@ public:
|
|||
|
||||
bool isEntityInside();
|
||||
|
||||
void updateSoundPosition();
|
||||
|
||||
protected:
|
||||
bool calledEntityDied;
|
||||
Path *waterBubble;
|
||||
|
@ -602,6 +605,8 @@ private:
|
|||
int maxSpeed;
|
||||
int oldMaxSpeed;
|
||||
|
||||
bool stopSoundsOnDeath;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8134,13 +8134,13 @@ void Game::playBurstSound(bool wallJump)
|
|||
int freqBase = 950;
|
||||
if (wallJump)
|
||||
freqBase += 100;
|
||||
sound->playSfx("Burst", 1, 0);//, (freqBase+rand()%25)/1000.0f);
|
||||
sound->playSfx("Burst", 1);
|
||||
if (chance(50))
|
||||
{
|
||||
switch (dsq->continuity.form)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2763,28 +2763,39 @@ luaFunc(entity_playSfx)
|
|||
void *h = NULL;
|
||||
if (e && !dsq->isSkippingCutscene())
|
||||
{
|
||||
PlaySfx sfx = dsq->calcPositionalSfx(e->position, lua_tonumber(L, 7));
|
||||
PlaySfx sfx;
|
||||
sfx.name = getString(L, 2);
|
||||
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);
|
||||
|
||||
float fadeOut = lua_tonumber(L, 6);
|
||||
if(vol > 0)
|
||||
sfx.vol *= vol;
|
||||
|
||||
// FIXME: See comment in DSQ::playPositionalSfx() -- FG
|
||||
if (sfx.vol <= 0)
|
||||
luaReturnPtr(NULL);
|
||||
sfx.maxdist = lua_tonumber(L, 7);
|
||||
sfx.relative = false;
|
||||
sfx.positional = true;
|
||||
|
||||
h = core->sound->playSfx(sfx);
|
||||
if (fadeOut != 0)
|
||||
{
|
||||
sound->fadeSfx(h, SFT_OUT, fadeOut);
|
||||
}
|
||||
|
||||
e->linkSound(h);
|
||||
e->updateSoundPosition();
|
||||
}
|
||||
luaReturnPtr(h);
|
||||
}
|
||||
|
||||
luaFunc(entity_setStopSoundsOnDeath)
|
||||
{
|
||||
Entity *e = entity(L);
|
||||
if (e)
|
||||
e->setStopSoundsOnDeath(getBool(L, 2));
|
||||
luaReturnNil();
|
||||
}
|
||||
|
||||
luaFunc(entity_setSpiritFreeze)
|
||||
{
|
||||
Entity *e = entity(L);
|
||||
|
@ -5927,32 +5938,24 @@ luaFunc(emote)
|
|||
|
||||
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;
|
||||
|
||||
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.freq = freq;
|
||||
sfx.loops = loops;
|
||||
sfx.freq = lua_tonumber(L, 2);
|
||||
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;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#ifdef BBGE_BUILD_WINDOWS
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -3138,6 +3138,8 @@ void Core::main(float runTime)
|
|||
}
|
||||
}
|
||||
|
||||
sound->setListenerPos(screenCenter.x, screenCenter.y);
|
||||
|
||||
if (doScreenshot)
|
||||
{
|
||||
if (verbose) debugLog("screenshot");
|
||||
|
|
|
@ -49,6 +49,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
//#define _DEBUG 1
|
||||
#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.
|
||||
|
@ -63,8 +69,12 @@ public:
|
|||
|
||||
~OggDecoder();
|
||||
|
||||
// Start playing on the given channel, with optional looping.
|
||||
bool start(ALuint source, bool loop);
|
||||
// Prepare playing on the given channel.
|
||||
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
|
||||
// on systems without threads; may be called without harm on systems
|
||||
|
@ -85,6 +95,10 @@ public:
|
|||
static void startDecoderThread();
|
||||
static void stopDecoderThread();
|
||||
|
||||
int getNumChannels() const { return channels; }
|
||||
|
||||
void setForceMono(bool mono) { forcemono = mono; }
|
||||
|
||||
private:
|
||||
|
||||
void _stop();
|
||||
|
@ -114,7 +128,9 @@ private:
|
|||
|
||||
OggVorbis_File vf;
|
||||
ALenum format;
|
||||
int channels;
|
||||
int freq;
|
||||
bool forcemono;
|
||||
|
||||
bool thread; // true if played by background thread
|
||||
|
||||
|
@ -272,6 +288,9 @@ OggDecoder::OggDecoder(VFILE *fp)
|
|||
this->eof = false;
|
||||
this->samples_done = 0;
|
||||
this->stopped = false;
|
||||
this->format = 0;
|
||||
this->channels = 0;
|
||||
this->forcemono = false;
|
||||
}
|
||||
|
||||
OggDecoder::OggDecoder(const void *data, long data_size)
|
||||
|
@ -291,6 +310,9 @@ OggDecoder::OggDecoder(const void *data, long data_size)
|
|||
this->eof = false;
|
||||
this->samples_done = 0;
|
||||
this->stopped = false;
|
||||
this->format = 0;
|
||||
this->channels = 0;
|
||||
this->forcemono = false;
|
||||
}
|
||||
|
||||
OggDecoder::~OggDecoder()
|
||||
|
@ -304,10 +326,9 @@ OggDecoder::~OggDecoder()
|
|||
}
|
||||
}
|
||||
|
||||
bool OggDecoder::start(ALuint source, bool loop)
|
||||
bool OggDecoder::preStart(ALuint source)
|
||||
{
|
||||
this->source = source;
|
||||
this->loop = loop;
|
||||
|
||||
if (fp) {
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
channels = info->channels;
|
||||
if (info->channels == 1)
|
||||
format = AL_FORMAT_MONO16;
|
||||
else if (info->channels == 2)
|
||||
|
@ -368,6 +390,13 @@ bool OggDecoder::start(ALuint source, bool loop)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OggDecoder::start(bool loop)
|
||||
{
|
||||
this->loop = loop;
|
||||
|
||||
playing = true;
|
||||
eof = false;
|
||||
samples_done = 0;
|
||||
|
@ -375,8 +404,6 @@ bool OggDecoder::start(ALuint source, bool loop)
|
|||
queue(buffers[i]);
|
||||
|
||||
detachDecoder(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OggDecoder::update()
|
||||
|
@ -493,7 +520,22 @@ void OggDecoder::queue(ALuint buffer)
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -597,8 +639,11 @@ public:
|
|||
bool isLooping() const { return looping; }
|
||||
bool isRaw() const { return raw; }
|
||||
FMOD_RESULT release();
|
||||
FMOD_RESULT getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits);
|
||||
void reference() { refcount++; }
|
||||
ALuint getBufferName() const { return bid; }
|
||||
int getNumChannels() const { return numChannels; }
|
||||
void setNumChannels(int c) { numChannels = c; }
|
||||
|
||||
private:
|
||||
VFILE * const fp;
|
||||
|
@ -608,6 +653,7 @@ private:
|
|||
int refcount;
|
||||
const bool raw; // true if buffer holds raw PCM data
|
||||
ALuint bid; // only used if raw == true
|
||||
int numChannels;
|
||||
};
|
||||
|
||||
OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
||||
|
@ -618,6 +664,7 @@ OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(false)
|
||||
, bid(0)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -629,6 +676,7 @@ OpenALSound::OpenALSound(void *_data, long _size, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(false)
|
||||
, bid(0)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -640,6 +688,7 @@ OpenALSound::OpenALSound(ALuint _bid, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(true)
|
||||
, bid(_bid)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -665,6 +714,14 @@ FMOD_RESULT OpenALSound::release()
|
|||
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;
|
||||
|
||||
|
@ -672,7 +729,7 @@ class OpenALChannel
|
|||
{
|
||||
public:
|
||||
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 setFrequency(const float _frequency);
|
||||
FMOD_RESULT setPriority(int _priority);
|
||||
|
@ -681,8 +738,16 @@ public:
|
|||
FMOD_RESULT isPlaying(bool *isplaying);
|
||||
FMOD_RESULT setChannelGroup(ChannelGroup *channelgroup);
|
||||
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 setDistanceVolume(float _volume);
|
||||
void setSourceName(const ALuint _sid) { sid = _sid; }
|
||||
ALuint getSourceName() const { return sid; }
|
||||
bool start(OpenALSound *sound);
|
||||
|
@ -692,9 +757,12 @@ public:
|
|||
void setSound(OpenALSound *sound);
|
||||
|
||||
private:
|
||||
void applyVolume();
|
||||
|
||||
ALuint sid; // source id.
|
||||
float groupvolume;
|
||||
float volume;
|
||||
float distvolume;
|
||||
bool paused;
|
||||
int priority;
|
||||
float frequency;
|
||||
|
@ -703,6 +771,12 @@ private:
|
|||
OggDecoder *decoder;
|
||||
bool inuse;
|
||||
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)
|
||||
, groupvolume(1.0f)
|
||||
, volume(1.0f)
|
||||
, distvolume(1.0f)
|
||||
, paused(false)
|
||||
, priority(0)
|
||||
, frequency(1.0f)
|
||||
|
@ -743,6 +818,10 @@ OpenALChannel::OpenALChannel()
|
|||
, decoder(NULL)
|
||||
, inuse(false)
|
||||
, initial(true)
|
||||
, _mode(FMOD_DEFAULT)
|
||||
, mindist(0.0f)
|
||||
, maxdist(0.0f)
|
||||
, relative(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -751,18 +830,21 @@ void OpenALChannel::reacquire()
|
|||
assert(!inuse);
|
||||
inuse = true;
|
||||
volume = 1.0f;
|
||||
distvolume = 1.0f;
|
||||
paused = true;
|
||||
priority = 0;
|
||||
frequency = 1.0f;
|
||||
sound = NULL;
|
||||
initial = true;
|
||||
mindist = 0.0f;
|
||||
maxdist = 0.0f;
|
||||
relative = false;
|
||||
}
|
||||
|
||||
void OpenALChannel::setGroupVolume(const float _volume)
|
||||
{
|
||||
groupvolume = _volume;
|
||||
alSourcef(sid, AL_GAIN, volume * groupvolume);
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
applyVolume();
|
||||
}
|
||||
|
||||
bool OpenALChannel::start(OpenALSound *sound)
|
||||
|
@ -780,12 +862,13 @@ bool OpenALChannel::start(OpenALSound *sound)
|
|||
decoder = new OggDecoder(sound->getFile());
|
||||
else
|
||||
decoder = new OggDecoder(sound->getData(), sound->getSize());
|
||||
if (!decoder->start(sid, sound->isLooping()))
|
||||
if (!decoder->preStart(sid))
|
||||
{
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
return false;
|
||||
}
|
||||
sound->setNumChannels(decoder->getNumChannels());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -805,12 +888,10 @@ void OpenALChannel::update()
|
|||
}
|
||||
|
||||
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;
|
||||
alSourcef(sid, AL_GAIN, _volume * groupvolume);
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
volume = _volume;
|
||||
applyVolume();
|
||||
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))))
|
||||
{
|
||||
if (initial && decoder)
|
||||
{
|
||||
decoder->setForceMono(mindist || maxdist); // HACK: this is set for positional sounds.
|
||||
decoder->start(sound->isLooping());
|
||||
}
|
||||
alSourcePlay(sid);
|
||||
initial = false;
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
|
@ -914,15 +1000,161 @@ FMOD_RESULT OpenALChannel::setPriority(int _priority)
|
|||
return FMOD_OK;
|
||||
}
|
||||
|
||||
ALBRIDGE(Channel,setPan,(float volume),(volume))
|
||||
FMOD_RESULT OpenALChannel::setPan(const float pan)
|
||||
ALBRIDGE(Channel,stop,(),())
|
||||
FMOD_RESULT OpenALChannel::stop()
|
||||
{
|
||||
alSource3f(sid, AL_POSITION, pan, 0, 0);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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...
|
||||
|
||||
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 ...
|
||||
|
@ -1112,6 +1321,7 @@ public:
|
|||
FMOD_RESULT getDriverCaps(const int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode);
|
||||
FMOD_RESULT getMasterChannelGroup(ChannelGroup **channelgroup);
|
||||
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);
|
||||
|
||||
|
@ -1247,8 +1457,11 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
|
|||
alGenBuffers(1, &bid);
|
||||
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);
|
||||
*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;
|
||||
}
|
||||
free(data);
|
||||
|
@ -1415,7 +1628,7 @@ FMOD_RESULT OpenALSystem::init(int maxchannels, const FMOD_INITFLAGS flags, cons
|
|||
break;
|
||||
}
|
||||
|
||||
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSourcei(sid, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
alSource3f(sid, AL_POSITION, 0.0f, 0.0f, 0.0f); // no panning or spatialization in Aquaria.
|
||||
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.";
|
||||
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();
|
||||
|
||||
return FMOD_OK;
|
||||
|
@ -1539,6 +1761,46 @@ FMOD_RESULT OpenALSystem::update()
|
|||
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...
|
||||
|
||||
|
|
|
@ -60,6 +60,24 @@ typedef enum
|
|||
FMOD_DSP_TYPE_REVERB,
|
||||
} 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
|
||||
|
||||
typedef int FMOD_CAPS;
|
||||
|
@ -77,8 +95,15 @@ typedef int FMOD_MODE;
|
|||
#define FMOD_LOOP_OFF (1<<4)
|
||||
#define FMOD_LOOP_NORMAL (1<<5)
|
||||
#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)
|
||||
|
||||
typedef int FMOD_SOUND_FORMAT;
|
||||
typedef int FMOD_SOUND_TYPE;
|
||||
|
||||
typedef int FMOD_CREATESOUNDEXINFO;
|
||||
|
||||
#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_SEEKCALLBACK)(void *,unsigned int,void *);
|
||||
|
||||
typedef FMOD_RESULT (*FMOD_CHANNEL_CALLBACK)(void *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2);
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -112,6 +139,7 @@ namespace FMOD
|
|||
{
|
||||
public:
|
||||
FMOD_RESULT release();
|
||||
FMOD_RESULT getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits); // only *channels implemented
|
||||
};
|
||||
|
||||
class DSP
|
||||
|
@ -145,7 +173,13 @@ namespace FMOD
|
|||
FMOD_RESULT setPriority(int priority);
|
||||
FMOD_RESULT stop();
|
||||
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
|
||||
|
@ -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 setSpeakerMode(FMOD_SPEAKERMODE speakermode);
|
||||
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...
|
||||
FMOD_RESULT getNumChannels(int *maxchannels_ret);
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
#include "Localization.h"
|
||||
|
||||
#ifdef BBGE_BUILD_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef BBGE_BUILD_UNIX
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
|
@ -1055,8 +1055,12 @@ bool SoundManager::playVoice(const std::string &name, SoundVoiceType svt, float
|
|||
checkError();
|
||||
*/
|
||||
|
||||
voiceChannel->setPan(0);
|
||||
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);
|
||||
checkError();
|
||||
|
@ -1143,13 +1147,30 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
|||
checkError();
|
||||
}
|
||||
|
||||
channel->setPan(play.pan);
|
||||
|
||||
float freq = play.freq;
|
||||
if (freq <= 0)
|
||||
freq = 1;
|
||||
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);
|
||||
checkError();
|
||||
|
||||
|
@ -1160,23 +1181,11 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
|||
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;
|
||||
play.name = name;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1205,49 +1214,6 @@ bool SoundManager::isPlayingMusic(const std::string &name)
|
|||
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)
|
||||
{
|
||||
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->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.
|
||||
checkError();
|
||||
|
@ -1557,7 +1527,7 @@ Buffer SoundManager::loadSoundIntoBank(const std::string &filename, const std::s
|
|||
if (sound)
|
||||
return sound;
|
||||
|
||||
FMOD_MODE mode = FMOD_DEFAULT | FMOD_LOWMEM;
|
||||
FMOD_MODE mode = FMOD_DEFAULT | FMOD_LOWMEM | FMOD_3D | FMOD_3D_LINEARROLLOFF;
|
||||
if (loop)
|
||||
mode |= FMOD_LOOP_NORMAL;
|
||||
|
||||
|
@ -1680,3 +1650,122 @@ bool SoundManager::checkError()
|
|||
#endif
|
||||
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 <list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include "Vector.h"
|
||||
|
||||
// if using SDL_MIXER
|
||||
|
@ -103,20 +104,27 @@ enum SoundLoadType
|
|||
|
||||
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;
|
||||
intptr_t handle;
|
||||
float pan;
|
||||
float vol;
|
||||
float time;
|
||||
float freq;
|
||||
int loops;
|
||||
int channel;
|
||||
float priority;
|
||||
float maxdist; // distance gain attenuation. if 0: use default value, -1: don't attenuate at all
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -140,16 +148,18 @@ public:
|
|||
SoundCore::Buffer getBuffer(const std::string &name);
|
||||
|
||||
void *playSfx(const PlaySfx &play);
|
||||
void *playSfx(const std::string &name, float vol=1, float pan=0, float freq=1);
|
||||
void *playSfx(int handle, float vol=1, float pan=0, float freq=1);
|
||||
void *playSfx(const std::string &name, float vol=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 playVoice(const std::string &name, SoundVoiceType=SVT_QUEUE, float vmod=-1);
|
||||
|
||||
float getMusicFader();
|
||||
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();
|
||||
|
||||
void toggleEffectMusic(SoundEffectType effect, bool on);
|
||||
|
@ -248,6 +258,28 @@ private:
|
|||
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;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue