mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-02-25 15:33:57 +00:00
Horrible hack to attenuate stereo sources properly.
OpenAL refuses to pan stereo sources, so apparently it needs to be done this way.
This commit is contained in:
parent
e6680da428
commit
f5da61fe78
4 changed files with 84 additions and 11 deletions
|
@ -2767,6 +2767,8 @@ luaFunc(entity_playSfx)
|
|||
sfx.name = getString(L, 2);
|
||||
sfx.freq = lua_tonumber(L, 3);
|
||||
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);
|
||||
|
|
|
@ -49,6 +49,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
//#define _DEBUG 1
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Decoder implementation for streamed Ogg Vorbis audio.
|
||||
|
@ -85,6 +88,8 @@ public:
|
|||
static void startDecoderThread();
|
||||
static void stopDecoderThread();
|
||||
|
||||
ALenum getFormat() const { return format; }
|
||||
|
||||
private:
|
||||
|
||||
void _stop();
|
||||
|
@ -597,8 +602,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 +616,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 +627,7 @@ OpenALSound::OpenALSound(VFILE *_fp, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(false)
|
||||
, bid(0)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -629,6 +639,7 @@ OpenALSound::OpenALSound(void *_data, long _size, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(false)
|
||||
, bid(0)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -640,6 +651,7 @@ OpenALSound::OpenALSound(ALuint _bid, const bool _looping)
|
|||
, refcount(1)
|
||||
, raw(true)
|
||||
, bid(_bid)
|
||||
, numChannels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -665,6 +677,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;
|
||||
|
||||
|
@ -691,6 +711,7 @@ public:
|
|||
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);
|
||||
|
@ -700,9 +721,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;
|
||||
|
@ -746,6 +770,7 @@ OpenALChannel::OpenALChannel()
|
|||
: sid(0)
|
||||
, groupvolume(1.0f)
|
||||
, volume(1.0f)
|
||||
, distvolume(1.0f)
|
||||
, paused(false)
|
||||
, priority(0)
|
||||
, frequency(1.0f)
|
||||
|
@ -763,6 +788,7 @@ void OpenALChannel::reacquire()
|
|||
assert(!inuse);
|
||||
inuse = true;
|
||||
volume = 1.0f;
|
||||
distvolume = 1.0f;
|
||||
paused = true;
|
||||
priority = 0;
|
||||
frequency = 1.0f;
|
||||
|
@ -773,8 +799,7 @@ void OpenALChannel::reacquire()
|
|||
void OpenALChannel::setGroupVolume(const float _volume)
|
||||
{
|
||||
groupvolume = _volume;
|
||||
alSourcef(sid, AL_GAIN, volume * groupvolume);
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
applyVolume();
|
||||
}
|
||||
|
||||
bool OpenALChannel::start(OpenALSound *sound)
|
||||
|
@ -798,6 +823,7 @@ bool OpenALChannel::start(OpenALSound *sound)
|
|||
decoder = NULL;
|
||||
return false;
|
||||
}
|
||||
sound->setNumChannels((decoder->getFormat() == AL_FORMAT_STEREO16) ? 2 : 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -820,8 +846,7 @@ ALBRIDGE(Channel,setVolume,(float volume),(volume))
|
|||
FMOD_RESULT OpenALChannel::setVolume(const float _volume)
|
||||
{
|
||||
volume = _volume;
|
||||
alSourcef(sid, AL_GAIN, _volume * groupvolume);
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
applyVolume();
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
@ -984,7 +1009,37 @@ ALBRIDGE(Channel,set3DAttributes,(const FMOD_VECTOR *pos, const FMOD_VECTOR *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);
|
||||
int chans = sound->getNumChannels();
|
||||
if(sound->getNumChannels() == 1)
|
||||
setDistanceVolume(1); // nothing to do
|
||||
else
|
||||
{
|
||||
// HACK: reduce volume if far away (OpanAL does not do this for stereo sounds)
|
||||
// HACK: assume linear distance model
|
||||
ALfloat listenerPos[3];
|
||||
ALint relative = 0;
|
||||
alGetSourcei(sid, AL_SOURCE_RELATIVE, &relative);
|
||||
if(relative)
|
||||
listenerPos[0] = listenerPos[1] = listenerPos[2] = 0;
|
||||
else
|
||||
alGetListenerfv(AL_POSITION, &listenerPos[0]);
|
||||
float dx = listenerPos[0] - pos->x;
|
||||
float dy = listenerPos[1] - pos->y;
|
||||
float dz = listenerPos[2] - pos->z;
|
||||
float distance = sqrtf(dx*dx + dy*dy + dz*dz);
|
||||
float rolloff = 1, refdist = 0, maxdist = 0;
|
||||
alGetSourcef(sid, AL_ROLLOFF_FACTOR, &rolloff);
|
||||
alGetSourcef(sid, AL_REFERENCE_DISTANCE, &refdist);
|
||||
alGetSourcef(sid, AL_MAX_DISTANCE, &maxdist);
|
||||
distance = std::max(distance, refdist);
|
||||
distance = std::min(distance, maxdist);
|
||||
float gain = (maxdist == refdist) ? 1 : (1 - rolloff * (distance - refdist) / (maxdist - refdist));
|
||||
setDistanceVolume(gain);
|
||||
}
|
||||
|
||||
}
|
||||
if(vel)
|
||||
alSource3f(sid, AL_VELOCITY, vel->x, vel->y, vel->z);
|
||||
|
||||
|
@ -1024,6 +1079,18 @@ FMOD_RESULT OpenALChannel::getMode(FMOD_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...
|
||||
|
@ -1330,6 +1397,7 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
|
|||
{
|
||||
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);
|
||||
|
|
|
@ -101,6 +101,8 @@ typedef int FMOD_MODE;
|
|||
#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;
|
||||
|
||||
|
@ -137,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
|
||||
|
|
|
@ -1060,8 +1060,8 @@ bool SoundManager::playVoice(const std::string &name, SoundVoiceType svt, float
|
|||
voiceChannel->setCallback(NULL);
|
||||
voiceChannel->setUserData(NULL);
|
||||
voiceChannel->set3DMinMaxDistance(0.0f, 0.0f);
|
||||
setSoundPos(voiceChannel, 0, 0);
|
||||
setSoundRelative(voiceChannel, true);
|
||||
setSoundPos(voiceChannel, 0, 0);
|
||||
|
||||
result = voiceChannel->setPaused(false);
|
||||
checkError();
|
||||
|
@ -1158,10 +1158,6 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
|||
channel->setCallback(NULL);
|
||||
channel->setUserData(NULL);
|
||||
|
||||
// position in space
|
||||
setSoundPos(channel, play.x, play.y);
|
||||
setSoundRelative(channel, play.relative);
|
||||
|
||||
// distance gain attenuation: stereo separation + silence at further away than maxdist
|
||||
float maxdist = play.maxdist;
|
||||
if (!maxdist)
|
||||
|
@ -1172,6 +1168,10 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
|||
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);
|
||||
|
@ -1344,9 +1344,9 @@ bool SoundManager::playMusic(const std::string &name, SoundLoopType slt, SoundFa
|
|||
musicChannel->setPan(0);
|
||||
musicChannel->setCallback(NULL);
|
||||
musicChannel->setUserData(NULL);
|
||||
musicChannel->set3DMinMaxDistance(0.0f, 0.0f); // disable attenuation // FIXME: is that right?
|
||||
setSoundPos(musicChannel, 0, 0);
|
||||
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();
|
||||
|
|
Loading…
Add table
Reference in a new issue