mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-08-10 08:09:53 +00:00
Merge branch 'posaudio' of file:///Users/User/code/coding/Aquaria_fg_clean
This commit is contained in:
commit
965ec50228
1 changed files with 135 additions and 86 deletions
|
@ -52,6 +52,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#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.
|
||||||
|
@ -88,7 +91,9 @@ public:
|
||||||
static void startDecoderThread();
|
static void startDecoderThread();
|
||||||
static void stopDecoderThread();
|
static void stopDecoderThread();
|
||||||
|
|
||||||
ALenum getFormat() const { return format; }
|
int getNumChannels() const { return channels; }
|
||||||
|
|
||||||
|
void setForceMono(bool mono) { forcemono = mono; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -119,7 +124,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
|
||||||
|
|
||||||
|
@ -277,6 +284,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)
|
||||||
|
@ -296,6 +306,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()
|
||||||
|
@ -338,6 +351,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)
|
||||||
|
@ -680,9 +694,9 @@ FMOD_RESULT OpenALSound::release()
|
||||||
ALBRIDGE(Sound,getFormat,(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits),(type, format, channels, bits))
|
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)
|
FMOD_RESULT OpenALSound::getFormat(FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits)
|
||||||
{
|
{
|
||||||
if(channels)
|
if(channels)
|
||||||
*channels = getNumChannels();
|
*channels = getNumChannels();
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -710,7 +724,7 @@ public:
|
||||||
FMOD_RESULT getMode(FMOD_MODE *mode);
|
FMOD_RESULT getMode(FMOD_MODE *mode);
|
||||||
|
|
||||||
void setGroupVolume(const float _volume);
|
void setGroupVolume(const float _volume);
|
||||||
void setDistanceVolume(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);
|
||||||
|
@ -737,6 +751,9 @@ private:
|
||||||
FMOD_CHANNEL_CALLBACK callback;
|
FMOD_CHANNEL_CALLBACK callback;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
FMOD_MODE _mode;
|
FMOD_MODE _mode;
|
||||||
|
float mindist;
|
||||||
|
float maxdist;
|
||||||
|
bool relative;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -779,6 +796,9 @@ OpenALChannel::OpenALChannel()
|
||||||
, inuse(false)
|
, inuse(false)
|
||||||
, initial(true)
|
, initial(true)
|
||||||
, _mode(FMOD_DEFAULT)
|
, _mode(FMOD_DEFAULT)
|
||||||
|
, mindist(0.0f)
|
||||||
|
, maxdist(0.0f)
|
||||||
|
, relative(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,6 +813,9 @@ void OpenALChannel::reacquire()
|
||||||
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)
|
||||||
|
@ -822,7 +845,7 @@ bool OpenALChannel::start(OpenALSound *sound)
|
||||||
decoder = NULL;
|
decoder = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sound->setNumChannels((decoder->getFormat() == AL_FORMAT_STEREO16) ? 2 : 1);
|
sound->setNumChannels(decoder->getNumChannels());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -952,134 +975,154 @@ FMOD_RESULT OpenALChannel::setPriority(int _priority)
|
||||||
ALBRIDGE(Channel,stop,(),())
|
ALBRIDGE(Channel,stop,(),())
|
||||||
FMOD_RESULT OpenALChannel::stop()
|
FMOD_RESULT OpenALChannel::stop()
|
||||||
{
|
{
|
||||||
if (decoder)
|
if (decoder)
|
||||||
{
|
{
|
||||||
decoder->stop();
|
decoder->stop();
|
||||||
decoder = NULL;
|
decoder = NULL;
|
||||||
}
|
}
|
||||||
alSourceStop(sid);
|
alSourceStop(sid);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
alSourcei(sid, AL_BUFFER, 0);
|
alSourcei(sid, AL_BUFFER, 0);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
if (sound)
|
if (sound)
|
||||||
{
|
{
|
||||||
sound->release();
|
sound->release();
|
||||||
sound = NULL;
|
sound = NULL;
|
||||||
}
|
}
|
||||||
if (inuse && callback)
|
if (inuse && callback)
|
||||||
callback(this, FMOD_CHANNEL_CALLBACKTYPE_END, NULL, NULL); // FIXME commanddata missing
|
callback(this, FMOD_CHANNEL_CALLBACKTYPE_END, NULL, NULL); // HACK: commanddata missing (but they are not used by the callback)
|
||||||
paused = false;
|
paused = false;
|
||||||
inuse = false;
|
inuse = false;
|
||||||
initial = false;
|
initial = false;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ALBRIDGE(Channel,setCallback,(FMOD_CHANNEL_CALLBACK callback),(callback))
|
ALBRIDGE(Channel,setCallback,(FMOD_CHANNEL_CALLBACK callback),(callback))
|
||||||
FMOD_RESULT OpenALChannel::setCallback(FMOD_CHANNEL_CALLBACK callback)
|
FMOD_RESULT OpenALChannel::setCallback(FMOD_CHANNEL_CALLBACK callback)
|
||||||
{
|
{
|
||||||
this->callback = callback;
|
this->callback = callback;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,getUserData,(void **userdata),(userdata))
|
ALBRIDGE(Channel,getUserData,(void **userdata),(userdata))
|
||||||
FMOD_RESULT OpenALChannel::getUserData(void **userdata)
|
FMOD_RESULT OpenALChannel::getUserData(void **userdata)
|
||||||
{
|
{
|
||||||
*userdata = this->userdata;
|
*userdata = this->userdata;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,setUserData,(void *userdata),(userdata))
|
ALBRIDGE(Channel,setUserData,(void *userdata),(userdata))
|
||||||
FMOD_RESULT OpenALChannel::setUserData(void *userdata)
|
FMOD_RESULT OpenALChannel::setUserData(void *userdata)
|
||||||
{
|
{
|
||||||
this->userdata = userdata;
|
this->userdata = userdata;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,set3DAttributes,(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel),(pos, vel))
|
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)
|
FMOD_RESULT OpenALChannel::set3DAttributes(const FMOD_VECTOR *pos, const FMOD_VECTOR *vel)
|
||||||
{
|
{
|
||||||
if (pos)
|
if (pos)
|
||||||
{
|
{
|
||||||
alSource3f(sid, AL_POSITION, pos->x, pos->y, pos->z);
|
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(maxdist == mindist)
|
||||||
if(vel)
|
setDistanceVolume(1.0f);
|
||||||
alSource3f(sid, AL_VELOCITY, vel->x, vel->y, vel->z);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
float d2 = dx*dx + dy*dy + dz*dz;
|
||||||
|
|
||||||
return FMOD_OK;
|
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))
|
ALBRIDGE(Channel,set3DMinMaxDistance,(float mindistance, float maxdistance),(mindistance, maxdistance))
|
||||||
FMOD_RESULT OpenALChannel::set3DMinMaxDistance(float mindistance, float maxdistance)
|
FMOD_RESULT OpenALChannel::set3DMinMaxDistance(float mindistance, float maxdistance)
|
||||||
{
|
{
|
||||||
alSourcef(sid, AL_REFERENCE_DISTANCE, mindistance);
|
alSourcef(sid, AL_REFERENCE_DISTANCE, mindistance);
|
||||||
alSourcef(sid, AL_MAX_DISTANCE, maxdistance);
|
alSourcef(sid, AL_MAX_DISTANCE, maxdistance);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
return FMOD_OK;
|
mindist = mindistance;
|
||||||
|
maxdist = maxdistance;
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,setMode,(FMOD_MODE mode),(mode))
|
ALBRIDGE(Channel,setMode,(FMOD_MODE mode),(mode))
|
||||||
FMOD_RESULT OpenALChannel::setMode(FMOD_MODE mode)
|
FMOD_RESULT OpenALChannel::setMode(FMOD_MODE mode)
|
||||||
{
|
{
|
||||||
_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();
|
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);
|
||||||
|
|
||||||
return FMOD_OK;
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
|
||||||
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBRIDGE(Channel,getMode,(FMOD_MODE *mode),(mode))
|
ALBRIDGE(Channel,getMode,(FMOD_MODE *mode),(mode))
|
||||||
FMOD_RESULT OpenALChannel::getMode(FMOD_MODE *mode)
|
FMOD_RESULT OpenALChannel::getMode(FMOD_MODE *mode)
|
||||||
{
|
{
|
||||||
*mode = _mode;
|
*mode = _mode;
|
||||||
return FMOD_OK;
|
return FMOD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALChannel::setDistanceVolume(float _volume)
|
void OpenALChannel::setDistanceVolume(float _volume)
|
||||||
{
|
{
|
||||||
distvolume = _volume;
|
distvolume = _volume;
|
||||||
applyVolume();
|
applyVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALChannel::applyVolume()
|
void OpenALChannel::applyVolume()
|
||||||
{
|
{
|
||||||
alSourcef(sid, AL_GAIN, volume * groupvolume * distvolume);
|
alSourcef(sid, AL_GAIN, volume * groupvolume * distvolume);
|
||||||
SANITY_CHECK_OPENAL_CALL();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1568,8 +1611,11 @@ FMOD_RESULT OpenALSystem::init(int maxchannels, const FMOD_INITFLAGS flags, cons
|
||||||
|
|
||||||
// HACK: FMOD doesn't do this.
|
// HACK: FMOD doesn't do this.
|
||||||
// For completeness, we pass FMOD_3D_LINEARROLLOFF to createSound().
|
// For completeness, we pass FMOD_3D_LINEARROLLOFF to createSound().
|
||||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
// 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();
|
SANITY_CHECK_OPENAL_CALL();
|
||||||
|
s_listenerPos.x = s_listenerPos.y = s_listenerPos.z = 0.0f;
|
||||||
|
|
||||||
|
|
||||||
OggDecoder::startDecoderThread();
|
OggDecoder::startDecoderThread();
|
||||||
|
@ -1714,7 +1760,10 @@ FMOD_RESULT OpenALSystem::set3DListenerAttributes(int listener, const FMOD_VECTO
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pos)
|
if(pos)
|
||||||
|
{
|
||||||
|
s_listenerPos = *pos;
|
||||||
alListener3f(AL_POSITION, pos->x, pos->y, pos->z);
|
alListener3f(AL_POSITION, pos->x, pos->y, pos->z);
|
||||||
|
}
|
||||||
|
|
||||||
if(vel)
|
if(vel)
|
||||||
alListener3f(AL_VELOCITY, vel->x, vel->y, vel->z);
|
alListener3f(AL_VELOCITY, vel->x, vel->y, vel->z);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue