This commit is contained in:
Christoph Oelckers 2016-05-05 21:51:54 +02:00
commit f4e4221da7
6 changed files with 128 additions and 57 deletions

View file

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

View file

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

View file

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

View file

@ -40,6 +40,9 @@
#include <dlfcn.h>
#endif
#include <memory>
#include <chrono>
#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<typename T>
static void LoadALFunc(const char *name, T *x)
{ *x = reinterpret_cast<T>(alGetProcAddress(name)); }
template<typename T>
static void LoadALCFunc(ALCdevice *device, const char *name, T *x)
{ *x = reinterpret_cast<T>(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<SoundHandle,bool> 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<SoundHandle,bool> 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<SoundHandle,bool> OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le
SampleType type;
int srate;
SoundDecoder *decoder = CreateDecoder(&reader);
std::unique_ptr<SoundDecoder> decoder(CreateDecoder(&reader));
if(!decoder) return std::make_pair(retval, true);
decoder->getInfo(&srate, &chans, &type);
@ -1143,46 +1171,53 @@ std::pair<SoundHandle,bool> 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<char> 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::duration<float>>(
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<float>(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::duration<float>>(
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)

View file

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

View file

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