diff --git a/CMakeLists.txt b/CMakeLists.txt index b52bafccf..80eac0c54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,7 +193,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) option(FORCE_INTERNAL_ZLIB "Use internal zlib") option(FORCE_INTERNAL_JPEG "Use internal jpeg") option(FORCE_INTERNAL_BZIP2 "Use internal bzip2") -option(FORCE_INTERNAL_GME "Use internal gme" ON) +option(FORCE_INTERNAL_GME "Use internal gme") # Fast math flags, required by some subprojects set( ZD_FASTMATH_FLAG "" ) diff --git a/src/p_lights.cpp b/src/p_lights.cpp index 10bf9edf4..90d1da869 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -301,9 +301,9 @@ void DFlicker::Tick () DFlicker::DFlicker (sector_t *sector, int upper, int lower) : DLighting (sector) { - m_MaxLight = upper; - m_MinLight = lower; - sector->lightlevel = upper; + m_MaxLight = sector_t::ClampLight(upper); + m_MinLight = sector_t::ClampLight(lower); + sector->lightlevel = m_MaxLight; m_Count = (pr_flicker()&64)+1; } diff --git a/src/sound/oalload.h b/src/sound/oalload.h index 986131b2c..3cee30d58 100644 --- a/src/sound/oalload.h +++ b/src/sound/oalload.h @@ -22,7 +22,7 @@ static oalloadentry oalfuncs[] = { { NULL, 0 } }; - +#ifndef IN_IDE_PARSER #define alEnable p_alEnable #define alDisable p_alDisable #define alIsEnabled p_alIsEnabled @@ -116,6 +116,7 @@ static oalloadentry oalfuncs[] = { #define alcCaptureStart p_alcCaptureStart #define alcCaptureStop p_alcCaptureStop #define alcCaptureSamples p_alcCaptureSamples +#endif #endif -#endif \ No newline at end of file +#endif diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 56dfb4a4c..95fa4d39a 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -40,6 +40,9 @@ #include #endif +#include +#include + #include "except.h" #include "doomstat.h" #include "templates.h" @@ -69,7 +72,7 @@ static void* hmodOpenAL; #ifdef __APPLE__ #define OPENALLIB "OpenAL.framework/OpenAL" #else -#define OPENALLIB "libopenal.so" +#define OPENALLIB "libopenal.so.1" #endif #define LoadLibrary(x) dlopen((x), RTLD_LAZY) #define GetProcAddress(a,b) dlsym((a),(b)) @@ -273,6 +276,8 @@ class OpenALSoundStream : public SoundStream 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); @@ -626,12 +631,21 @@ public: extern ReverbContainer *ForcedEnvironment; -#define AREA_SOUND_RADIUS (128.f) +#define AREA_SOUND_RADIUS (32.f) #define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */ #define PITCH(pitch) (snd_pitched ? (pitch)/128.f : 1.f) +static size_t GetChannelCount(ChannelConfig chans) +{ + switch(chans) + { + case ChannelConfig_Mono: return 1; + case ChannelConfig_Stereo: return 2; + } + return 0; +} static float GetRolloff(const FRolloffInfo *rolloff, float distance) { @@ -686,7 +700,12 @@ template static void LoadALFunc(const char *name, T *x) { *x = reinterpret_cast(alGetProcAddress(name)); } +template +static void LoadALCFunc(ALCdevice *device, const char *name, T *x) +{ *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() : Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) { @@ -744,8 +763,10 @@ OpenALSoundRenderer::OpenALSoundRenderer() DPrintf(" 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.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"); @@ -766,6 +787,12 @@ OpenALSoundRenderer::OpenALSoundRenderer() alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT; } + if(ALC.SOFT_pause_device) + { + LOAD_DEV_FUNC(Device, alcDevicePauseSOFT); + LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT); + } + ALenum err = getALError(); if(err != AL_NO_ERROR) { @@ -905,6 +932,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() if(EnvSlot) Printf(" EFX enabled\n"); } +#undef LOAD_DEV_FUNC #undef LOAD_FUNC OpenALSoundRenderer::~OpenALSoundRenderer() @@ -1042,7 +1070,7 @@ std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int { int sum = 0; for(int c = 0;c < channels;c++) - sum = ((short*)sfxdata)[i*channels + c]; + sum += ((short*)sfxdata)[i*channels + c]; ((short*)sfxdata)[i] = sum / channels; } } @@ -1052,7 +1080,7 @@ std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int { int sum = 0; for(int c = 0;c < channels;c++) - sum = sfxdata[i*channels + c] - 128; + sum += sfxdata[i*channels + c] - 128; sfxdata[i] = (sum / channels) + 128; } } @@ -1124,7 +1152,7 @@ std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le SampleType type; int srate; - SoundDecoder *decoder = CreateDecoder(&reader); + std::unique_ptr decoder(CreateDecoder(&reader)); if(!decoder) return std::make_pair(retval, true); decoder->getInfo(&srate, &chans, &type); @@ -1143,46 +1171,53 @@ std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le { Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), GetSampleTypeName(type)); - delete decoder; return std::make_pair(retval, true); } TArray data = decoder->readAll(); if(chans != ChannelConfig_Mono && monoize) { - // TODO: Handle this better if ChannelConfig ever gets more channel configurations. - size_t frames = data.Size() / 2 / (type == SampleType_Int16 ? 2 : 1); + 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++) - sfxdata[i] = (sfxdata[i*2 + 0]-0 + sfxdata[i*2 + 1]-0)/2; + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c]; + sfxdata[i] = sum / chancount; + } } else if(type == SampleType_UInt8) { BYTE *sfxdata = (BYTE*)&data[0]; for(size_t i = 0;i < frames;i++) - sfxdata[i] = (sfxdata[i*2 + 0]-128 + sfxdata[i*2 + 1]-128)/2 + 128; + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c] - 128; + sfxdata[i] = (sum / chancount) + 128; + } } - data.Resize(data.Size()/2); + data.Resize(data.Size()/chancount); } + ALenum err; ALuint buffer = 0; alGenBuffers(1, &buffer); alBufferData(buffer, format, &data[0], data.Size(), srate); - - ALenum err; if((err=getALError()) != AL_NO_ERROR) { Printf("Failed to buffer data: %s\n", alGetString(err)); alDeleteBuffers(1, &buffer); getALError(); - delete decoder; return std::make_pair(retval, true); } retval.data = MAKE_PTRID(buffer); - delete decoder; return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); } @@ -1262,6 +1297,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int 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) { @@ -1282,7 +1319,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int else alSourcef(source, AL_PITCH, PITCH(pitch)); - if(!reuse_chan) + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) alSourcef(source, AL_SEC_OFFSET, 0.f); else { @@ -1290,8 +1327,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); else { - // FIXME: set offset based on the current time and the StartTime - alSourcef(source, AL_SEC_OFFSET, 0.f); + 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) @@ -1321,7 +1361,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int chan->Rolloff.RolloffType = ROLLOFF_Log; chan->Rolloff.RolloffFactor = 0.f; chan->Rolloff.MinDistance = 1.f; - chan->DistanceScale = 1.f; chan->DistanceSqr = 0.f; chan->ManualRolloff = false; @@ -1404,7 +1443,16 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale); dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); } - if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + 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; @@ -1414,20 +1462,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + else { - FVector3 dir = pos - listener->position; + 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; + 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; + dir += listener->position; + } alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } - else - alSource3f(source, AL_POSITION, pos[0], pos[1], -pos[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); @@ -1456,7 +1508,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else alSourcef(source, AL_PITCH, PITCH(pitch)); - if(!reuse_chan) + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) alSourcef(source, AL_SEC_OFFSET, 0.f); else { @@ -1464,8 +1516,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); else { - // FIXME: set offset based on the current time and the StartTime - alSourcef(source, AL_SAMPLE_OFFSET, 0.f); + 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) @@ -1493,7 +1548,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff = *rolloff; - chan->DistanceScale = distscale; chan->DistanceSqr = dist_sqr; chan->ManualRolloff = manualRolloff; @@ -1579,10 +1633,20 @@ void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state) { case SoundRenderer::INACTIVE_Active: alListenerf(AL_GAIN, 1.0f); + if(ALC.SOFT_pause_device) + { + alcDeviceResumeSOFT(Device); + getALCError(Device); + } break; - /* FIXME: This doesn't stop anything. */ 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; @@ -1631,26 +1695,26 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh if(chan == NULL || chan->SysChannel == NULL) return; - alDeferUpdatesSOFT(); - FVector3 dir = pos - listener->position; chan->DistanceSqr = (float)dir.LengthSquared(); if(chan->ManualRolloff) { - 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); - } - if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + 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(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + 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); @@ -1659,6 +1723,8 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh } dir += listener->position; + alDeferUpdatesSOFT(); + ALuint source = GET_PTRID(chan->SysChannel); alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); @@ -1802,7 +1868,7 @@ 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 = 0; + chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count(); } float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 2644b171a..88dcbc238 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -58,6 +58,11 @@ #define AL_FORMAT_71CHN32 0x1212 #endif +#ifndef AL_EXT_SOURCE_RADIUS +#define AL_EXT_SOURCE_RADIUS 1 +#define AL_SOURCE_RADIUS 0x1031 +#endif + #include "efx.h" @@ -124,9 +129,11 @@ private: struct { bool EXT_EFX; bool EXT_disconnect; + bool SOFT_pause_device; } ALC; struct { bool EXT_source_distance_model; + bool EXT_SOURCE_RADIUS; bool SOFT_deferred_updates; bool SOFT_loop_points; } AL; @@ -174,6 +181,9 @@ private: ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void); ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void); + void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device); + void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device); + void LoadReverb(const ReverbContainer *env); void PurgeStoppedSources(); static FSoundChan *FindLowestChannel(); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 34a9cf02c..e5d080095 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2433,12 +2433,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) ACTION_RETURN_BOOL(true); } - if (distance == 0) - { - // use the minimum distance that does not result in an overlap - distance = (self->radius + GetDefaultByType(missile)->radius); - } - if (ACTION_CALL_FROM_WEAPON()) { // Used from a weapon, so use some ammo