1
0
Fork 0
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:
fgenesis 2013-07-22 05:35:50 +02:00
parent e6680da428
commit f5da61fe78
4 changed files with 84 additions and 11 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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();