mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-15 14:09:06 +00:00
Implement stereo to mono mixing for proper L/R separation even for stereo samples.
This mixes only those sounds that are supposed to be played positional. All centered (default) sounds are played in stereo, as usual.
This commit is contained in:
parent
66802e1935
commit
cf6556b94d
5 changed files with 51 additions and 14 deletions
|
@ -2299,6 +2299,7 @@ void DSQ::playPositionalSfx(const std::string &name, const Vector &position, flo
|
|||
sfx.freq = f;
|
||||
sfx.name = name;
|
||||
sfx.relative = false;
|
||||
sfx.positional = true;
|
||||
sfx.x = position.x;
|
||||
sfx.y = position.y;
|
||||
|
||||
|
|
|
@ -2774,6 +2774,7 @@ luaFunc(entity_playSfx)
|
|||
float fadeOut = lua_tonumber(L, 6);
|
||||
sfx.maxdist = lua_tonumber(L, 7);
|
||||
sfx.relative = false;
|
||||
sfx.positional = true;
|
||||
|
||||
h = core->sound->playSfx(sfx);
|
||||
if (fadeOut != 0)
|
||||
|
@ -5944,8 +5945,12 @@ luaFunc(playSfx)
|
|||
if (sfx.vol <= 0)
|
||||
sfx.vol = 1;
|
||||
sfx.loops = lua_tointeger(L, 4);
|
||||
sfx.x = lua_tonumber(L, 5);
|
||||
sfx.y = lua_tonumber(L, 6);
|
||||
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);
|
||||
|
|
|
@ -69,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
|
||||
|
@ -322,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)
|
||||
|
@ -387,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;
|
||||
|
@ -394,8 +404,6 @@ bool OggDecoder::start(ALuint source, bool loop)
|
|||
queue(buffers[i]);
|
||||
|
||||
detachDecoder(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OggDecoder::update()
|
||||
|
@ -512,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);
|
||||
}
|
||||
}
|
||||
|
@ -839,7 +862,7 @@ 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;
|
||||
|
@ -954,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->setForceMono(mindist || maxdist); // HACK: this is set for positional sounds.
|
||||
decoder->start(sound->isLooping());
|
||||
}
|
||||
alSourcePlay(sid);
|
||||
initial = false;
|
||||
SANITY_CHECK_OPENAL_CALL();
|
||||
|
@ -1429,6 +1457,8 @@ 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);
|
||||
|
|
|
@ -1158,9 +1158,9 @@ void *SoundManager::playSfx(const PlaySfx &play)
|
|||
// distance gain attenuation: stereo separation + silence at further away than maxdist
|
||||
float maxdist = play.maxdist;
|
||||
if (!maxdist)
|
||||
maxdist = 1300;
|
||||
maxdist = 1800;
|
||||
|
||||
if(maxdist > 0)
|
||||
if(maxdist > 0 && play.positional)
|
||||
channel->set3DMinMaxDistance(maxdist * 0.3, maxdist); // HACK: this works reasonably well
|
||||
else
|
||||
channel->set3DMinMaxDistance(0, 0); // no attenuation
|
||||
|
|
|
@ -106,7 +106,7 @@ struct PlaySfx
|
|||
{
|
||||
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) {}
|
||||
maxdist(0), x(0), y(0), relative(true), positional(false) {}
|
||||
|
||||
std::string name;
|
||||
intptr_t handle;
|
||||
|
@ -119,7 +119,8 @@ struct PlaySfx
|
|||
float maxdist; // distance gain attenuation. if 0: use default value, -1: don't attenuate at all
|
||||
SoundFadeType fade;
|
||||
float x, y;
|
||||
bool relative;
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue