diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 1b34583f9..aa35b03b5 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -11,12 +11,12 @@ ** are met: ** ** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. +** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. ** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. +** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -99,9 +99,9 @@ bool IsOpenALPresent() void I_BuildALDeviceList(FOptionValues *opt) { - opt->mValues.Resize(1); - opt->mValues[0].TextValue = "Default"; - opt->mValues[0].Text = "Default"; + opt->mValues.Resize(1); + opt->mValues[0].TextValue = "Default"; + opt->mValues[0].Text = "Default"; #ifndef NO_OPENAL if (IsOpenALPresent()) @@ -138,31 +138,31 @@ EXTERN_CVAR (Bool, snd_pitched) static ALenum checkALError(const char *fn, unsigned int ln) { - ALenum err = alGetError(); - if(err != AL_NO_ERROR) - { - if(strchr(fn, '/')) - fn = strrchr(fn, '/')+1; - else if(strchr(fn, '\\')) - fn = strrchr(fn, '\\')+1; - Printf(">>>>>>>>>>>> Received AL error %s (%#x), %s:%u\n", alGetString(err), err, fn, ln); - } - return err; + ALenum err = alGetError(); + if(err != AL_NO_ERROR) + { + if(strchr(fn, '/')) + fn = strrchr(fn, '/')+1; + else if(strchr(fn, '\\')) + fn = strrchr(fn, '\\')+1; + Printf(">>>>>>>>>>>> Received AL error %s (%#x), %s:%u\n", alGetString(err), err, fn, ln); + } + return err; } #define getALError() checkALError(__FILE__, __LINE__) static ALCenum checkALCError(ALCdevice *device, const char *fn, unsigned int ln) { - ALCenum err = alcGetError(device); - if(err != ALC_NO_ERROR) - { - if(strchr(fn, '/')) - fn = strrchr(fn, '/')+1; - else if(strchr(fn, '\\')) - fn = strrchr(fn, '\\')+1; - Printf(">>>>>>>>>>>> Received ALC error %s (%#x), %s:%u\n", alcGetString(device, err), err, fn, ln); - } - return err; + ALCenum err = alcGetError(device); + if(err != ALC_NO_ERROR) + { + if(strchr(fn, '/')) + fn = strrchr(fn, '/')+1; + else if(strchr(fn, '\\')) + fn = strrchr(fn, '\\')+1; + Printf(">>>>>>>>>>>> Received ALC error %s (%#x), %s:%u\n", alcGetString(device, err), err, fn, ln); + } + return err; } #define getALCError(d) checkALCError((d), __FILE__, __LINE__) @@ -172,272 +172,272 @@ static ALCenum checkALCError(ALCdevice *device, const char *fn, unsigned int ln) // where they act as appropriate fallbacks. static ALvoid AL_APIENTRY _wrap_DeferUpdatesSOFT(void) { - alcSuspendContext(alcGetCurrentContext()); + alcSuspendContext(alcGetCurrentContext()); } static ALvoid AL_APIENTRY _wrap_ProcessUpdatesSOFT(void) { - alcProcessContext(alcGetCurrentContext()); + alcProcessContext(alcGetCurrentContext()); } class OpenALSoundStream : public SoundStream { - OpenALSoundRenderer *Renderer; + OpenALSoundRenderer *Renderer; - SoundStreamCallback Callback; - void *UserData; + SoundStreamCallback Callback; + void *UserData; - TArray Data; + TArray Data; - ALsizei SampleRate; - ALenum Format; - ALsizei FrameSize; + ALsizei SampleRate; + ALenum Format; + ALsizei FrameSize; - static const int BufferCount = 4; - ALuint Buffers[BufferCount]; - ALuint Source; + static const int BufferCount = 4; + ALuint Buffers[BufferCount]; + ALuint Source; - std::atomic Playing; - bool Looping; - ALfloat Volume; + std::atomic Playing; + bool Looping; + ALfloat Volume; - FileReader *Reader; - SoundDecoder *Decoder; - static bool DecoderCallback(SoundStream *_sstream, void *ptr, int length, void *user) - { - OpenALSoundStream *self = static_cast(_sstream); - if(length < 0) return false; + FileReader *Reader; + SoundDecoder *Decoder; + static bool DecoderCallback(SoundStream *_sstream, void *ptr, int length, void *user) + { + OpenALSoundStream *self = static_cast(_sstream); + if(length < 0) return false; - size_t got = self->Decoder->read((char*)ptr, length); - if(got < (unsigned int)length) - { - if(!self->Looping || !self->Decoder->seek(0)) - return false; - got += self->Decoder->read((char*)ptr+got, length-got); - } + size_t got = self->Decoder->read((char*)ptr, length); + if(got < (unsigned int)length) + { + if(!self->Looping || !self->Decoder->seek(0)) + return false; + got += self->Decoder->read((char*)ptr+got, length-got); + } - return (got == (unsigned int)length); - } + return (got == (unsigned int)length); + } - bool SetupSource() - { - /* Get a source, killing the farthest, lowest-priority sound if needed */ - if(Renderer->FreeSfx.Size() == 0) - { - FSoundChan *lowest = Renderer->FindLowestChannel(); - if(lowest) Renderer->StopChannel(lowest); + bool SetupSource() + { + /* Get a source, killing the farthest, lowest-priority sound if needed */ + if(Renderer->FreeSfx.Size() == 0) + { + FSoundChan *lowest = Renderer->FindLowestChannel(); + if(lowest) Renderer->StopChannel(lowest); - if(Renderer->FreeSfx.Size() == 0) - return false; - } - Renderer->FreeSfx.Pop(Source); + if(Renderer->FreeSfx.Size() == 0) + return false; + } + Renderer->FreeSfx.Pop(Source); - /* Set the default properties for localized playback */ - alSource3f(Source, AL_DIRECTION, 0.f, 0.f, 0.f); - alSource3f(Source, AL_VELOCITY, 0.f, 0.f, 0.f); - alSource3f(Source, AL_POSITION, 0.f, 0.f, 0.f); - alSourcef(Source, AL_MAX_GAIN, 1.f); - alSourcef(Source, AL_GAIN, 1.f); - alSourcef(Source, AL_PITCH, 1.f); - alSourcef(Source, AL_ROLLOFF_FACTOR, 0.f); - alSourcef(Source, AL_SEC_OFFSET, 0.f); - alSourcei(Source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(Source, AL_LOOPING, AL_FALSE); - if(Renderer->EnvSlot) - { - alSourcef(Source, AL_ROOM_ROLLOFF_FACTOR, 0.f); - alSourcef(Source, AL_AIR_ABSORPTION_FACTOR, 0.f); - alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL); - alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); - } - if(Renderer->AL.EXT_SOURCE_RADIUS) - alSourcef(Source, AL_SOURCE_RADIUS, 0.f); + /* Set the default properties for localized playback */ + alSource3f(Source, AL_DIRECTION, 0.f, 0.f, 0.f); + alSource3f(Source, AL_VELOCITY, 0.f, 0.f, 0.f); + alSource3f(Source, AL_POSITION, 0.f, 0.f, 0.f); + alSourcef(Source, AL_MAX_GAIN, 1.f); + alSourcef(Source, AL_GAIN, 1.f); + alSourcef(Source, AL_PITCH, 1.f); + alSourcef(Source, AL_ROLLOFF_FACTOR, 0.f); + alSourcef(Source, AL_SEC_OFFSET, 0.f); + alSourcei(Source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(Source, AL_LOOPING, AL_FALSE); + if(Renderer->EnvSlot) + { + alSourcef(Source, AL_ROOM_ROLLOFF_FACTOR, 0.f); + alSourcef(Source, AL_AIR_ABSORPTION_FACTOR, 0.f); + alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL); + alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); + } + if(Renderer->AL.EXT_SOURCE_RADIUS) + alSourcef(Source, AL_SOURCE_RADIUS, 0.f); - alGenBuffers(BufferCount, Buffers); - return (getALError() == AL_NO_ERROR); - } + alGenBuffers(BufferCount, Buffers); + return (getALError() == AL_NO_ERROR); + } public: - OpenALSoundStream(OpenALSoundRenderer *renderer) - : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL) - { - memset(Buffers, 0, sizeof(Buffers)); - Renderer->AddStream(this); - } + OpenALSoundStream(OpenALSoundRenderer *renderer) + : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL) + { + memset(Buffers, 0, sizeof(Buffers)); + Renderer->AddStream(this); + } - virtual ~OpenALSoundStream() - { - Renderer->RemoveStream(this); + virtual ~OpenALSoundStream() + { + Renderer->RemoveStream(this); - if(Source) - { - alSourceRewind(Source); - alSourcei(Source, AL_BUFFER, 0); + if(Source) + { + alSourceRewind(Source); + alSourcei(Source, AL_BUFFER, 0); - Renderer->FreeSfx.Push(Source); - Source = 0; - } + Renderer->FreeSfx.Push(Source); + Source = 0; + } - if(Buffers[0]) - { - alDeleteBuffers(BufferCount, &Buffers[0]); - memset(Buffers, 0, sizeof(Buffers)); - } - getALError(); + if(Buffers[0]) + { + alDeleteBuffers(BufferCount, &Buffers[0]); + memset(Buffers, 0, sizeof(Buffers)); + } + getALError(); - delete Decoder; - delete Reader; - } + delete Decoder; + delete Reader; + } - virtual bool Play(bool loop, float vol) - { - SetVolume(vol); + virtual bool Play(bool loop, float vol) + { + SetVolume(vol); - if(Playing.load()) - return true; + if(Playing.load()) + return true; - /* Clear the buffer queue, then fill and queue each buffer */ - alSourcei(Source, AL_BUFFER, 0); - for(int i = 0;i < BufferCount;i++) - { - if(!Callback(this, &Data[0], Data.Size(), UserData)) - { - if(i == 0) - return false; - break; - } + /* Clear the buffer queue, then fill and queue each buffer */ + alSourcei(Source, AL_BUFFER, 0); + for(int i = 0;i < BufferCount;i++) + { + if(!Callback(this, &Data[0], Data.Size(), UserData)) + { + if(i == 0) + return false; + break; + } - alBufferData(Buffers[i], Format, &Data[0], Data.Size(), SampleRate); - alSourceQueueBuffers(Source, 1, &Buffers[i]); - } - if(getALError() != AL_NO_ERROR) - return false; + alBufferData(Buffers[i], Format, &Data[0], Data.Size(), SampleRate); + alSourceQueueBuffers(Source, 1, &Buffers[i]); + } + if(getALError() != AL_NO_ERROR) + return false; - alSourcePlay(Source); - if(getALError() != AL_NO_ERROR) - return false; + alSourcePlay(Source); + if(getALError() != AL_NO_ERROR) + return false; - Playing.store(true); - return true; - } + Playing.store(true); + return true; + } - virtual void Stop() - { - if(!Playing.load()) - return; + virtual void Stop() + { + if(!Playing.load()) + return; - std::unique_lock lock(Renderer->StreamLock); - alSourceStop(Source); - alSourcei(Source, AL_BUFFER, 0); - getALError(); + std::unique_lock lock(Renderer->StreamLock); + alSourceStop(Source); + alSourcei(Source, AL_BUFFER, 0); + getALError(); - Playing.store(false); - } + Playing.store(false); + } - virtual void SetVolume(float vol) - { - Volume = vol; - UpdateVolume(); - } + virtual void SetVolume(float vol) + { + Volume = vol; + UpdateVolume(); + } - void UpdateVolume() - { - alSourcef(Source, AL_GAIN, Renderer->MusicVolume*Volume); - getALError(); - } + void UpdateVolume() + { + alSourcef(Source, AL_GAIN, Renderer->MusicVolume*Volume); + getALError(); + } - virtual bool SetPaused(bool pause) - { - if(pause) - alSourcePause(Source); - else - alSourcePlay(Source); - return (getALError()==AL_NO_ERROR); - } + virtual bool SetPaused(bool pause) + { + if(pause) + alSourcePause(Source); + else + alSourcePlay(Source); + return (getALError()==AL_NO_ERROR); + } - virtual bool SetPosition(unsigned int ms_pos) - { - std::unique_lock lock(Renderer->StreamLock); - if(!Decoder->seek(ms_pos)) - return false; + virtual bool SetPosition(unsigned int ms_pos) + { + std::unique_lock lock(Renderer->StreamLock); + if(!Decoder->seek(ms_pos)) + return false; - if(!Playing.load()) - return true; - // Stop the source so that all buffers become processed, which will - // allow the next update to restart the source queue with the new - // position. - alSourceStop(Source); - getALError(); - lock.unlock(); - Renderer->StreamWake.notify_all(); - return true; - } + if(!Playing.load()) + return true; + // Stop the source so that all buffers become processed, which will + // allow the next update to restart the source queue with the new + // position. + alSourceStop(Source); + getALError(); + lock.unlock(); + Renderer->StreamWake.notify_all(); + return true; + } - virtual unsigned int GetPosition() - { - std::unique_lock lock(Renderer->StreamLock); - ALint offset, queued, state; - alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); - alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); - alGetSourcei(Source, AL_SOURCE_STATE, &state); - if(getALError() != AL_NO_ERROR) - return 0; + virtual unsigned int GetPosition() + { + std::unique_lock lock(Renderer->StreamLock); + ALint offset, queued, state; + alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + alGetSourcei(Source, AL_SOURCE_STATE, &state); + if(getALError() != AL_NO_ERROR) + return 0; - size_t pos = Decoder->getSampleOffset(); - lock.unlock(); + size_t pos = Decoder->getSampleOffset(); + lock.unlock(); - if(state != AL_STOPPED) - { - size_t rem = queued*(Data.Size()/FrameSize) - offset; - if(pos > rem) pos -= rem; - else pos = 0; - } - return (unsigned int)(pos * 1000.0 / SampleRate); - } + if(state != AL_STOPPED) + { + size_t rem = queued*(Data.Size()/FrameSize) - offset; + if(pos > rem) pos -= rem; + else pos = 0; + } + return (unsigned int)(pos * 1000.0 / SampleRate); + } - virtual bool IsEnded() - { - return !Playing.load(); - } + virtual bool IsEnded() + { + return !Playing.load(); + } - virtual FString GetStats() - { - FString stats; - size_t pos = 0, len = 0; - ALfloat volume; - ALint offset; - ALint processed; - ALint queued; - ALint state; - ALenum err; + virtual FString GetStats() + { + FString stats; + size_t pos = 0, len = 0; + ALfloat volume; + ALint offset; + ALint processed; + ALint queued; + ALint state; + ALenum err; - std::unique_lock lock(Renderer->StreamLock); - alGetSourcef(Source, AL_GAIN, &volume); - alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); - alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); - alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); - alGetSourcei(Source, AL_SOURCE_STATE, &state); - if((err=alGetError()) != AL_NO_ERROR) - { - lock.unlock(); - stats = "Error getting stats: "; - stats += alGetString(err); - return stats; - } + std::unique_lock lock(Renderer->StreamLock); + alGetSourcef(Source, AL_GAIN, &volume); + alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); + alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + alGetSourcei(Source, AL_SOURCE_STATE, &state); + if((err=alGetError()) != AL_NO_ERROR) + { + lock.unlock(); + stats = "Error getting stats: "; + stats += alGetString(err); + return stats; + } if (Decoder != nullptr) { pos = Decoder->getSampleOffset(); len = Decoder->getSampleLength(); } - lock.unlock(); + lock.unlock(); - stats = (state == AL_INITIAL) ? "Buffering" : (state == AL_STOPPED) ? "Underrun" : - (state == AL_PLAYING || state == AL_PAUSED) ? "Ready" : "Unknown state"; + stats = (state == AL_INITIAL) ? "Buffering" : (state == AL_STOPPED) ? "Underrun" : + (state == AL_PLAYING || state == AL_PAUSED) ? "Ready" : "Unknown state"; if (Decoder != nullptr) { @@ -457,177 +457,177 @@ public: if (len > 0) stats.AppendFormat(" / %zu.%03zu", len / 1000, len % 1000); } - if(state == AL_PAUSED) - stats += ", paused"; - if(state == AL_PLAYING) - stats += ", playing"; - stats.AppendFormat(", %uHz", SampleRate); - if(!Playing) - stats += " XX"; - return stats; - } + if(state == AL_PAUSED) + stats += ", paused"; + if(state == AL_PLAYING) + stats += ", playing"; + stats.AppendFormat(", %uHz", SampleRate); + if(!Playing) + stats += " XX"; + return stats; + } - bool Process() - { - if(!Playing.load()) - return false; + bool Process() + { + if(!Playing.load()) + return false; - ALint state, processed; - alGetSourcei(Source, AL_SOURCE_STATE, &state); - alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); - if(getALError() != AL_NO_ERROR) - { - Playing.store(false); - return false; - } + ALint state, processed; + alGetSourcei(Source, AL_SOURCE_STATE, &state); + alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); + if(getALError() != AL_NO_ERROR) + { + Playing.store(false); + return false; + } - // For each processed buffer in the queue... - while(processed > 0) - { - ALuint bufid; + // For each processed buffer in the queue... + while(processed > 0) + { + ALuint bufid; - // Unqueue the oldest buffer, fill it with more data, and queue it - // on the end - alSourceUnqueueBuffers(Source, 1, &bufid); - processed--; + // Unqueue the oldest buffer, fill it with more data, and queue it + // on the end + alSourceUnqueueBuffers(Source, 1, &bufid); + processed--; - if(Callback(this, &Data[0], Data.Size(), UserData)) - { - alBufferData(bufid, Format, &Data[0], Data.Size(), SampleRate); - alSourceQueueBuffers(Source, 1, &bufid); - } - } + if(Callback(this, &Data[0], Data.Size(), UserData)) + { + alBufferData(bufid, Format, &Data[0], Data.Size(), SampleRate); + alSourceQueueBuffers(Source, 1, &bufid); + } + } - // If the source is not playing or paused, and there are buffers queued, - // then there was an underrun. Restart the source. - bool ok = (getALError()==AL_NO_ERROR); - if(ok && state != AL_PLAYING && state != AL_PAUSED) - { - ALint queued = 0; - alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + // If the source is not playing or paused, and there are buffers queued, + // then there was an underrun. Restart the source. + bool ok = (getALError()==AL_NO_ERROR); + if(ok && state != AL_PLAYING && state != AL_PAUSED) + { + ALint queued = 0; + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); - ok = (getALError() == AL_NO_ERROR) && (queued > 0); - if(ok) - { - alSourcePlay(Source); - ok = (getALError()==AL_NO_ERROR); - } - } + ok = (getALError() == AL_NO_ERROR) && (queued > 0); + if(ok) + { + alSourcePlay(Source); + ok = (getALError()==AL_NO_ERROR); + } + } - Playing.store(ok); - return ok; - } + Playing.store(ok); + return ok; + } - bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) - { - if(!SetupSource()) - return false; + bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) + { + if(!SetupSource()) + return false; - Callback = callback; - UserData = userdata; - SampleRate = samplerate; + Callback = callback; + UserData = userdata; + SampleRate = samplerate; - Format = AL_NONE; - if((flags&Bits8)) /* Signed or unsigned? We assume unsigned 8-bit... */ - { - if((flags&Mono)) Format = AL_FORMAT_MONO8; - else Format = AL_FORMAT_STEREO8; - } - else if((flags&Float)) - { - if(alIsExtensionPresent("AL_EXT_FLOAT32")) - { - if((flags&Mono)) Format = AL_FORMAT_MONO_FLOAT32; - else Format = AL_FORMAT_STEREO_FLOAT32; - } - } - else if((flags&Bits32)) - { - } - else - { - if((flags&Mono)) Format = AL_FORMAT_MONO16; - else Format = AL_FORMAT_STEREO16; - } + Format = AL_NONE; + if((flags&Bits8)) /* Signed or unsigned? We assume unsigned 8-bit... */ + { + if((flags&Mono)) Format = AL_FORMAT_MONO8; + else Format = AL_FORMAT_STEREO8; + } + else if((flags&Float)) + { + if(alIsExtensionPresent("AL_EXT_FLOAT32")) + { + if((flags&Mono)) Format = AL_FORMAT_MONO_FLOAT32; + else Format = AL_FORMAT_STEREO_FLOAT32; + } + } + else if((flags&Bits32)) + { + } + else + { + if((flags&Mono)) Format = AL_FORMAT_MONO16; + else Format = AL_FORMAT_STEREO16; + } - if(Format == AL_NONE) - { - Printf("Unsupported format: 0x%x\n", flags); - return false; - } + if(Format == AL_NONE) + { + Printf("Unsupported format: 0x%x\n", flags); + return false; + } - FrameSize = 1; - if((flags&Bits8)) - FrameSize *= 1; - else if((flags&(Bits32|Float))) - FrameSize *= 4; - else - FrameSize *= 2; + FrameSize = 1; + if((flags&Bits8)) + FrameSize *= 1; + else if((flags&(Bits32|Float))) + FrameSize *= 4; + else + FrameSize *= 2; - if((flags&Mono)) - FrameSize *= 1; - else - FrameSize *= 2; + if((flags&Mono)) + FrameSize *= 1; + else + FrameSize *= 2; - buffbytes += FrameSize-1; - buffbytes -= buffbytes%FrameSize; - Data.Resize(buffbytes); + buffbytes += FrameSize-1; + buffbytes -= buffbytes%FrameSize; + Data.Resize(buffbytes); - return true; - } + return true; + } - bool Init(FileReader *reader, bool loop) - { - if(!SetupSource()) - { - delete reader; - return false; - } + bool Init(FileReader *reader, bool loop) + { + if(!SetupSource()) + { + delete reader; + return false; + } - if(Decoder) delete Decoder; - if(Reader) delete Reader; - Reader = reader; - Decoder = Renderer->CreateDecoder(Reader); - if(!Decoder) return false; + if(Decoder) delete Decoder; + if(Reader) delete Reader; + Reader = reader; + Decoder = Renderer->CreateDecoder(Reader); + if(!Decoder) return false; - Callback = DecoderCallback; - UserData = NULL; - Format = AL_NONE; - FrameSize = 1; + Callback = DecoderCallback; + UserData = NULL; + Format = AL_NONE; + FrameSize = 1; - ChannelConfig chans; - SampleType type; - int srate; + ChannelConfig chans; + SampleType type; + int srate; - Decoder->getInfo(&srate, &chans, &type); - if(chans == ChannelConfig_Mono) - { - if(type == SampleType_UInt8) Format = AL_FORMAT_MONO8; - if(type == SampleType_Int16) Format = AL_FORMAT_MONO16; - FrameSize *= 1; - } - if(chans == ChannelConfig_Stereo) - { - if(type == SampleType_UInt8) Format = AL_FORMAT_STEREO8; - if(type == SampleType_Int16) Format = AL_FORMAT_STEREO16; - FrameSize *= 2; - } - if(type == SampleType_UInt8) FrameSize *= 1; - if(type == SampleType_Int16) FrameSize *= 2; + Decoder->getInfo(&srate, &chans, &type); + if(chans == ChannelConfig_Mono) + { + if(type == SampleType_UInt8) Format = AL_FORMAT_MONO8; + if(type == SampleType_Int16) Format = AL_FORMAT_MONO16; + FrameSize *= 1; + } + if(chans == ChannelConfig_Stereo) + { + if(type == SampleType_UInt8) Format = AL_FORMAT_STEREO8; + if(type == SampleType_Int16) Format = AL_FORMAT_STEREO16; + FrameSize *= 2; + } + if(type == SampleType_UInt8) FrameSize *= 1; + if(type == SampleType_Int16) FrameSize *= 2; - if(Format == AL_NONE) - { - Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), - GetSampleTypeName(type)); - return false; - } - SampleRate = srate; - Looping = loop; + if(Format == AL_NONE) + { + Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), + GetSampleTypeName(type)); + return false; + } + SampleRate = srate; + Looping = loop; - Data.Resize((SampleRate / 5) * FrameSize); + Data.Resize((SampleRate / 5) * FrameSize); - return true; - } + return true; + } }; @@ -641,32 +641,32 @@ extern ReverbContainer *ForcedEnvironment; static size_t GetChannelCount(ChannelConfig chans) { - switch(chans) - { - case ChannelConfig_Mono: return 1; - case ChannelConfig_Stereo: return 2; - } - return 0; + switch(chans) + { + case ChannelConfig_Mono: return 1; + case ChannelConfig_Stereo: return 2; + } + return 0; } static float GetRolloff(const FRolloffInfo *rolloff, float distance) { - if(distance <= rolloff->MinDistance) - return 1.f; - // Logarithmic rolloff has no max distance where it goes silent. - if(rolloff->RolloffType == ROLLOFF_Log) - return rolloff->MinDistance / - (rolloff->MinDistance + rolloff->RolloffFactor*(distance-rolloff->MinDistance)); - if(distance >= rolloff->MaxDistance) - return 0.f; + if(distance <= rolloff->MinDistance) + return 1.f; + // Logarithmic rolloff has no max distance where it goes silent. + if(rolloff->RolloffType == ROLLOFF_Log) + return rolloff->MinDistance / + (rolloff->MinDistance + rolloff->RolloffFactor*(distance-rolloff->MinDistance)); + if(distance >= rolloff->MaxDistance) + return 0.f; - float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); - if(rolloff->RolloffType == ROLLOFF_Linear) - return volume; + float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); + if(rolloff->RolloffType == ROLLOFF_Linear) + return volume; - if(rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve != NULL) - return S_SoundCurve[int(S_SoundCurveSize * (1.f - volume))] / 127.f; - return (powf(10.f, volume) - 1.f) / 9.f; + if(rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve != NULL) + return S_SoundCurve[int(S_SoundCurveSize * (1.f - volume))] / 127.f; + return (powf(10.f, volume) - 1.f) / 9.f; } ALCdevice *OpenALSoundRenderer::InitDevice() @@ -700,608 +700,612 @@ ALCdevice *OpenALSoundRenderer::InitDevice() template static void LoadALFunc(const char *name, T *x) -{ *x = reinterpret_cast(alGetProcAddress(name)); } +{ + *x = reinterpret_cast(alGetProcAddress(name)); +} template static void LoadALCFunc(ALCdevice *device, const char *name, T *x) -{ *x = reinterpret_cast(alcGetProcAddress(device, name)); } +{ + *x = reinterpret_cast(alcGetProcAddress(device, name)); +} #define LOAD_FUNC(x) (LoadALFunc(#x, &x)) #define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x)) OpenALSoundRenderer::OpenALSoundRenderer() - : QuitThread(false), Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) + : QuitThread(false), Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) { - EnvFilters[0] = EnvFilters[1] = 0; + EnvFilters[0] = EnvFilters[1] = 0; - Printf("I_InitSound: Initializing OpenAL\n"); + Printf("I_InitSound: Initializing OpenAL\n"); Device = InitDevice(); if (Device == NULL) return; - const ALCchar *current = NULL; - if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) - current = alcGetString(Device, ALC_ALL_DEVICES_SPECIFIER); - if(alcGetError(Device) != ALC_NO_ERROR || !current) - current = alcGetString(Device, ALC_DEVICE_SPECIFIER); - Printf(" Opened device " TEXTCOLOR_ORANGE"%s\n", current); + const ALCchar *current = NULL; + if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) + current = alcGetString(Device, ALC_ALL_DEVICES_SPECIFIER); + if(alcGetError(Device) != ALC_NO_ERROR || !current) + current = alcGetString(Device, ALC_DEVICE_SPECIFIER); + Printf(" Opened device " TEXTCOLOR_ORANGE"%s\n", current); - ALCint major=0, minor=0; - alcGetIntegerv(Device, ALC_MAJOR_VERSION, 1, &major); - alcGetIntegerv(Device, ALC_MINOR_VERSION, 1, &minor); - DPrintf(DMSG_SPAMMY, " ALC Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); - DPrintf(DMSG_SPAMMY, " ALC Extensions: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_EXTENSIONS)); + ALCint major=0, minor=0; + alcGetIntegerv(Device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(Device, ALC_MINOR_VERSION, 1, &minor); + DPrintf(DMSG_SPAMMY, " ALC Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); + DPrintf(DMSG_SPAMMY, " ALC Extensions: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_EXTENSIONS)); - TArray attribs; - if(*snd_samplerate > 0) - { - attribs.Push(ALC_FREQUENCY); - attribs.Push(*snd_samplerate); - } - // Make sure one source is capable of stereo output with the rest doing - // mono, without running out of voices - attribs.Push(ALC_MONO_SOURCES); - attribs.Push(MAX(*snd_channels, 2) - 1); - attribs.Push(ALC_STEREO_SOURCES); - attribs.Push(1); - // Other attribs..? - attribs.Push(0); + TArray attribs; + if(*snd_samplerate > 0) + { + attribs.Push(ALC_FREQUENCY); + attribs.Push(*snd_samplerate); + } + // Make sure one source is capable of stereo output with the rest doing + // mono, without running out of voices + attribs.Push(ALC_MONO_SOURCES); + attribs.Push(MAX(*snd_channels, 2) - 1); + attribs.Push(ALC_STEREO_SOURCES); + attribs.Push(1); + // Other attribs..? + attribs.Push(0); - Context = alcCreateContext(Device, &attribs[0]); - if(!Context || alcMakeContextCurrent(Context) == ALC_FALSE) - { - Printf(TEXTCOLOR_RED" Failed to setup context: %s\n", alcGetString(Device, alcGetError(Device))); - if(Context) - alcDestroyContext(Context); - Context = NULL; - alcCloseDevice(Device); - Device = NULL; - return; - } - attribs.Clear(); + Context = alcCreateContext(Device, &attribs[0]); + if(!Context || alcMakeContextCurrent(Context) == ALC_FALSE) + { + Printf(TEXTCOLOR_RED" Failed to setup context: %s\n", alcGetString(Device, alcGetError(Device))); + if(Context) + alcDestroyContext(Context); + Context = NULL; + alcCloseDevice(Device); + Device = NULL; + return; + } + attribs.Clear(); - DPrintf(DMSG_SPAMMY, " Vendor: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VENDOR)); - DPrintf(DMSG_SPAMMY, " Renderer: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_RENDERER)); - DPrintf(DMSG_SPAMMY, " Version: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VERSION)); - DPrintf(DMSG_SPAMMY, " Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS)); + DPrintf(DMSG_SPAMMY, " Vendor: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VENDOR)); + DPrintf(DMSG_SPAMMY, " Renderer: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_RENDERER)); + DPrintf(DMSG_SPAMMY, " Version: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VERSION)); + DPrintf(DMSG_SPAMMY, " Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS)); - ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX"); - ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect"); - ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device"); - AL.EXT_source_distance_model = !!alIsExtensionPresent("AL_EXT_source_distance_model"); - AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS"); - AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates"); - AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points"); + ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX"); + ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect"); + ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device"); + AL.EXT_source_distance_model = !!alIsExtensionPresent("AL_EXT_source_distance_model"); + AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS"); + AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates"); + AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points"); - alDopplerFactor(0.5f); - alSpeedOfSound(343.3f * 96.0f); - alDistanceModel(AL_INVERSE_DISTANCE); - if(AL.EXT_source_distance_model) - alEnable(AL_SOURCE_DISTANCE_MODEL); + alDopplerFactor(0.5f); + alSpeedOfSound(343.3f * 96.0f); + alDistanceModel(AL_INVERSE_DISTANCE); + if(AL.EXT_source_distance_model) + alEnable(AL_SOURCE_DISTANCE_MODEL); - if(AL.SOFT_deferred_updates) - { - LOAD_FUNC(alDeferUpdatesSOFT); - LOAD_FUNC(alProcessUpdatesSOFT); - } - else - { - alDeferUpdatesSOFT = _wrap_DeferUpdatesSOFT; - alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT; - } + if(AL.SOFT_deferred_updates) + { + LOAD_FUNC(alDeferUpdatesSOFT); + LOAD_FUNC(alProcessUpdatesSOFT); + } + else + { + alDeferUpdatesSOFT = _wrap_DeferUpdatesSOFT; + alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT; + } - if(ALC.SOFT_pause_device) - { - LOAD_DEV_FUNC(Device, alcDevicePauseSOFT); - LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT); - } + if(ALC.SOFT_pause_device) + { + LOAD_DEV_FUNC(Device, alcDevicePauseSOFT); + LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT); + } - ALenum err = getALError(); - if(err != AL_NO_ERROR) - { - alcMakeContextCurrent(NULL); - alcDestroyContext(Context); - Context = NULL; - alcCloseDevice(Device); - Device = NULL; - return; - } + ALenum err = getALError(); + if(err != AL_NO_ERROR) + { + alcMakeContextCurrent(NULL); + alcDestroyContext(Context); + Context = NULL; + alcCloseDevice(Device); + Device = NULL; + return; + } - ALCint numMono=0, numStereo=0; - alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &numMono); - alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &numStereo); + ALCint numMono=0, numStereo=0; + alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &numMono); + alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &numStereo); - // OpenAL specification doesn't require alcGetIntegerv() to return - // meaningful values for ALC_MONO_SOURCES and ALC_MONO_SOURCES. - // At least Apple's OpenAL implementation returns zeroes, - // although it can generate reasonable number of sources. + // OpenAL specification doesn't require alcGetIntegerv() to return + // meaningful values for ALC_MONO_SOURCES and ALC_MONO_SOURCES. + // At least Apple's OpenAL implementation returns zeroes, + // although it can generate reasonable number of sources. - const int numChannels = MAX(*snd_channels, 2); - int numSources = numMono + numStereo; + const int numChannels = MAX(*snd_channels, 2); + int numSources = numMono + numStereo; - if (0 == numSources) - { - numSources = numChannels; - } + if (0 == numSources) + { + numSources = numChannels; + } - Sources.Resize(MIN(numChannels, numSources)); - for(unsigned i = 0;i < Sources.Size();i++) - { - alGenSources(1, &Sources[i]); - if(getALError() != AL_NO_ERROR) - { - Sources.Resize(i); - Sources.ShrinkToFit(); - break; - } - } - if(Sources.Size() == 0) - { - Printf(TEXTCOLOR_RED" Error: could not generate any sound sources!\n"); - alcMakeContextCurrent(NULL); - alcDestroyContext(Context); - Context = NULL; - alcCloseDevice(Device); - Device = NULL; - return; - } - FreeSfx = Sources; - DPrintf(DMSG_NOTIFY, " Allocated " TEXTCOLOR_BLUE"%u" TEXTCOLOR_NORMAL" sources\n", Sources.Size()); + Sources.Resize(MIN(numChannels, numSources)); + for(unsigned i = 0;i < Sources.Size();i++) + { + alGenSources(1, &Sources[i]); + if(getALError() != AL_NO_ERROR) + { + Sources.Resize(i); + Sources.ShrinkToFit(); + break; + } + } + if(Sources.Size() == 0) + { + Printf(TEXTCOLOR_RED" Error: could not generate any sound sources!\n"); + alcMakeContextCurrent(NULL); + alcDestroyContext(Context); + Context = NULL; + alcCloseDevice(Device); + Device = NULL; + return; + } + FreeSfx = Sources; + DPrintf(DMSG_NOTIFY, " Allocated " TEXTCOLOR_BLUE"%u" TEXTCOLOR_NORMAL" sources\n", Sources.Size()); - WasInWater = false; - if(*snd_efx && ALC.EXT_EFX) - { - // EFX function pointers - LOAD_FUNC(alGenEffects); - LOAD_FUNC(alDeleteEffects); - LOAD_FUNC(alIsEffect); - LOAD_FUNC(alEffecti); - LOAD_FUNC(alEffectiv); - LOAD_FUNC(alEffectf); - LOAD_FUNC(alEffectfv); - LOAD_FUNC(alGetEffecti); - LOAD_FUNC(alGetEffectiv); - LOAD_FUNC(alGetEffectf); - LOAD_FUNC(alGetEffectfv); + WasInWater = false; + if(*snd_efx && ALC.EXT_EFX) + { + // EFX function pointers + LOAD_FUNC(alGenEffects); + LOAD_FUNC(alDeleteEffects); + LOAD_FUNC(alIsEffect); + LOAD_FUNC(alEffecti); + LOAD_FUNC(alEffectiv); + LOAD_FUNC(alEffectf); + LOAD_FUNC(alEffectfv); + LOAD_FUNC(alGetEffecti); + LOAD_FUNC(alGetEffectiv); + LOAD_FUNC(alGetEffectf); + LOAD_FUNC(alGetEffectfv); - LOAD_FUNC(alGenFilters); - LOAD_FUNC(alDeleteFilters); - LOAD_FUNC(alIsFilter); - LOAD_FUNC(alFilteri); - LOAD_FUNC(alFilteriv); - LOAD_FUNC(alFilterf); - LOAD_FUNC(alFilterfv); - LOAD_FUNC(alGetFilteri); - LOAD_FUNC(alGetFilteriv); - LOAD_FUNC(alGetFilterf); - LOAD_FUNC(alGetFilterfv); + LOAD_FUNC(alGenFilters); + LOAD_FUNC(alDeleteFilters); + LOAD_FUNC(alIsFilter); + LOAD_FUNC(alFilteri); + LOAD_FUNC(alFilteriv); + LOAD_FUNC(alFilterf); + LOAD_FUNC(alFilterfv); + LOAD_FUNC(alGetFilteri); + LOAD_FUNC(alGetFilteriv); + LOAD_FUNC(alGetFilterf); + LOAD_FUNC(alGetFilterfv); - LOAD_FUNC(alGenAuxiliaryEffectSlots); - LOAD_FUNC(alDeleteAuxiliaryEffectSlots); - LOAD_FUNC(alIsAuxiliaryEffectSlot); - LOAD_FUNC(alAuxiliaryEffectSloti); - LOAD_FUNC(alAuxiliaryEffectSlotiv); - LOAD_FUNC(alAuxiliaryEffectSlotf); - LOAD_FUNC(alAuxiliaryEffectSlotfv); - LOAD_FUNC(alGetAuxiliaryEffectSloti); - LOAD_FUNC(alGetAuxiliaryEffectSlotiv); - LOAD_FUNC(alGetAuxiliaryEffectSlotf); - LOAD_FUNC(alGetAuxiliaryEffectSlotfv); - if(getALError() == AL_NO_ERROR) - { - ALuint envReverb; - alGenEffects(1, &envReverb); - if(getALError() == AL_NO_ERROR) - { - alEffecti(envReverb, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); - if(alGetError() == AL_NO_ERROR) - DPrintf(DMSG_SPAMMY, " EAX Reverb found\n"); - alEffecti(envReverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB); - if(alGetError() == AL_NO_ERROR) - DPrintf(DMSG_SPAMMY, " Standard Reverb found\n"); + LOAD_FUNC(alGenAuxiliaryEffectSlots); + LOAD_FUNC(alDeleteAuxiliaryEffectSlots); + LOAD_FUNC(alIsAuxiliaryEffectSlot); + LOAD_FUNC(alAuxiliaryEffectSloti); + LOAD_FUNC(alAuxiliaryEffectSlotiv); + LOAD_FUNC(alAuxiliaryEffectSlotf); + LOAD_FUNC(alAuxiliaryEffectSlotfv); + LOAD_FUNC(alGetAuxiliaryEffectSloti); + LOAD_FUNC(alGetAuxiliaryEffectSlotiv); + LOAD_FUNC(alGetAuxiliaryEffectSlotf); + LOAD_FUNC(alGetAuxiliaryEffectSlotfv); + if(getALError() == AL_NO_ERROR) + { + ALuint envReverb; + alGenEffects(1, &envReverb); + if(getALError() == AL_NO_ERROR) + { + alEffecti(envReverb, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); + if(alGetError() == AL_NO_ERROR) + DPrintf(DMSG_SPAMMY, " EAX Reverb found\n"); + alEffecti(envReverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB); + if(alGetError() == AL_NO_ERROR) + DPrintf(DMSG_SPAMMY, " Standard Reverb found\n"); - alDeleteEffects(1, &envReverb); - getALError(); - } + alDeleteEffects(1, &envReverb); + getALError(); + } - alGenAuxiliaryEffectSlots(1, &EnvSlot); - alGenFilters(2, EnvFilters); - if(getALError() == AL_NO_ERROR) - { - alFilteri(EnvFilters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS); - alFilteri(EnvFilters[1], AL_FILTER_TYPE, AL_FILTER_LOWPASS); - if(getALError() == AL_NO_ERROR) - DPrintf(DMSG_SPAMMY, " Lowpass found\n"); - else - { - alDeleteFilters(2, EnvFilters); - EnvFilters[0] = EnvFilters[1] = 0; - alDeleteAuxiliaryEffectSlots(1, &EnvSlot); - EnvSlot = 0; - getALError(); - } - } - else - { - alDeleteFilters(2, EnvFilters); - alDeleteAuxiliaryEffectSlots(1, &EnvSlot); - EnvFilters[0] = EnvFilters[1] = 0; - EnvSlot = 0; - getALError(); - } - } - } + alGenAuxiliaryEffectSlots(1, &EnvSlot); + alGenFilters(2, EnvFilters); + if(getALError() == AL_NO_ERROR) + { + alFilteri(EnvFilters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS); + alFilteri(EnvFilters[1], AL_FILTER_TYPE, AL_FILTER_LOWPASS); + if(getALError() == AL_NO_ERROR) + DPrintf(DMSG_SPAMMY, " Lowpass found\n"); + else + { + alDeleteFilters(2, EnvFilters); + EnvFilters[0] = EnvFilters[1] = 0; + alDeleteAuxiliaryEffectSlots(1, &EnvSlot); + EnvSlot = 0; + getALError(); + } + } + else + { + alDeleteFilters(2, EnvFilters); + alDeleteAuxiliaryEffectSlots(1, &EnvSlot); + EnvFilters[0] = EnvFilters[1] = 0; + EnvSlot = 0; + getALError(); + } + } + } - if(EnvSlot) - Printf(" EFX enabled\n"); + if(EnvSlot) + Printf(" EFX enabled\n"); } #undef LOAD_DEV_FUNC #undef LOAD_FUNC OpenALSoundRenderer::~OpenALSoundRenderer() { - if(!Device) - return; + if(!Device) + return; - if(StreamThread.joinable()) - { - std::unique_lock lock(StreamLock); - QuitThread.store(true); - lock.unlock(); - StreamWake.notify_all(); - StreamThread.join(); - } + if(StreamThread.joinable()) + { + std::unique_lock lock(StreamLock); + QuitThread.store(true); + lock.unlock(); + StreamWake.notify_all(); + StreamThread.join(); + } - while(Streams.Size() > 0) - delete Streams[0]; + while(Streams.Size() > 0) + delete Streams[0]; - alDeleteSources(Sources.Size(), &Sources[0]); - Sources.Clear(); - FreeSfx.Clear(); - SfxGroup.Clear(); - PausableSfx.Clear(); - ReverbSfx.Clear(); + alDeleteSources(Sources.Size(), &Sources[0]); + Sources.Clear(); + FreeSfx.Clear(); + SfxGroup.Clear(); + PausableSfx.Clear(); + ReverbSfx.Clear(); - if(EnvEffects.CountUsed() > 0) - { - EffectMapIter iter(EnvEffects); - EffectMap::Pair *pair; - while(iter.NextPair(pair)) - alDeleteEffects(1, &(pair->Value)); - } - EnvEffects.Clear(); + if(EnvEffects.CountUsed() > 0) + { + EffectMapIter iter(EnvEffects); + EffectMap::Pair *pair; + while(iter.NextPair(pair)) + alDeleteEffects(1, &(pair->Value)); + } + EnvEffects.Clear(); - if(EnvSlot) - { - alDeleteAuxiliaryEffectSlots(1, &EnvSlot); - alDeleteFilters(2, EnvFilters); - } - EnvSlot = 0; - EnvFilters[0] = EnvFilters[1] = 0; + if(EnvSlot) + { + alDeleteAuxiliaryEffectSlots(1, &EnvSlot); + alDeleteFilters(2, EnvFilters); + } + EnvSlot = 0; + EnvFilters[0] = EnvFilters[1] = 0; - alcMakeContextCurrent(NULL); - alcDestroyContext(Context); - Context = NULL; - alcCloseDevice(Device); - Device = NULL; + alcMakeContextCurrent(NULL); + alcDestroyContext(Context); + Context = NULL; + alcCloseDevice(Device); + Device = NULL; } void OpenALSoundRenderer::BackgroundProc() { - std::unique_lock lock(StreamLock); - while(!QuitThread.load()) - { - if(Streams.Size() == 0) - { - // If there's nothing to play, wait indefinitely. - StreamWake.wait(lock); - } - else - { - // Else, process all active streams and sleep for 100ms - for(size_t i = 0;i < Streams.Size();i++) - Streams[i]->Process(); - StreamWake.wait_for(lock, std::chrono::milliseconds(100)); - } - } + std::unique_lock lock(StreamLock); + while(!QuitThread.load()) + { + if(Streams.Size() == 0) + { + // If there's nothing to play, wait indefinitely. + StreamWake.wait(lock); + } + else + { + // Else, process all active streams and sleep for 100ms + for(size_t i = 0;i < Streams.Size();i++) + Streams[i]->Process(); + StreamWake.wait_for(lock, std::chrono::milliseconds(100)); + } + } } void OpenALSoundRenderer::AddStream(OpenALSoundStream *stream) { - std::unique_lock lock(StreamLock); - Streams.Push(stream); - lock.unlock(); - // There's a stream to play, make sure the background thread is aware - StreamWake.notify_all(); + std::unique_lock lock(StreamLock); + Streams.Push(stream); + lock.unlock(); + // There's a stream to play, make sure the background thread is aware + StreamWake.notify_all(); } void OpenALSoundRenderer::RemoveStream(OpenALSoundStream *stream) { - std::unique_lock lock(StreamLock); - unsigned int idx = Streams.Find(stream); - if(idx < Streams.Size()) - Streams.Delete(idx); + std::unique_lock lock(StreamLock); + unsigned int idx = Streams.Find(stream); + if(idx < Streams.Size()) + Streams.Delete(idx); } void OpenALSoundRenderer::SetSfxVolume(float volume) { - SfxVolume = volume; + SfxVolume = volume; - FSoundChan *schan = Channels; - while(schan) - { - if(schan->SysChannel != NULL) - { - ALuint source = GET_PTRID(schan->SysChannel); - volume = SfxVolume; + FSoundChan *schan = Channels; + while(schan) + { + if(schan->SysChannel != NULL) + { + ALuint source = GET_PTRID(schan->SysChannel); + volume = SfxVolume; - alDeferUpdatesSOFT(); - alSourcef(source, AL_MAX_GAIN, volume); - alSourcef(source, AL_GAIN, volume * schan->Volume); - } - schan = schan->NextChan; - } + alDeferUpdatesSOFT(); + alSourcef(source, AL_MAX_GAIN, volume); + alSourcef(source, AL_GAIN, volume * schan->Volume); + } + schan = schan->NextChan; + } - alProcessUpdatesSOFT(); + alProcessUpdatesSOFT(); - getALError(); + getALError(); } void OpenALSoundRenderer::SetMusicVolume(float volume) { - MusicVolume = volume; - for(uint32 i = 0;i < Streams.Size();++i) - Streams[i]->UpdateVolume(); + MusicVolume = volume; + for(uint32 i = 0;i < Streams.Size();++i) + Streams[i]->UpdateVolume(); } unsigned int OpenALSoundRenderer::GetMSLength(SoundHandle sfx) { - if(sfx.data) - { - ALuint buffer = GET_PTRID(sfx.data); - if(alIsBuffer(buffer)) - { - ALint bits, channels, freq, size; - alGetBufferi(buffer, AL_BITS, &bits); - alGetBufferi(buffer, AL_CHANNELS, &channels); - alGetBufferi(buffer, AL_FREQUENCY, &freq); - alGetBufferi(buffer, AL_SIZE, &size); - if(getALError() == AL_NO_ERROR) - return (unsigned int)(size / (channels*bits/8) * 1000. / freq); - } - } - return 0; + if(sfx.data) + { + ALuint buffer = GET_PTRID(sfx.data); + if(alIsBuffer(buffer)) + { + ALint bits, channels, freq, size; + alGetBufferi(buffer, AL_BITS, &bits); + alGetBufferi(buffer, AL_CHANNELS, &channels); + alGetBufferi(buffer, AL_FREQUENCY, &freq); + alGetBufferi(buffer, AL_SIZE, &size); + if(getALError() == AL_NO_ERROR) + return (unsigned int)(size / (channels*bits/8) * 1000. / freq); + } + } + return 0; } unsigned int OpenALSoundRenderer::GetSampleLength(SoundHandle sfx) { - if(sfx.data) - { - ALuint buffer = GET_PTRID(sfx.data); - ALint bits, channels, size; - alGetBufferi(buffer, AL_BITS, &bits); - alGetBufferi(buffer, AL_CHANNELS, &channels); - alGetBufferi(buffer, AL_SIZE, &size); - if(getALError() == AL_NO_ERROR) - return (ALsizei)(size / (channels * bits / 8)); - } - return 0; + if(sfx.data) + { + ALuint buffer = GET_PTRID(sfx.data); + ALint bits, channels, size; + alGetBufferi(buffer, AL_BITS, &bits); + alGetBufferi(buffer, AL_CHANNELS, &channels); + alGetBufferi(buffer, AL_SIZE, &size); + if(getALError() == AL_NO_ERROR) + return (ALsizei)(size / (channels * bits / 8)); + } + return 0; } float OpenALSoundRenderer::GetOutputRate() { - ALCint rate = 44100; // Default, just in case - alcGetIntegerv(Device, ALC_FREQUENCY, 1, &rate); - return (float)rate; + ALCint rate = 44100; // Default, just in case + alcGetIntegerv(Device, ALC_FREQUENCY, 1, &rate); + return (float)rate; } std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { - SoundHandle retval = { NULL }; + SoundHandle retval = { NULL }; - if(length == 0) return std::make_pair(retval, true); + if(length == 0) return std::make_pair(retval, true); - if(bits == -8) - { - // Simple signed->unsigned conversion - for(int i = 0;i < length;i++) - sfxdata[i] ^= 0x80; - bits = -bits; - } + if(bits == -8) + { + // Simple signed->unsigned conversion + for(int i = 0;i < length;i++) + sfxdata[i] ^= 0x80; + bits = -bits; + } - if(channels > 1 && monoize) - { - size_t frames = length / channels * 8 / bits; - if(bits == 16) - { - for(size_t i = 0;i < frames;i++) - { - int sum = 0; - for(int c = 0;c < channels;c++) - sum += ((short*)sfxdata)[i*channels + c]; - ((short*)sfxdata)[i] = sum / channels; - } - } - else if(bits == 8) - { - for(size_t i = 0;i < frames;i++) - { - int sum = 0; - for(int c = 0;c < channels;c++) - sum += sfxdata[i*channels + c] - 128; - sfxdata[i] = (sum / channels) + 128; - } - } - length /= channels; - channels = 1; - } + if(channels > 1 && monoize) + { + size_t frames = length / channels * 8 / bits; + if(bits == 16) + { + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(int c = 0;c < channels;c++) + sum += ((short*)sfxdata)[i*channels + c]; + ((short*)sfxdata)[i] = sum / channels; + } + } + else if(bits == 8) + { + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(int c = 0;c < channels;c++) + sum += sfxdata[i*channels + c] - 128; + sfxdata[i] = (sum / channels) + 128; + } + } + length /= channels; + channels = 1; + } - ALenum format = AL_NONE; - if(bits == 16) - { - if(channels == 1) format = AL_FORMAT_MONO16; - if(channels == 2) format = AL_FORMAT_STEREO16; - } - else if(bits == 8) - { - if(channels == 1) format = AL_FORMAT_MONO8; - if(channels == 2) format = AL_FORMAT_STEREO8; - } + ALenum format = AL_NONE; + if(bits == 16) + { + if(channels == 1) format = AL_FORMAT_MONO16; + if(channels == 2) format = AL_FORMAT_STEREO16; + } + else if(bits == 8) + { + if(channels == 1) format = AL_FORMAT_MONO8; + if(channels == 2) format = AL_FORMAT_STEREO8; + } - if(format == AL_NONE || frequency <= 0) - { - Printf("Unhandled format: %d bit, %d channel, %d hz\n", bits, channels, frequency); - return std::make_pair(retval, true); - } - length -= length%(channels*bits/8); + if(format == AL_NONE || frequency <= 0) + { + Printf("Unhandled format: %d bit, %d channel, %d hz\n", bits, channels, frequency); + return std::make_pair(retval, true); + } + length -= length%(channels*bits/8); - ALenum err; - ALuint buffer = 0; - alGenBuffers(1, &buffer); - alBufferData(buffer, format, sfxdata, length, frequency); - if((err=getALError()) != AL_NO_ERROR) - { - Printf("Failed to buffer data: %s\n", alGetString(err)); - alDeleteBuffers(1, &buffer); - getALError(); - return std::make_pair(retval, true); - } + ALenum err; + ALuint buffer = 0; + alGenBuffers(1, &buffer); + alBufferData(buffer, format, sfxdata, length, frequency); + if((err=getALError()) != AL_NO_ERROR) + { + Printf("Failed to buffer data: %s\n", alGetString(err)); + alDeleteBuffers(1, &buffer); + getALError(); + return std::make_pair(retval, true); + } - if((loopstart > 0 || loopend > 0) && AL.SOFT_loop_points) - { - if(loopstart < 0) - loopstart = 0; - if(loopend < loopstart) - loopend = length / (channels*bits/8); + if((loopstart > 0 || loopend > 0) && AL.SOFT_loop_points) + { + if(loopstart < 0) + loopstart = 0; + if(loopend < loopstart) + loopend = length / (channels*bits/8); - ALint loops[2] = { loopstart, loopend }; - DPrintf(DMSG_NOTIFY, "Setting loop points %d -> %d\n", loops[0], loops[1]); - alBufferiv(buffer, AL_LOOP_POINTS_SOFT, loops); - getALError(); - } - else if(loopstart > 0 || loopend > 0) - { - static bool warned = false; - if(!warned) - Printf(DMSG_WARNING, "Loop points not supported!\n"); - warned = true; - } + ALint loops[2] = { loopstart, loopend }; + DPrintf(DMSG_NOTIFY, "Setting loop points %d -> %d\n", loops[0], loops[1]); + alBufferiv(buffer, AL_LOOP_POINTS_SOFT, loops); + getALError(); + } + else if(loopstart > 0 || loopend > 0) + { + static bool warned = false; + if(!warned) + Printf(DMSG_WARNING, "Loop points not supported!\n"); + warned = true; + } - retval.data = MAKE_PTRID(buffer); - return std::make_pair(retval, channels==1); + retval.data = MAKE_PTRID(buffer); + return std::make_pair(retval, channels==1); } std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize) { - SoundHandle retval = { NULL }; - MemoryReader reader((const char*)sfxdata, length); - ALenum format = AL_NONE; - ChannelConfig chans; - SampleType type; - int srate; + SoundHandle retval = { NULL }; + MemoryReader reader((const char*)sfxdata, length); + ALenum format = AL_NONE; + ChannelConfig chans; + SampleType type; + int srate; - std::unique_ptr decoder(CreateDecoder(&reader)); - if(!decoder) return std::make_pair(retval, true); + std::unique_ptr decoder(CreateDecoder(&reader)); + if(!decoder) return std::make_pair(retval, true); - decoder->getInfo(&srate, &chans, &type); - if(chans == ChannelConfig_Mono || monoize) - { - if(type == SampleType_UInt8) format = AL_FORMAT_MONO8; - if(type == SampleType_Int16) format = AL_FORMAT_MONO16; - } - else if(chans == ChannelConfig_Stereo) - { - if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8; - if(type == SampleType_Int16) format = AL_FORMAT_STEREO16; - } + decoder->getInfo(&srate, &chans, &type); + if(chans == ChannelConfig_Mono || monoize) + { + if(type == SampleType_UInt8) format = AL_FORMAT_MONO8; + if(type == SampleType_Int16) format = AL_FORMAT_MONO16; + } + else if(chans == ChannelConfig_Stereo) + { + if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8; + if(type == SampleType_Int16) format = AL_FORMAT_STEREO16; + } - if(format == AL_NONE) - { - Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), - GetSampleTypeName(type)); - return std::make_pair(retval, true); - } + if(format == AL_NONE) + { + Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), + GetSampleTypeName(type)); + return std::make_pair(retval, true); + } - TArray data = decoder->readAll(); - if(chans != ChannelConfig_Mono && monoize) - { - size_t chancount = GetChannelCount(chans); - size_t frames = data.Size() / chancount / - (type == SampleType_Int16 ? 2 : 1); - if(type == SampleType_Int16) - { - short *sfxdata = (short*)&data[0]; - for(size_t i = 0;i < frames;i++) - { - int sum = 0; - for(size_t c = 0;c < chancount;c++) - sum += sfxdata[i*chancount + c]; - sfxdata[i] = short(sum / chancount); - } - } - else if(type == SampleType_UInt8) - { - BYTE *sfxdata = (BYTE*)&data[0]; - for(size_t i = 0;i < frames;i++) - { - int sum = 0; - for(size_t c = 0;c < chancount;c++) - sum += sfxdata[i*chancount + c] - 128; - sfxdata[i] = BYTE((sum / chancount) + 128); - } - } - data.Resize(unsigned(data.Size()/chancount)); - } + TArray data = decoder->readAll(); + if(chans != ChannelConfig_Mono && monoize) + { + size_t chancount = GetChannelCount(chans); + size_t frames = data.Size() / chancount / + (type == SampleType_Int16 ? 2 : 1); + if(type == SampleType_Int16) + { + short *sfxdata = (short*)&data[0]; + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c]; + sfxdata[i] = short(sum / chancount); + } + } + else if(type == SampleType_UInt8) + { + BYTE *sfxdata = (BYTE*)&data[0]; + for(size_t i = 0;i < frames;i++) + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c] - 128; + sfxdata[i] = BYTE((sum / chancount) + 128); + } + } + data.Resize(unsigned(data.Size()/chancount)); + } - ALenum err; - ALuint buffer = 0; - alGenBuffers(1, &buffer); - alBufferData(buffer, format, &data[0], data.Size(), srate); - if((err=getALError()) != AL_NO_ERROR) - { - Printf("Failed to buffer data: %s\n", alGetString(err)); - alDeleteBuffers(1, &buffer); - getALError(); - return std::make_pair(retval, true); - } + ALenum err; + ALuint buffer = 0; + alGenBuffers(1, &buffer); + alBufferData(buffer, format, &data[0], data.Size(), srate); + if((err=getALError()) != AL_NO_ERROR) + { + Printf("Failed to buffer data: %s\n", alGetString(err)); + alDeleteBuffers(1, &buffer); + getALError(); + return std::make_pair(retval, true); + } - retval.data = MAKE_PTRID(buffer); - return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); + retval.data = MAKE_PTRID(buffer); + return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); } void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) { - if(!sfx.data) - return; + if(!sfx.data) + return; - ALuint buffer = GET_PTRID(sfx.data); - FSoundChan *schan = Channels; - while(schan) - { - if(schan->SysChannel) - { - ALint bufID = 0; - alGetSourcei(GET_PTRID(schan->SysChannel), AL_BUFFER, &bufID); - if((ALuint)bufID == buffer) - { - FSoundChan *next = schan->NextChan; - StopChannel(schan); - schan = next; - continue; - } - } - schan = schan->NextChan; - } + ALuint buffer = GET_PTRID(sfx.data); + FSoundChan *schan = Channels; + while(schan) + { + if(schan->SysChannel) + { + ALint bufID = 0; + alGetSourcei(GET_PTRID(schan->SysChannel), AL_BUFFER, &bufID); + if((ALuint)bufID == buffer) + { + FSoundChan *next = schan->NextChan; + StopChannel(schan); + schan = next; + continue; + } + } + schan = schan->NextChan; + } - alDeleteBuffers(1, &buffer); - getALError(); + alDeleteBuffers(1, &buffer); + getALError(); } SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) { - if(StreamThread.get_id() == std::thread::id()) - StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); + if(StreamThread.get_id() == std::thread::id()) + StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); OpenALSoundStream *stream = new OpenALSoundStream(this); if (!stream->Init(callback, buffbytes, flags, samplerate, userdata)) { @@ -1313,8 +1317,8 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags) { - if(StreamThread.get_id() == std::thread::id()) - StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); + if(StreamThread.get_id() == std::thread::id()) + StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); OpenALSoundStream *stream = new OpenALSoundStream(this); if (!stream->Init(reader, !!(flags&SoundStream::Loop))) { @@ -1326,875 +1330,875 @@ SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags) FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) { - if(FreeSfx.Size() == 0) - { - FSoundChan *lowest = FindLowestChannel(); - if(lowest) StopChannel(lowest); + if(FreeSfx.Size() == 0) + { + FSoundChan *lowest = FindLowestChannel(); + if(lowest) StopChannel(lowest); - if(FreeSfx.Size() == 0) - return NULL; - } + if(FreeSfx.Size() == 0) + return NULL; + } - ALuint buffer = GET_PTRID(sfx.data); - ALuint source = FreeSfx.Last(); - alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); - alSource3f(source, AL_VELOCITY, 0.f, 0.f, 0.f); - alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + ALuint buffer = GET_PTRID(sfx.data); + ALuint source = FreeSfx.Last(); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + alSource3f(source, AL_VELOCITY, 0.f, 0.f, 0.f); + alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); + alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); - alSourcef(source, AL_REFERENCE_DISTANCE, 1.f); - alSourcef(source, AL_MAX_DISTANCE, 1000.f); - alSourcef(source, AL_ROLLOFF_FACTOR, 0.f); - alSourcef(source, AL_MAX_GAIN, SfxVolume); - alSourcef(source, AL_GAIN, SfxVolume*vol); - if(AL.EXT_SOURCE_RADIUS) - alSourcef(source, AL_SOURCE_RADIUS, 0.f); + alSourcef(source, AL_REFERENCE_DISTANCE, 1.f); + alSourcef(source, AL_MAX_DISTANCE, 1000.f); + alSourcef(source, AL_ROLLOFF_FACTOR, 0.f); + alSourcef(source, AL_MAX_GAIN, SfxVolume); + alSourcef(source, AL_GAIN, SfxVolume*vol); + if(AL.EXT_SOURCE_RADIUS) + alSourcef(source, AL_SOURCE_RADIUS, 0.f); - if(EnvSlot) - { - if(!(chanflags&SNDF_NOREVERB)) - { - alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); - alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); - } - else - { - alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL); - alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); - } - alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); - } - if(WasInWater && !(chanflags&SNDF_NOREVERB)) - alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); - else - alSourcef(source, AL_PITCH, PITCH(pitch)); + if(EnvSlot) + { + if(!(chanflags&SNDF_NOREVERB)) + { + alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); + alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); + } + else + { + alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL); + alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); + } + alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); + } + if(WasInWater && !(chanflags&SNDF_NOREVERB)) + alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); + else + alSourcef(source, AL_PITCH, PITCH(pitch)); - if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) - alSourcef(source, AL_SEC_OFFSET, 0.f); - else - { - if((chanflags&SNDF_ABSTIME)) - alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); - else - { - float offset = std::chrono::duration_cast>( - std::chrono::steady_clock::now().time_since_epoch() - - std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) - ).count(); - if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); - } - } - if(getALError() != AL_NO_ERROR) - return NULL; + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) + alSourcef(source, AL_SEC_OFFSET, 0.f); + else + { + if((chanflags&SNDF_ABSTIME)) + alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); + else + { + float offset = std::chrono::duration_cast>( + std::chrono::steady_clock::now().time_since_epoch() - + std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) + ).count(); + if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); + } + } + if(getALError() != AL_NO_ERROR) + return NULL; - alSourcei(source, AL_BUFFER, buffer); - if((chanflags&SNDF_NOPAUSE) || !SFXPaused) - alSourcePlay(source); - if(getALError() != AL_NO_ERROR) - { - alSourcei(source, AL_BUFFER, 0); - getALError(); - return NULL; - } + alSourcei(source, AL_BUFFER, buffer); + if((chanflags&SNDF_NOPAUSE) || !SFXPaused) + alSourcePlay(source); + if(getALError() != AL_NO_ERROR) + { + alSourcei(source, AL_BUFFER, 0); + getALError(); + return NULL; + } - if(!(chanflags&SNDF_NOREVERB)) - ReverbSfx.Push(source); - if(!(chanflags&SNDF_NOPAUSE)) - PausableSfx.Push(source); - SfxGroup.Push(source); - FreeSfx.Pop(); + if(!(chanflags&SNDF_NOREVERB)) + ReverbSfx.Push(source); + if(!(chanflags&SNDF_NOPAUSE)) + PausableSfx.Push(source); + SfxGroup.Push(source); + FreeSfx.Pop(); - FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); - else chan->SysChannel = MAKE_PTRID(source); + FISoundChannel *chan = reuse_chan; + if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + else chan->SysChannel = MAKE_PTRID(source); - chan->Rolloff.RolloffType = ROLLOFF_Log; - chan->Rolloff.RolloffFactor = 0.f; - chan->Rolloff.MinDistance = 1.f; - chan->DistanceSqr = 0.f; - chan->ManualRolloff = false; + chan->Rolloff.RolloffType = ROLLOFF_Log; + chan->Rolloff.RolloffFactor = 0.f; + chan->Rolloff.MinDistance = 1.f; + chan->DistanceSqr = 0.f; + chan->ManualRolloff = false; - return chan; + return chan; } FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, - FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, - int channum, int chanflags, FISoundChannel *reuse_chan) + FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, + int channum, int chanflags, FISoundChannel *reuse_chan) { - float dist_sqr = (float)(pos - listener->position).LengthSquared(); + float dist_sqr = (float)(pos - listener->position).LengthSquared(); - if(FreeSfx.Size() == 0) - { - FSoundChan *lowest = FindLowestChannel(); - if(lowest) - { - if(lowest->Priority < priority || (lowest->Priority == priority && - lowest->DistanceSqr > dist_sqr)) - StopChannel(lowest); - } - if(FreeSfx.Size() == 0) - return NULL; - } + if(FreeSfx.Size() == 0) + { + FSoundChan *lowest = FindLowestChannel(); + if(lowest) + { + if(lowest->Priority < priority || (lowest->Priority == priority && + lowest->DistanceSqr > dist_sqr)) + StopChannel(lowest); + } + if(FreeSfx.Size() == 0) + return NULL; + } - bool manualRolloff = true; - ALuint buffer = GET_PTRID(sfx.data); - ALuint source = FreeSfx.Last(); - if(rolloff->RolloffType == ROLLOFF_Log) - { - if(AL.EXT_source_distance_model) - alSourcei(source, AL_DISTANCE_MODEL, AL_INVERSE_DISTANCE); - alSourcef(source, AL_REFERENCE_DISTANCE, rolloff->MinDistance/distscale); - alSourcef(source, AL_MAX_DISTANCE, (1000.f+rolloff->MinDistance)/distscale); - alSourcef(source, AL_ROLLOFF_FACTOR, rolloff->RolloffFactor); - manualRolloff = false; - } - else if(rolloff->RolloffType == ROLLOFF_Linear && AL.EXT_source_distance_model) - { - alSourcei(source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE); - alSourcef(source, AL_REFERENCE_DISTANCE, rolloff->MinDistance/distscale); - alSourcef(source, AL_MAX_DISTANCE, rolloff->MaxDistance/distscale); - alSourcef(source, AL_ROLLOFF_FACTOR, 1.f); - manualRolloff = false; - } - if(manualRolloff) - { - // How manual rolloff works: - // - // If a sound is using Custom or Doom style rolloff, or Linear style - // when AL_EXT_source_distance_model is not supported, we have to play - // around a bit to get appropriate distance attenation. What we do is - // calculate the attenuation that should be applied, then given an - // Inverse Distance rolloff model with OpenAL, reverse the calculation - // to get the distance needed for that much attenuation. The Inverse - // Distance calculation is: - // - // Gain = MinDist / (MinDist + RolloffFactor*(Distance - MinDist)) - // - // Thus, the reverse is: - // - // Distance = (MinDist/Gain - MinDist)/RolloffFactor + MinDist - // - // This can be simplified by using a MinDist and RolloffFactor of 1, - // which makes it: - // - // Distance = 1.0f/Gain; - // - // The source position is then set that many units away from the - // listener position, and OpenAL takes care of the rest. - if(AL.EXT_source_distance_model) - alSourcei(source, AL_DISTANCE_MODEL, AL_INVERSE_DISTANCE); - alSourcef(source, AL_REFERENCE_DISTANCE, 1.f); - alSourcef(source, AL_MAX_DISTANCE, 100000.f); - alSourcef(source, AL_ROLLOFF_FACTOR, 1.f); + bool manualRolloff = true; + ALuint buffer = GET_PTRID(sfx.data); + ALuint source = FreeSfx.Last(); + if(rolloff->RolloffType == ROLLOFF_Log) + { + if(AL.EXT_source_distance_model) + alSourcei(source, AL_DISTANCE_MODEL, AL_INVERSE_DISTANCE); + alSourcef(source, AL_REFERENCE_DISTANCE, rolloff->MinDistance/distscale); + alSourcef(source, AL_MAX_DISTANCE, (1000.f+rolloff->MinDistance)/distscale); + alSourcef(source, AL_ROLLOFF_FACTOR, rolloff->RolloffFactor); + manualRolloff = false; + } + else if(rolloff->RolloffType == ROLLOFF_Linear && AL.EXT_source_distance_model) + { + alSourcei(source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE); + alSourcef(source, AL_REFERENCE_DISTANCE, rolloff->MinDistance/distscale); + alSourcef(source, AL_MAX_DISTANCE, rolloff->MaxDistance/distscale); + alSourcef(source, AL_ROLLOFF_FACTOR, 1.f); + manualRolloff = false; + } + if(manualRolloff) + { + // How manual rolloff works: + // + // If a sound is using Custom or Doom style rolloff, or Linear style + // when AL_EXT_source_distance_model is not supported, we have to play + // around a bit to get appropriate distance attenation. What we do is + // calculate the attenuation that should be applied, then given an + // Inverse Distance rolloff model with OpenAL, reverse the calculation + // to get the distance needed for that much attenuation. The Inverse + // Distance calculation is: + // + // Gain = MinDist / (MinDist + RolloffFactor*(Distance - MinDist)) + // + // Thus, the reverse is: + // + // Distance = (MinDist/Gain - MinDist)/RolloffFactor + MinDist + // + // This can be simplified by using a MinDist and RolloffFactor of 1, + // which makes it: + // + // Distance = 1.0f/Gain; + // + // The source position is then set that many units away from the + // listener position, and OpenAL takes care of the rest. + if(AL.EXT_source_distance_model) + alSourcei(source, AL_DISTANCE_MODEL, AL_INVERSE_DISTANCE); + alSourcef(source, AL_REFERENCE_DISTANCE, 1.f); + alSourcef(source, AL_MAX_DISTANCE, 100000.f); + alSourcef(source, AL_ROLLOFF_FACTOR, 1.f); - FVector3 dir = pos - listener->position; - if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) - { - float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale); - dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); - } - if(AL.EXT_SOURCE_RADIUS) - { - /* Since the OpenAL distance is decoupled from the sound's distance, get the OpenAL - * distance that corresponds to the area radius. */ - alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? - // Clamp in case the max distance is <= the area radius - 1.f/MAX(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f - ); - } - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { - FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); - float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; - } - dir += listener->position; + FVector3 dir = pos - listener->position; + if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) + { + float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale); + dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); + } + if(AL.EXT_SOURCE_RADIUS) + { + /* Since the OpenAL distance is decoupled from the sound's distance, get the OpenAL + * distance that corresponds to the area radius. */ + alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? + // Clamp in case the max distance is <= the area radius + 1.f/MAX(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f + ); + } + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { + FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); + float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; + } + dir += listener->position; - if(dist_sqr < (0.0004f*0.0004f)) - { - // Head relative - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); - } - else - { - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } - } - else - { - FVector3 dir = pos; - if(AL.EXT_SOURCE_RADIUS) - alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f); - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { - dir -= listener->position; + if(dist_sqr < (0.0004f*0.0004f)) + { + // Head relative + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } + } + else + { + FVector3 dir = pos; + if(AL.EXT_SOURCE_RADIUS) + alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f); + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { + dir -= listener->position; + + float mindist = rolloff->MinDistance/distscale; + FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); + float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; + + dir += listener->position; + } + if(dist_sqr < (0.0004f*0.0004f)) + { + // Head relative + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } + } + alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); + alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); - float mindist = rolloff->MinDistance/distscale; - FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); - float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; + alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); - dir += listener->position; - } - if(dist_sqr < (0.0004f*0.0004f)) - { - // Head relative - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); - } - else - { - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } - } - alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); - alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); + alSourcef(source, AL_MAX_GAIN, SfxVolume); + alSourcef(source, AL_GAIN, SfxVolume*vol); - alSourcei(source, AL_LOOPING, (chanflags&SNDF_LOOP) ? AL_TRUE : AL_FALSE); + if(EnvSlot) + { + if(!(chanflags&SNDF_NOREVERB)) + { + alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); + alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); + } + else + { + alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL); + alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); + } + alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); + } + if(WasInWater && !(chanflags&SNDF_NOREVERB)) + alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); + else + alSourcef(source, AL_PITCH, PITCH(pitch)); - alSourcef(source, AL_MAX_GAIN, SfxVolume); - alSourcef(source, AL_GAIN, SfxVolume*vol); + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) + alSourcef(source, AL_SEC_OFFSET, 0.f); + else + { + if((chanflags&SNDF_ABSTIME)) + alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); + else + { + float offset = std::chrono::duration_cast>( + std::chrono::steady_clock::now().time_since_epoch() - + std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) + ).count(); + if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); + } + } + if(getALError() != AL_NO_ERROR) + return NULL; - if(EnvSlot) - { - if(!(chanflags&SNDF_NOREVERB)) - { - alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); - alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); - } - else - { - alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL); - alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); - } - alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); - } - if(WasInWater && !(chanflags&SNDF_NOREVERB)) - alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); - else - alSourcef(source, AL_PITCH, PITCH(pitch)); + alSourcei(source, AL_BUFFER, buffer); + if((chanflags&SNDF_NOPAUSE) || !SFXPaused) + alSourcePlay(source); + if(getALError() != AL_NO_ERROR) + { + alSourcei(source, AL_BUFFER, 0); + getALError(); + return NULL; + } - if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) - alSourcef(source, AL_SEC_OFFSET, 0.f); - else - { - if((chanflags&SNDF_ABSTIME)) - alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); - else - { - float offset = std::chrono::duration_cast>( - std::chrono::steady_clock::now().time_since_epoch() - - std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) - ).count(); - if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); - } - } - if(getALError() != AL_NO_ERROR) - return NULL; + if(!(chanflags&SNDF_NOREVERB)) + ReverbSfx.Push(source); + if(!(chanflags&SNDF_NOPAUSE)) + PausableSfx.Push(source); + SfxGroup.Push(source); + FreeSfx.Pop(); - alSourcei(source, AL_BUFFER, buffer); - if((chanflags&SNDF_NOPAUSE) || !SFXPaused) - alSourcePlay(source); - if(getALError() != AL_NO_ERROR) - { - alSourcei(source, AL_BUFFER, 0); - getALError(); - return NULL; - } + FISoundChannel *chan = reuse_chan; + if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + else chan->SysChannel = MAKE_PTRID(source); - if(!(chanflags&SNDF_NOREVERB)) - ReverbSfx.Push(source); - if(!(chanflags&SNDF_NOPAUSE)) - PausableSfx.Push(source); - SfxGroup.Push(source); - FreeSfx.Pop(); + chan->Rolloff = *rolloff; + chan->DistanceSqr = dist_sqr; + chan->ManualRolloff = manualRolloff; - FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); - else chan->SysChannel = MAKE_PTRID(source); - - chan->Rolloff = *rolloff; - chan->DistanceSqr = dist_sqr; - chan->ManualRolloff = manualRolloff; - - return chan; + return chan; } void OpenALSoundRenderer::ChannelVolume(FISoundChannel *chan, float volume) { - if(chan == NULL || chan->SysChannel == NULL) - return; + if(chan == NULL || chan->SysChannel == NULL) + return; - alDeferUpdatesSOFT(); + alDeferUpdatesSOFT(); - ALuint source = GET_PTRID(chan->SysChannel); - alSourcef(source, AL_GAIN, SfxVolume * volume); + ALuint source = GET_PTRID(chan->SysChannel); + alSourcef(source, AL_GAIN, SfxVolume * volume); } void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) { - if(chan == NULL || chan->SysChannel == NULL) - return; + if(chan == NULL || chan->SysChannel == NULL) + return; - ALuint source = GET_PTRID(chan->SysChannel); - // Release first, so it can be properly marked as evicted if it's being - // forcefully killed - S_ChannelEnded(chan); + ALuint source = GET_PTRID(chan->SysChannel); + // Release first, so it can be properly marked as evicted if it's being + // forcefully killed + S_ChannelEnded(chan); - alSourceRewind(source); - alSourcei(source, AL_BUFFER, 0); - getALError(); + alSourceRewind(source); + alSourcei(source, AL_BUFFER, 0); + getALError(); - uint32 i; - if((i=PausableSfx.Find(source)) < PausableSfx.Size()) - PausableSfx.Delete(i); - if((i=ReverbSfx.Find(source)) < ReverbSfx.Size()) - ReverbSfx.Delete(i); + uint32 i; + if((i=PausableSfx.Find(source)) < PausableSfx.Size()) + PausableSfx.Delete(i); + if((i=ReverbSfx.Find(source)) < ReverbSfx.Size()) + ReverbSfx.Delete(i); - SfxGroup.Delete(SfxGroup.Find(source)); - FreeSfx.Push(source); + SfxGroup.Delete(SfxGroup.Find(source)); + FreeSfx.Push(source); } unsigned int OpenALSoundRenderer::GetPosition(FISoundChannel *chan) { - if(chan == NULL || chan->SysChannel == NULL) - return 0; + if(chan == NULL || chan->SysChannel == NULL) + return 0; - ALint pos; - alGetSourcei(GET_PTRID(chan->SysChannel), AL_SAMPLE_OFFSET, &pos); - if(getALError() == AL_NO_ERROR) - return pos; - return 0; + ALint pos; + alGetSourcei(GET_PTRID(chan->SysChannel), AL_SAMPLE_OFFSET, &pos); + if(getALError() == AL_NO_ERROR) + return pos; + return 0; } void OpenALSoundRenderer::SetSfxPaused(bool paused, int slot) { - int oldslots = SFXPaused; + int oldslots = SFXPaused; - if(paused) - { - SFXPaused |= 1 << slot; - if(oldslots == 0 && PausableSfx.Size() > 0) - { - alSourcePausev(PausableSfx.Size(), &PausableSfx[0]); - getALError(); - PurgeStoppedSources(); - } - } - else - { - SFXPaused &= ~(1 << slot); - if(SFXPaused == 0 && oldslots != 0 && PausableSfx.Size() > 0) - { - alSourcePlayv(PausableSfx.Size(), &PausableSfx[0]); - getALError(); - } - } + if(paused) + { + SFXPaused |= 1 << slot; + if(oldslots == 0 && PausableSfx.Size() > 0) + { + alSourcePausev(PausableSfx.Size(), &PausableSfx[0]); + getALError(); + PurgeStoppedSources(); + } + } + else + { + SFXPaused &= ~(1 << slot); + if(SFXPaused == 0 && oldslots != 0 && PausableSfx.Size() > 0) + { + alSourcePlayv(PausableSfx.Size(), &PausableSfx[0]); + getALError(); + } + } } void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state) { - switch(state) - { - case SoundRenderer::INACTIVE_Active: - alListenerf(AL_GAIN, 1.0f); - if(ALC.SOFT_pause_device) - { - alcDeviceResumeSOFT(Device); - getALCError(Device); - } - break; + switch(state) + { + case SoundRenderer::INACTIVE_Active: + alListenerf(AL_GAIN, 1.0f); + if(ALC.SOFT_pause_device) + { + alcDeviceResumeSOFT(Device); + getALCError(Device); + } + break; - case SoundRenderer::INACTIVE_Complete: - if(ALC.SOFT_pause_device) - { - alcDevicePauseSOFT(Device); - getALCError(Device); - } - /* fall-through */ - case SoundRenderer::INACTIVE_Mute: - alListenerf(AL_GAIN, 0.0f); - break; - } + case SoundRenderer::INACTIVE_Complete: + if(ALC.SOFT_pause_device) + { + alcDevicePauseSOFT(Device); + getALCError(Device); + } + /* fall-through */ + case SoundRenderer::INACTIVE_Mute: + alListenerf(AL_GAIN, 0.0f); + break; + } } void OpenALSoundRenderer::Sync(bool sync) { - if(sync) - { - if(SfxGroup.Size() > 0) - { - alSourcePausev(SfxGroup.Size(), &SfxGroup[0]); - getALError(); - PurgeStoppedSources(); - } - } - else - { - // Might already be something to handle this; basically, get a vector - // of all values in SfxGroup that are not also in PausableSfx (when - // SFXPaused is non-0). - TArray toplay = SfxGroup; - if(SFXPaused) - { - uint32 i = 0; - while(i < toplay.Size()) - { - uint32 p = PausableSfx.Find(toplay[i]); - if(p < PausableSfx.Size()) - toplay.Delete(i); - else - i++; - } - } - if(toplay.Size() > 0) - { - alSourcePlayv(toplay.Size(), &toplay[0]); - getALError(); - } - } + if(sync) + { + if(SfxGroup.Size() > 0) + { + alSourcePausev(SfxGroup.Size(), &SfxGroup[0]); + getALError(); + PurgeStoppedSources(); + } + } + else + { + // Might already be something to handle this; basically, get a vector + // of all values in SfxGroup that are not also in PausableSfx (when + // SFXPaused is non-0). + TArray toplay = SfxGroup; + if(SFXPaused) + { + uint32 i = 0; + while(i < toplay.Size()) + { + uint32 p = PausableSfx.Find(toplay[i]); + if(p < PausableSfx.Size()) + toplay.Delete(i); + else + i++; + } + } + if(toplay.Size() > 0) + { + alSourcePlayv(toplay.Size(), &toplay[0]); + getALError(); + } + } } void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundChannel *chan, bool areasound, const FVector3 &pos, const FVector3 &vel) { - if(chan == NULL || chan->SysChannel == NULL) - return; + if(chan == NULL || chan->SysChannel == NULL) + return; - FVector3 dir = pos - listener->position; - chan->DistanceSqr = (float)dir.LengthSquared(); + FVector3 dir = pos - listener->position; + chan->DistanceSqr = (float)dir.LengthSquared(); - if(chan->ManualRolloff) - { - if(!AL.EXT_SOURCE_RADIUS && areasound && - chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { - FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); - float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; - } - if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) - { - float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale); - dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); - } - } - else if(!AL.EXT_SOURCE_RADIUS && areasound && - chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { - float mindist = chan->Rolloff.MinDistance / chan->DistanceScale; - FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); - float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; - } - dir += listener->position; + if(chan->ManualRolloff) + { + if(!AL.EXT_SOURCE_RADIUS && areasound && + chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { + FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); + float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; + } + if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) + { + float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale); + dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); + } + } + else if(!AL.EXT_SOURCE_RADIUS && areasound && + chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { + float mindist = chan->Rolloff.MinDistance / chan->DistanceScale; + FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); + float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; + } + dir += listener->position; - alDeferUpdatesSOFT(); - ALuint source = GET_PTRID(chan->SysChannel); + alDeferUpdatesSOFT(); + ALuint source = GET_PTRID(chan->SysChannel); - if(chan->DistanceSqr < (0.0004f*0.0004f)) - { - alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); - } - else - { - alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } - alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); - getALError(); + if(chan->DistanceSqr < (0.0004f*0.0004f)) + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source, AL_POSITION, 0.f, 0.f, 0.f); + } + else + { + alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } + alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); + getALError(); } void OpenALSoundRenderer::UpdateListener(SoundListener *listener) { - if(!listener->valid) - return; + if(!listener->valid) + return; - alDeferUpdatesSOFT(); + alDeferUpdatesSOFT(); - float angle = listener->angle; - ALfloat orient[6]; - // forward - orient[0] = cosf(angle); - orient[1] = 0.f; - orient[2] = -sinf(angle); - // up - orient[3] = 0.f; - orient[4] = 1.f; - orient[5] = 0.f; + float angle = listener->angle; + ALfloat orient[6]; + // forward + orient[0] = cosf(angle); + orient[1] = 0.f; + orient[2] = -sinf(angle); + // up + orient[3] = 0.f; + orient[4] = 1.f; + orient[5] = 0.f; - alListenerfv(AL_ORIENTATION, orient); - alListener3f(AL_POSITION, listener->position.X, - listener->position.Y, - -listener->position.Z); - alListener3f(AL_VELOCITY, listener->velocity.X, - listener->velocity.Y, - -listener->velocity.Z); - getALError(); + alListenerfv(AL_ORIENTATION, orient); + alListener3f(AL_POSITION, listener->position.X, + listener->position.Y, + -listener->position.Z); + alListener3f(AL_VELOCITY, listener->velocity.X, + listener->velocity.Y, + -listener->velocity.Z); + getALError(); - const ReverbContainer *env = ForcedEnvironment; - if(!env) - { - env = listener->Environment; - if(!env) - env = DefaultEnvironments[0]; - } - if(env != PrevEnvironment || env->Modified) - { - PrevEnvironment = env; - DPrintf(DMSG_NOTIFY, "Reverb Environment %s\n", env->Name); + const ReverbContainer *env = ForcedEnvironment; + if(!env) + { + env = listener->Environment; + if(!env) + env = DefaultEnvironments[0]; + } + if(env != PrevEnvironment || env->Modified) + { + PrevEnvironment = env; + DPrintf(DMSG_NOTIFY, "Reverb Environment %s\n", env->Name); - if(EnvSlot != 0) - LoadReverb(env); + if(EnvSlot != 0) + LoadReverb(env); - const_cast(env)->Modified = false; - } + const_cast(env)->Modified = false; + } - // NOTE: Moving into and out of water will undo pitch variations on sounds. - if(listener->underwater || env->SoftwareWater) - { - if(!WasInWater) - { - WasInWater = true; + // NOTE: Moving into and out of water will undo pitch variations on sounds. + if(listener->underwater || env->SoftwareWater) + { + if(!WasInWater) + { + WasInWater = true; - if(EnvSlot != 0 && *snd_waterreverb) - { - // Find the "Underwater" reverb environment - env = S_FindEnvironment(0x1600); - LoadReverb(env ? env : DefaultEnvironments[0]); + if(EnvSlot != 0 && *snd_waterreverb) + { + // Find the "Underwater" reverb environment + env = S_FindEnvironment(0x1600); + LoadReverb(env ? env : DefaultEnvironments[0]); - alFilterf(EnvFilters[0], AL_LOWPASS_GAIN, 1.f); - alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 0.125f); - alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); - alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); + alFilterf(EnvFilters[0], AL_LOWPASS_GAIN, 1.f); + alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 0.125f); + alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); + alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); - // Apply the updated filters on the sources - for(uint32 i = 0;i < ReverbSfx.Size();++i) - { - alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); - alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); - } - } + // Apply the updated filters on the sources + for(uint32 i = 0;i < ReverbSfx.Size();++i) + { + alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); + alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); + } + } - for(uint32 i = 0;i < ReverbSfx.Size();++i) - alSourcef(ReverbSfx[i], AL_PITCH, PITCH_MULT); - getALError(); - } - } - else if(WasInWater) - { - WasInWater = false; + for(uint32 i = 0;i < ReverbSfx.Size();++i) + alSourcef(ReverbSfx[i], AL_PITCH, PITCH_MULT); + getALError(); + } + } + else if(WasInWater) + { + WasInWater = false; - if(EnvSlot != 0) - { - LoadReverb(env); + if(EnvSlot != 0) + { + LoadReverb(env); - alFilterf(EnvFilters[0], AL_LOWPASS_GAIN, 1.f); - alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 1.f); - alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); - alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); - for(uint32 i = 0;i < ReverbSfx.Size();++i) - { - alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); - alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); - } - } + alFilterf(EnvFilters[0], AL_LOWPASS_GAIN, 1.f); + alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 1.f); + alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); + alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); + for(uint32 i = 0;i < ReverbSfx.Size();++i) + { + alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); + alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); + } + } - for(uint32 i = 0;i < ReverbSfx.Size();++i) - alSourcef(ReverbSfx[i], AL_PITCH, 1.f); - getALError(); - } + for(uint32 i = 0;i < ReverbSfx.Size();++i) + alSourcef(ReverbSfx[i], AL_PITCH, 1.f); + getALError(); + } } void OpenALSoundRenderer::UpdateSounds() { - alProcessUpdatesSOFT(); + alProcessUpdatesSOFT(); - if(ALC.EXT_disconnect) - { - ALCint connected = ALC_TRUE; - alcGetIntegerv(Device, ALC_CONNECTED, 1, &connected); - if(connected == ALC_FALSE) - { - Printf("Sound device disconnected; restarting...\n"); - static char snd_reset[] = "snd_reset"; - AddCommandString(snd_reset); - return; - } - } + if(ALC.EXT_disconnect) + { + ALCint connected = ALC_TRUE; + alcGetIntegerv(Device, ALC_CONNECTED, 1, &connected); + if(connected == ALC_FALSE) + { + Printf("Sound device disconnected; restarting...\n"); + static char snd_reset[] = "snd_reset"; + AddCommandString(snd_reset); + return; + } + } - PurgeStoppedSources(); + PurgeStoppedSources(); } bool OpenALSoundRenderer::IsValid() { - return Device != NULL; + return Device != NULL; } void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan) { - // FIXME: Get current time (preferably from the audio clock, but the system - // time will have to do) - chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count(); + // FIXME: Get current time (preferably from the audio clock, but the system + // time will have to do) + chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count(); } float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) { - if(chan == NULL || chan->SysChannel == NULL) - return 0.f; + if(chan == NULL || chan->SysChannel == NULL) + return 0.f; - ALuint source = GET_PTRID(chan->SysChannel); - ALfloat volume = 0.f; + ALuint source = GET_PTRID(chan->SysChannel); + ALfloat volume = 0.f; - alGetSourcef(source, AL_GAIN, &volume); - getALError(); + alGetSourcef(source, AL_GAIN, &volume); + getALError(); - volume *= GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale); - return volume; + volume *= GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale); + return volume; } void OpenALSoundRenderer::PrintStatus() { - Printf("Output device: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_DEVICE_SPECIFIER)); - getALCError(Device); + Printf("Output device: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_DEVICE_SPECIFIER)); + getALCError(Device); - ALCint frequency, major, minor, mono, stereo; - alcGetIntegerv(Device, ALC_FREQUENCY, 1, &frequency); - alcGetIntegerv(Device, ALC_MAJOR_VERSION, 1, &major); - alcGetIntegerv(Device, ALC_MINOR_VERSION, 1, &minor); - alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &mono); - alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &stereo); - if(getALCError(Device) == AL_NO_ERROR) - { - Printf("Device sample rate: " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL"hz\n", frequency); - Printf("ALC Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); - Printf("ALC Extensions: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_EXTENSIONS)); - Printf("Available sources: " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" (" TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" mono, " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" stereo)\n", mono+stereo, mono, stereo); - } - if(!alcIsExtensionPresent(Device, "ALC_EXT_EFX")) - Printf("EFX not found\n"); - else - { - ALCint sends; - alcGetIntegerv(Device, ALC_EFX_MAJOR_VERSION, 1, &major); - alcGetIntegerv(Device, ALC_EFX_MINOR_VERSION, 1, &minor); - alcGetIntegerv(Device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); - if(getALCError(Device) == AL_NO_ERROR) - { - Printf("EFX Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); - Printf("Auxiliary sends: " TEXTCOLOR_BLUE"%d\n", sends); - } - } - Printf("Vendor: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VENDOR)); - Printf("Renderer: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_RENDERER)); - Printf("Version: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VERSION)); - Printf("Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS)); - getALError(); + ALCint frequency, major, minor, mono, stereo; + alcGetIntegerv(Device, ALC_FREQUENCY, 1, &frequency); + alcGetIntegerv(Device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(Device, ALC_MINOR_VERSION, 1, &minor); + alcGetIntegerv(Device, ALC_MONO_SOURCES, 1, &mono); + alcGetIntegerv(Device, ALC_STEREO_SOURCES, 1, &stereo); + if(getALCError(Device) == AL_NO_ERROR) + { + Printf("Device sample rate: " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL"hz\n", frequency); + Printf("ALC Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); + Printf("ALC Extensions: " TEXTCOLOR_ORANGE"%s\n", alcGetString(Device, ALC_EXTENSIONS)); + Printf("Available sources: " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" (" TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" mono, " TEXTCOLOR_BLUE"%d" TEXTCOLOR_NORMAL" stereo)\n", mono+stereo, mono, stereo); + } + if(!alcIsExtensionPresent(Device, "ALC_EXT_EFX")) + Printf("EFX not found\n"); + else + { + ALCint sends; + alcGetIntegerv(Device, ALC_EFX_MAJOR_VERSION, 1, &major); + alcGetIntegerv(Device, ALC_EFX_MINOR_VERSION, 1, &minor); + alcGetIntegerv(Device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); + if(getALCError(Device) == AL_NO_ERROR) + { + Printf("EFX Version: " TEXTCOLOR_BLUE"%d.%d\n", major, minor); + Printf("Auxiliary sends: " TEXTCOLOR_BLUE"%d\n", sends); + } + } + Printf("Vendor: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VENDOR)); + Printf("Renderer: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_RENDERER)); + Printf("Version: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_VERSION)); + Printf("Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS)); + getALError(); } FString OpenALSoundRenderer::GatherStats() { - ALCint updates = 1; - alcGetIntegerv(Device, ALC_REFRESH, 1, &updates); - getALCError(Device); + ALCint updates = 1; + alcGetIntegerv(Device, ALC_REFRESH, 1, &updates); + getALCError(Device); - uint32 total = Sources.Size(); - uint32 used = SfxGroup.Size()+Streams.Size(); - uint32 unused = FreeSfx.Size(); + uint32 total = Sources.Size(); + uint32 used = SfxGroup.Size()+Streams.Size(); + uint32 unused = FreeSfx.Size(); - FString out; - out.Format("%u sources (" TEXTCOLOR_YELLOW"%u" TEXTCOLOR_NORMAL" active, " TEXTCOLOR_YELLOW"%u" TEXTCOLOR_NORMAL" free), Update interval: " TEXTCOLOR_YELLOW"%d" TEXTCOLOR_NORMAL"ms", - total, used, unused, 1000/updates); - return out; + FString out; + out.Format("%u sources (" TEXTCOLOR_YELLOW"%u" TEXTCOLOR_NORMAL" active, " TEXTCOLOR_YELLOW"%u" TEXTCOLOR_NORMAL" free), Update interval: " TEXTCOLOR_YELLOW"%d" TEXTCOLOR_NORMAL"ms", + total, used, unused, 1000/updates); + return out; } void OpenALSoundRenderer::PrintDriversList() { - const ALCchar *drivers = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? - alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : - alcGetString(NULL, ALC_DEVICE_SPECIFIER)); - if(drivers == NULL) - { - Printf(TEXTCOLOR_YELLOW"Failed to retrieve device list: %s\n", alcGetString(NULL, alcGetError(NULL))); - return; - } + const ALCchar *drivers = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? + alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : + alcGetString(NULL, ALC_DEVICE_SPECIFIER)); + if(drivers == NULL) + { + Printf(TEXTCOLOR_YELLOW"Failed to retrieve device list: %s\n", alcGetString(NULL, alcGetError(NULL))); + return; + } - const ALCchar *current = NULL; - if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) - current = alcGetString(Device, ALC_ALL_DEVICES_SPECIFIER); - if(alcGetError(Device) != ALC_NO_ERROR || !current) - current = alcGetString(Device, ALC_DEVICE_SPECIFIER); - if(current == NULL) - { - Printf(TEXTCOLOR_YELLOW"Failed to retrieve device name: %s\n", alcGetString(Device, alcGetError(Device))); - return; - } + const ALCchar *current = NULL; + if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) + current = alcGetString(Device, ALC_ALL_DEVICES_SPECIFIER); + if(alcGetError(Device) != ALC_NO_ERROR || !current) + current = alcGetString(Device, ALC_DEVICE_SPECIFIER); + if(current == NULL) + { + Printf(TEXTCOLOR_YELLOW"Failed to retrieve device name: %s\n", alcGetString(Device, alcGetError(Device))); + return; + } - Printf("%c%s%2d. %s\n", ' ', ((strcmp(snd_aldevice, "Default") == 0) ? TEXTCOLOR_BOLD : ""), 0, - "Default"); - for(int i = 1;*drivers;i++) - { - Printf("%c%s%2d. %s\n", ((strcmp(current, drivers)==0) ? '*' : ' '), - ((strcmp(*snd_aldevice, drivers)==0) ? TEXTCOLOR_BOLD : ""), i, - drivers); - drivers += strlen(drivers)+1; - } + Printf("%c%s%2d. %s\n", ' ', ((strcmp(snd_aldevice, "Default") == 0) ? TEXTCOLOR_BOLD : ""), 0, + "Default"); + for(int i = 1;*drivers;i++) + { + Printf("%c%s%2d. %s\n", ((strcmp(current, drivers)==0) ? '*' : ' '), + ((strcmp(*snd_aldevice, drivers)==0) ? TEXTCOLOR_BOLD : ""), i, + drivers); + drivers += strlen(drivers)+1; + } } void OpenALSoundRenderer::PurgeStoppedSources() { - // Release channels that are stopped - for(uint32 i = 0;i < SfxGroup.Size();++i) - { - ALuint src = SfxGroup[i]; - ALint state = AL_INITIAL; - alGetSourcei(src, AL_SOURCE_STATE, &state); - if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED) - continue; + // Release channels that are stopped + for(uint32 i = 0;i < SfxGroup.Size();++i) + { + ALuint src = SfxGroup[i]; + ALint state = AL_INITIAL; + alGetSourcei(src, AL_SOURCE_STATE, &state); + if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED) + continue; - FSoundChan *schan = Channels; - while(schan) - { - if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) - { - StopChannel(schan); - break; - } - schan = schan->NextChan; - } - } - getALError(); + FSoundChan *schan = Channels; + while(schan) + { + if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) + { + StopChannel(schan); + break; + } + schan = schan->NextChan; + } + } + getALError(); } void OpenALSoundRenderer::LoadReverb(const ReverbContainer *env) { - ALuint *envReverb = EnvEffects.CheckKey(env->ID); - bool doLoad = (env->Modified || !envReverb); + ALuint *envReverb = EnvEffects.CheckKey(env->ID); + bool doLoad = (env->Modified || !envReverb); - if(!envReverb) - { - bool ok = false; + if(!envReverb) + { + bool ok = false; - envReverb = &EnvEffects.Insert(env->ID, 0); - alGenEffects(1, envReverb); - if(getALError() == AL_NO_ERROR) - { - alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); - ok = (alGetError() == AL_NO_ERROR); - if(!ok) - { - alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB); - ok = (alGetError() == AL_NO_ERROR); - } - if(!ok) - { - alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_NULL); - ok = (alGetError() == AL_NO_ERROR); - } - if(!ok) - { - alDeleteEffects(1, envReverb); - getALError(); - } - } - if(!ok) - { - *envReverb = 0; - doLoad = false; - } - } + envReverb = &EnvEffects.Insert(env->ID, 0); + alGenEffects(1, envReverb); + if(getALError() == AL_NO_ERROR) + { + alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); + ok = (alGetError() == AL_NO_ERROR); + if(!ok) + { + alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_REVERB); + ok = (alGetError() == AL_NO_ERROR); + } + if(!ok) + { + alEffecti(*envReverb, AL_EFFECT_TYPE, AL_EFFECT_NULL); + ok = (alGetError() == AL_NO_ERROR); + } + if(!ok) + { + alDeleteEffects(1, envReverb); + getALError(); + } + } + if(!ok) + { + *envReverb = 0; + doLoad = false; + } + } - if(doLoad) - { - const REVERB_PROPERTIES &props = env->Properties; - ALint type = AL_EFFECT_NULL; + if(doLoad) + { + const REVERB_PROPERTIES &props = env->Properties; + ALint type = AL_EFFECT_NULL; - alGetEffecti(*envReverb, AL_EFFECT_TYPE, &type); + alGetEffecti(*envReverb, AL_EFFECT_TYPE, &type); #define mB2Gain(x) ((float)pow(10., (x)/2000.)) - if(type == AL_EFFECT_EAXREVERB) - { - ALfloat reflectpan[3] = { props.ReflectionsPan0, - props.ReflectionsPan1, - props.ReflectionsPan2 }; - ALfloat latepan[3] = { props.ReverbPan0, props.ReverbPan1, - props.ReverbPan2 }; + if(type == AL_EFFECT_EAXREVERB) + { + ALfloat reflectpan[3] = { props.ReflectionsPan0, + props.ReflectionsPan1, + props.ReflectionsPan2 }; + ALfloat latepan[3] = { props.ReverbPan0, props.ReverbPan1, + props.ReverbPan2 }; #undef SETPARAM #define SETPARAM(e,t,v) alEffectf((e), AL_EAXREVERB_##t, clamp((v), AL_EAXREVERB_MIN_##t, AL_EAXREVERB_MAX_##t)) - SETPARAM(*envReverb, DIFFUSION, props.EnvDiffusion); - SETPARAM(*envReverb, DENSITY, powf(props.EnvSize, 3.0f) * 0.0625f); - SETPARAM(*envReverb, GAIN, mB2Gain(props.Room)); - SETPARAM(*envReverb, GAINHF, mB2Gain(props.RoomHF)); - SETPARAM(*envReverb, GAINLF, mB2Gain(props.RoomLF)); - SETPARAM(*envReverb, DECAY_TIME, props.DecayTime); - SETPARAM(*envReverb, DECAY_HFRATIO, props.DecayHFRatio); - SETPARAM(*envReverb, DECAY_LFRATIO, props.DecayLFRatio); - SETPARAM(*envReverb, REFLECTIONS_GAIN, mB2Gain(props.Reflections)); - SETPARAM(*envReverb, REFLECTIONS_DELAY, props.ReflectionsDelay); - alEffectfv(*envReverb, AL_EAXREVERB_REFLECTIONS_PAN, reflectpan); - SETPARAM(*envReverb, LATE_REVERB_GAIN, mB2Gain(props.Reverb)); - SETPARAM(*envReverb, LATE_REVERB_DELAY, props.ReverbDelay); - alEffectfv(*envReverb, AL_EAXREVERB_LATE_REVERB_PAN, latepan); - SETPARAM(*envReverb, ECHO_TIME, props.EchoTime); - SETPARAM(*envReverb, ECHO_DEPTH, props.EchoDepth); - SETPARAM(*envReverb, MODULATION_TIME, props.ModulationTime); - SETPARAM(*envReverb, MODULATION_DEPTH, props.ModulationDepth); - SETPARAM(*envReverb, AIR_ABSORPTION_GAINHF, mB2Gain(props.AirAbsorptionHF)); - SETPARAM(*envReverb, HFREFERENCE, props.HFReference); - SETPARAM(*envReverb, LFREFERENCE, props.LFReference); - SETPARAM(*envReverb, ROOM_ROLLOFF_FACTOR, props.RoomRolloffFactor); - alEffecti(*envReverb, AL_EAXREVERB_DECAY_HFLIMIT, - (props.Flags&REVERB_FLAGS_DECAYHFLIMIT)?AL_TRUE:AL_FALSE); + SETPARAM(*envReverb, DIFFUSION, props.EnvDiffusion); + SETPARAM(*envReverb, DENSITY, powf(props.EnvSize, 3.0f) * 0.0625f); + SETPARAM(*envReverb, GAIN, mB2Gain(props.Room)); + SETPARAM(*envReverb, GAINHF, mB2Gain(props.RoomHF)); + SETPARAM(*envReverb, GAINLF, mB2Gain(props.RoomLF)); + SETPARAM(*envReverb, DECAY_TIME, props.DecayTime); + SETPARAM(*envReverb, DECAY_HFRATIO, props.DecayHFRatio); + SETPARAM(*envReverb, DECAY_LFRATIO, props.DecayLFRatio); + SETPARAM(*envReverb, REFLECTIONS_GAIN, mB2Gain(props.Reflections)); + SETPARAM(*envReverb, REFLECTIONS_DELAY, props.ReflectionsDelay); + alEffectfv(*envReverb, AL_EAXREVERB_REFLECTIONS_PAN, reflectpan); + SETPARAM(*envReverb, LATE_REVERB_GAIN, mB2Gain(props.Reverb)); + SETPARAM(*envReverb, LATE_REVERB_DELAY, props.ReverbDelay); + alEffectfv(*envReverb, AL_EAXREVERB_LATE_REVERB_PAN, latepan); + SETPARAM(*envReverb, ECHO_TIME, props.EchoTime); + SETPARAM(*envReverb, ECHO_DEPTH, props.EchoDepth); + SETPARAM(*envReverb, MODULATION_TIME, props.ModulationTime); + SETPARAM(*envReverb, MODULATION_DEPTH, props.ModulationDepth); + SETPARAM(*envReverb, AIR_ABSORPTION_GAINHF, mB2Gain(props.AirAbsorptionHF)); + SETPARAM(*envReverb, HFREFERENCE, props.HFReference); + SETPARAM(*envReverb, LFREFERENCE, props.LFReference); + SETPARAM(*envReverb, ROOM_ROLLOFF_FACTOR, props.RoomRolloffFactor); + alEffecti(*envReverb, AL_EAXREVERB_DECAY_HFLIMIT, + (props.Flags&REVERB_FLAGS_DECAYHFLIMIT)?AL_TRUE:AL_FALSE); #undef SETPARAM - } - else if(type == AL_EFFECT_REVERB) - { + } + else if(type == AL_EFFECT_REVERB) + { #define SETPARAM(e,t,v) alEffectf((e), AL_REVERB_##t, clamp((v), AL_REVERB_MIN_##t, AL_REVERB_MAX_##t)) - SETPARAM(*envReverb, DIFFUSION, props.EnvDiffusion); - SETPARAM(*envReverb, DENSITY, powf(props.EnvSize, 3.0f) * 0.0625f); - SETPARAM(*envReverb, GAIN, mB2Gain(props.Room)); - SETPARAM(*envReverb, GAINHF, mB2Gain(props.RoomHF)); - SETPARAM(*envReverb, DECAY_TIME, props.DecayTime); - SETPARAM(*envReverb, DECAY_HFRATIO, props.DecayHFRatio); - SETPARAM(*envReverb, REFLECTIONS_GAIN, mB2Gain(props.Reflections)); - SETPARAM(*envReverb, REFLECTIONS_DELAY, props.ReflectionsDelay); - SETPARAM(*envReverb, LATE_REVERB_GAIN, mB2Gain(props.Reverb)); - SETPARAM(*envReverb, LATE_REVERB_DELAY, props.ReverbDelay); - SETPARAM(*envReverb, AIR_ABSORPTION_GAINHF, mB2Gain(props.AirAbsorptionHF)); - SETPARAM(*envReverb, ROOM_ROLLOFF_FACTOR, props.RoomRolloffFactor); - alEffecti(*envReverb, AL_REVERB_DECAY_HFLIMIT, - (props.Flags&REVERB_FLAGS_DECAYHFLIMIT)?AL_TRUE:AL_FALSE); + SETPARAM(*envReverb, DIFFUSION, props.EnvDiffusion); + SETPARAM(*envReverb, DENSITY, powf(props.EnvSize, 3.0f) * 0.0625f); + SETPARAM(*envReverb, GAIN, mB2Gain(props.Room)); + SETPARAM(*envReverb, GAINHF, mB2Gain(props.RoomHF)); + SETPARAM(*envReverb, DECAY_TIME, props.DecayTime); + SETPARAM(*envReverb, DECAY_HFRATIO, props.DecayHFRatio); + SETPARAM(*envReverb, REFLECTIONS_GAIN, mB2Gain(props.Reflections)); + SETPARAM(*envReverb, REFLECTIONS_DELAY, props.ReflectionsDelay); + SETPARAM(*envReverb, LATE_REVERB_GAIN, mB2Gain(props.Reverb)); + SETPARAM(*envReverb, LATE_REVERB_DELAY, props.ReverbDelay); + SETPARAM(*envReverb, AIR_ABSORPTION_GAINHF, mB2Gain(props.AirAbsorptionHF)); + SETPARAM(*envReverb, ROOM_ROLLOFF_FACTOR, props.RoomRolloffFactor); + alEffecti(*envReverb, AL_REVERB_DECAY_HFLIMIT, + (props.Flags&REVERB_FLAGS_DECAYHFLIMIT)?AL_TRUE:AL_FALSE); #undef SETPARAM - } + } #undef mB2Gain - } + } - alAuxiliaryEffectSloti(EnvSlot, AL_EFFECTSLOT_EFFECT, *envReverb); - getALError(); + alAuxiliaryEffectSloti(EnvSlot, AL_EFFECTSLOT_EFFECT, *envReverb); + getALError(); } FSoundChan *OpenALSoundRenderer::FindLowestChannel() { - FSoundChan *schan = Channels; - FSoundChan *lowest = NULL; - while(schan) - { - if(schan->SysChannel != NULL) - { - if(!lowest || schan->Priority < lowest->Priority || - (schan->Priority == lowest->Priority && - schan->DistanceSqr > lowest->DistanceSqr)) - lowest = schan; - } - schan = schan->NextChan; - } - return lowest; + FSoundChan *schan = Channels; + FSoundChan *lowest = NULL; + while(schan) + { + if(schan->SysChannel != NULL) + { + if(!lowest || schan->Priority < lowest->Priority || + (schan->Priority == lowest->Priority && + schan->DistanceSqr > lowest->DistanceSqr)) + lowest = schan; + } + schan = schan->NextChan; + } + return lowest; } #endif // NO_OPENAL