# Conflicts:
#	src/sound/fmodsound.cpp
This commit is contained in:
nashmuhandes 2016-05-20 16:38:54 +08:00
commit 8e87f5debe
22 changed files with 301 additions and 128 deletions

View file

@ -2817,8 +2817,8 @@ void AM_drawThings ()
if (texture == NULL) goto drawTriangle; // fall back to standard display if no sprite can be found. if (texture == NULL) goto drawTriangle; // fall back to standard display if no sprite can be found.
const double spriteXScale = (t->Scale.X * 10 * scale_mtof); const double spriteXScale = (t->Scale.X * (10. / 16.) * scale_mtof);
const double spriteYScale = (t->Scale.Y * 10 * scale_mtof); const double spriteYScale = (t->Scale.Y * (10. / 16.) * scale_mtof);
DrawMarker (texture, p.x, p.y, 0, !!(frame->Flip & (1 << rotation)), DrawMarker (texture, p.x, p.y, 0, !!(frame->Flip & (1 << rotation)),
spriteXScale, spriteYScale, t->Translation, 1., 0, LegacyRenderStyles[STYLE_Normal]); spriteXScale, spriteYScale, t->Translation, 1., 0, LegacyRenderStyles[STYLE_Normal]);
@ -2918,8 +2918,8 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust,
AM_rotatePoint (&x, &y); AM_rotatePoint (&x, &y);
} }
screen->DrawTexture (tex, CXMTOF(x) + f_x, CYMTOF(y) + yadjust + f_y, screen->DrawTexture (tex, CXMTOF(x) + f_x, CYMTOF(y) + yadjust + f_y,
DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * xscale / 16, DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * xscale,
DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * yscale / 16, DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * yscale,
DTA_ClipTop, f_y, DTA_ClipTop, f_y,
DTA_ClipBottom, f_y + f_h, DTA_ClipBottom, f_y + f_h,
DTA_ClipLeft, f_x, DTA_ClipLeft, f_x,
@ -3012,7 +3012,7 @@ void AM_drawAuthorMarkers ()
marked->subsector->flags & SSECF_DRAWN : marked->subsector->flags & SSECF_DRAWN :
marked->Sector->MoreFlags & SECF_DRAWN))) marked->Sector->MoreFlags & SECF_DRAWN)))
{ {
DrawMarker (tex, marked->X(), marked->Y(), 0, flip, mark->Scale.X*16, mark->Scale.Y*16, mark->Translation, DrawMarker (tex, marked->X(), marked->Y(), 0, flip, mark->Scale.X, mark->Scale.Y, mark->Translation,
mark->Alpha, mark->fillcolor, mark->RenderStyle); mark->Alpha, mark->fillcolor, mark->RenderStyle);
} }
marked = mark->args[0] != 0 ? it.Next() : NULL; marked = mark->args[0] != 0 ? it.Next() : NULL;

View file

@ -555,8 +555,15 @@ void SetCompatibilityParams()
if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors) if ((unsigned)CompatParams[i + 1] < (unsigned)numsectors)
{ {
// this assumes that the sector does not have any tags yet! // this assumes that the sector does not have any tags yet!
if (CompatParams[i + 2] == 0)
{
tagManager.RemoveSectorTags(CompatParams[i + 1]);
}
else
{
tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]); tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]);
} }
}
i += 3; i += 3;
break; break;
} }

View file

@ -914,7 +914,6 @@ void D_Display ()
} while (diff < 1); } while (diff < 1);
wipestart = nowtime; wipestart = nowtime;
done = screen->WipeDo (1); done = screen->WipeDo (1);
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
C_DrawConsole (hw2d); // console and C_DrawConsole (hw2d); // console and
M_Drawer (); // menu are drawn even on top of wipes M_Drawer (); // menu are drawn even on top of wipes
screen->Update (); // page flip or blit buffer screen->Update (); // page flip or blit buffer
@ -1013,7 +1012,6 @@ void D_DoomLoop ()
// Update display, next frame, with current state. // Update display, next frame, with current state.
I_StartTic (); I_StartTic ();
D_Display (); D_Display ();
S_UpdateMusic(); // OpenAL needs this to keep the music running, thanks to a complete lack of a sane streaming implementation using callbacks. :(
if (wantToRestart) if (wantToRestart)
{ {
wantToRestart = false; wantToRestart = false;

View file

@ -223,7 +223,7 @@ static void ParseLock(FScanner &sc)
} }
ignorekey = true; ignorekey = true;
if (keynum > 0 && keynum < 255) if (keynum > 0 && keynum <= 255)
{ {
lock = new Lock; lock = new Lock;
if (locks[keynum]) if (locks[keynum])

View file

@ -963,7 +963,7 @@ void gl_RenderModel(GLSprite * spr)
// Added MDL_INHERITACTORPITCH and MDL_INHERITACTORROLL flags processing. // Added MDL_INHERITACTORPITCH and MDL_INHERITACTORROLL flags processing.
// If both flags MDL_INHERITACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the momentum vector pitch. // If both flags MDL_INHERITACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the momentum vector pitch.
if(smf->flags & MDL_INHERITACTORPITCH) pitch += spr->actor->Angles.Pitch.Degrees; if(smf->flags & MDL_INHERITACTORPITCH) pitch -= spr->actor->Angles.Pitch.Degrees;
if(smf->flags & MDL_INHERITACTORROLL) roll += spr->actor->Angles.Roll.Degrees; if(smf->flags & MDL_INHERITACTORROLL) roll += spr->actor->Angles.Roll.Degrees;
gl_RenderState.mModelMatrix.loadIdentity(); gl_RenderState.mModelMatrix.loadIdentity();
@ -974,7 +974,7 @@ void gl_RenderModel(GLSprite * spr)
// Applying model transformations: // Applying model transformations:
// 1) Applying actor angle, pitch and roll to the model // 1) Applying actor angle, pitch and roll to the model
gl_RenderState.mModelMatrix.rotate(-angle, 0, 1, 0); gl_RenderState.mModelMatrix.rotate(-angle, 0, 1, 0);
gl_RenderState.mModelMatrix.rotate(-pitch, 0, 0, 1); gl_RenderState.mModelMatrix.rotate(pitch, 0, 0, 1);
gl_RenderState.mModelMatrix.rotate(-roll, 1, 0, 0); gl_RenderState.mModelMatrix.rotate(-roll, 1, 0, 0);
// 2) Applying Doomsday like rotation of the weapon pickup models // 2) Applying Doomsday like rotation of the weapon pickup models

View file

@ -120,6 +120,8 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli)
{ {
Plane p; Plane p;
if (renderstyle == STYLE_Add) return; // no lights on additively blended surfaces.
if (dli != NULL && *dli != -1) if (dli != NULL && *dli != -1)
{ {
gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli));
@ -453,6 +455,7 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
gl_SetPlaneTextureRotation(&plane, gltexture); gl_SetPlaneTextureRotation(&plane, gltexture);
DrawSubsectors(pass, false, false); DrawSubsectors(pass, false, false);
gl_RenderState.EnableTextureMatrix(false);
break; break;
} }
} }

View file

@ -73,6 +73,8 @@ FDynLightData lightdata;
void GLWall::SetupLights() void GLWall::SetupLights()
{ {
if (RenderStyle == STYLE_Add) return; // no lights on additively blended surfaces.
// check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.)
switch (type) switch (type)
{ {

View file

@ -458,6 +458,7 @@ void M_SetMenu(FName menu, int param)
} }
} }
Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars()); Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars());
M_ClearMenus();
} }
//============================================================================= //=============================================================================

View file

@ -1333,9 +1333,13 @@ static int CheckInventory (AActor *activator, const char *type, bool max)
if (max) if (max)
{ {
if (item) if (item)
{
return item->MaxAmount; return item->MaxAmount;
else }
return ((AInventory *)GetDefaultByType (info))->MaxAmount; else if (info != nullptr && info->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
return ((AInventory *)GetDefaultByType(info))->MaxAmount;
}
} }
return item ? item->Amount : 0; return item ? item->Amount : 0;
} }

View file

@ -783,6 +783,63 @@ DEFINE_ACTION_FUNCTION(AInventory, A_CheckReload)
return 0; return 0;
} }
//---------------------------------------------------------------------------
//
// PROC A_WeaponOffset
//
//---------------------------------------------------------------------------
enum WOFFlags
{
WOF_KEEPX = 1,
WOF_KEEPY = 1 << 1,
WOF_ADD = 1 << 2,
};
DEFINE_ACTION_FUNCTION(AInventory, A_WeaponOffset)
{
PARAM_ACTION_PROLOGUE;
PARAM_FLOAT_OPT(wx) { wx = 0.; }
PARAM_FLOAT_OPT(wy) { wy = 32.; }
PARAM_INT_OPT(flags) { flags = 0; }
if ((flags & WOF_KEEPX) && (flags & WOF_KEEPY))
{
return 0;
}
player_t *player = self->player;
pspdef_t *psp;
if (player && (player->playerstate != PST_DEAD))
{
psp = &player->psprites[ps_weapon];
if (!(flags & WOF_KEEPX))
{
if (flags & WOF_ADD)
{
psp->sx += wx;
}
else
{
psp->sx = wx;
}
}
if (!(flags & WOF_KEEPY))
{
if (flags & WOF_ADD)
{
psp->sy += wy;
}
else
{
psp->sy = wy;
}
}
}
return 0;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// PROC A_Lower // PROC A_Lower

View file

@ -2661,17 +2661,6 @@ void S_StopMusic (bool force)
} }
} }
//==========================================================================
//
//
//
//==========================================================================
void S_UpdateMusic()
{
GSnd->UpdateMusic();
}
//========================================================================== //==========================================================================
// //
// CCMD playsound // CCMD playsound

View file

@ -333,7 +333,6 @@ int S_GetMusic (char **name);
// Stops the music for sure. // Stops the music for sure.
void S_StopMusic (bool force); void S_StopMusic (bool force);
void S_UpdateMusic();
// Stop and resume music, during game PAUSE. // Stop and resume music, during game PAUSE.
void S_PauseSound (bool notmusic, bool notsfx); void S_PauseSound (bool notmusic, bool notsfx);

View file

@ -23,19 +23,6 @@ inline int CheckException(DWORD code)
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
#else
#ifdef __try
#undef __try
#endif
#define __try
#ifdef __except
#undef __except
#endif
#define __except(a) if (0)
#endif #endif
#endif #endif

View file

@ -148,7 +148,6 @@ public:
virtual void UpdateListener (SoundListener *) = 0; virtual void UpdateListener (SoundListener *) = 0;
virtual void UpdateSounds () = 0; virtual void UpdateSounds () = 0;
virtual void UpdateMusic() {}
virtual bool IsValid () = 0; virtual bool IsValid () = 0;
virtual void PrintStatus () = 0; virtual void PrintStatus () = 0;

View file

@ -56,17 +56,18 @@ bool MPG123Decoder::open(FileReader *reader)
{ {
if(!inited) if(!inited)
{ {
__try #ifdef _MSC_VER
{ __try {
#endif
if(mpg123_init() != MPG123_OK) if(mpg123_init() != MPG123_OK)
return false; return false;
inited = true; inited = true;
} #ifdef _MSC_VER
__except (CheckException(GetExceptionCode())) } __except (CheckException(GetExceptionCode())) {
{
// this means that the delay loaded decoder DLL was not found. // this means that the delay loaded decoder DLL was not found.
return false; return false;
} }
#endif
} }
Reader = reader; Reader = reader;

View file

@ -75,8 +75,12 @@ CUSTOM_CVAR (Int, snd_mididevice, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
if ((self >= (signed)nummididevices) || (self < -6)) if ((self >= (signed)nummididevices) || (self < -6))
{ {
Printf ("ID out of range. Using default device.\n"); // Don't do repeated message spam if there is no valid device.
if (self != 0)
{
Printf("ID out of range. Using default device.\n");
self = 0; self = 0;
}
return; return;
} }
mididevice = MAX<UINT>(0, self); mididevice = MAX<UINT>(0, self);

View file

@ -221,7 +221,7 @@ class OpenALSoundStream : public SoundStream
ALuint Buffers[BufferCount]; ALuint Buffers[BufferCount];
ALuint Source; ALuint Source;
bool Playing; std::atomic<bool> Playing;
bool Looping; bool Looping;
ALfloat Volume; ALfloat Volume;
@ -287,12 +287,14 @@ public:
OpenALSoundStream(OpenALSoundRenderer *renderer) OpenALSoundStream(OpenALSoundRenderer *renderer)
: Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL) : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL)
{ {
Renderer->Streams.Push(this);
memset(Buffers, 0, sizeof(Buffers)); memset(Buffers, 0, sizeof(Buffers));
Renderer->AddStream(this);
} }
virtual ~OpenALSoundStream() virtual ~OpenALSoundStream()
{ {
Renderer->RemoveStream(this);
if(Source) if(Source)
{ {
alSourceRewind(Source); alSourceRewind(Source);
@ -309,9 +311,6 @@ public:
} }
getALError(); getALError();
Renderer->Streams.Delete(Renderer->Streams.Find(this));
Renderer = NULL;
delete Decoder; delete Decoder;
delete Reader; delete Reader;
} }
@ -321,7 +320,7 @@ public:
{ {
SetVolume(vol); SetVolume(vol);
if(Playing) if(Playing.load())
return true; return true;
/* Clear the buffer queue, then fill and queue each buffer */ /* Clear the buffer queue, then fill and queue each buffer */
@ -342,21 +341,24 @@ public:
return false; return false;
alSourcePlay(Source); alSourcePlay(Source);
Playing = (getALError()==AL_NO_ERROR); if(getALError() != AL_NO_ERROR)
return false;
return Playing; Playing.store(true);
return true;
} }
virtual void Stop() virtual void Stop()
{ {
if(!Playing) if(!Playing.load())
return; return;
std::unique_lock<std::mutex> lock(Renderer->StreamLock);
alSourceStop(Source); alSourceStop(Source);
alSourcei(Source, AL_BUFFER, 0); alSourcei(Source, AL_BUFFER, 0);
getALError(); getALError();
Playing = false; Playing.store(false);
} }
virtual void SetVolume(float vol) virtual void SetVolume(float vol)
@ -382,21 +384,25 @@ public:
virtual bool SetPosition(unsigned int ms_pos) virtual bool SetPosition(unsigned int ms_pos)
{ {
std::unique_lock<std::mutex> lock(Renderer->StreamLock);
if(!Decoder->seek(ms_pos)) if(!Decoder->seek(ms_pos))
return false; return false;
if(!Playing) if(!Playing.load())
return true; return true;
// Stop the source so that all buffers become processed, then call // Stop the source so that all buffers become processed, which will
// IsEnded() to refill and restart the source queue with the new // allow the next update to restart the source queue with the new
// position. // position.
alSourceStop(Source); alSourceStop(Source);
getALError(); getALError();
return !IsEnded(); lock.unlock();
Renderer->StreamWake.notify_all();
return true;
} }
virtual unsigned int GetPosition() virtual unsigned int GetPosition()
{ {
std::unique_lock<std::mutex> lock(Renderer->StreamLock);
ALint offset, queued, state; ALint offset, queued, state;
alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset);
alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
@ -405,6 +411,8 @@ public:
return 0; return 0;
size_t pos = Decoder->getSampleOffset(); size_t pos = Decoder->getSampleOffset();
lock.unlock();
if(state != AL_STOPPED) if(state != AL_STOPPED)
{ {
size_t rem = queued*(Data.Size()/FrameSize) - offset; size_t rem = queued*(Data.Size()/FrameSize) - offset;
@ -416,54 +424,10 @@ public:
virtual bool IsEnded() virtual bool IsEnded()
{ {
if(!Playing) return !Playing.load();
return true;
ALint state, processed;
alGetSourcei(Source, AL_SOURCE_STATE, &state);
alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed);
Playing = (getALError()==AL_NO_ERROR);
if(!Playing)
return true;
// 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--;
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, virtual FString GetStats()
// then there was an underrun. Restart the source.
Playing = (getALError()==AL_NO_ERROR);
if(Playing && state != AL_PLAYING && state != AL_PAUSED)
{
ALint queued = 0;
alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
Playing = (getALError() == AL_NO_ERROR) && (queued > 0);
if(Playing)
{
alSourcePlay(Source);
Playing = (getALError()==AL_NO_ERROR);
}
}
return !Playing;
}
FString GetStats()
{ {
FString stats; FString stats;
size_t pos, len; size_t pos, len;
@ -474,6 +438,7 @@ public:
ALint state; ALint state;
ALenum err; ALenum err;
std::unique_lock<std::mutex> lock(Renderer->StreamLock);
alGetSourcef(Source, AL_GAIN, &volume); alGetSourcef(Source, AL_GAIN, &volume);
alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset); alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset);
alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed);
@ -481,16 +446,19 @@ public:
alGetSourcei(Source, AL_SOURCE_STATE, &state); alGetSourcei(Source, AL_SOURCE_STATE, &state);
if((err=alGetError()) != AL_NO_ERROR) if((err=alGetError()) != AL_NO_ERROR)
{ {
lock.unlock();
stats = "Error getting stats: "; stats = "Error getting stats: ";
stats += alGetString(err); stats += alGetString(err);
return stats; return stats;
} }
pos = Decoder->getSampleOffset();
len = Decoder->getSampleLength();
lock.unlock();
stats = (state == AL_INITIAL) ? "Buffering" : (state == AL_STOPPED) ? "Underrun" : stats = (state == AL_INITIAL) ? "Buffering" : (state == AL_STOPPED) ? "Underrun" :
(state == AL_PLAYING || state == AL_PAUSED) ? "Ready" : "Unknown state"; (state == AL_PLAYING || state == AL_PAUSED) ? "Ready" : "Unknown state";
pos = Decoder->getSampleOffset();
len = Decoder->getSampleLength();
if(state == AL_STOPPED) if(state == AL_STOPPED)
offset = BufferCount * (Data.Size()/FrameSize); offset = BufferCount * (Data.Size()/FrameSize);
else else
@ -516,6 +484,57 @@ public:
return stats; return stats;
} }
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;
}
// 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--;
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);
ok = (getALError() == AL_NO_ERROR) && (queued > 0);
if(ok)
{
alSourcePlay(Source);
ok = (getALError()==AL_NO_ERROR);
}
}
Playing.store(ok);
return ok;
}
bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata)
{ {
if(!SetupSource()) if(!SetupSource())
@ -707,7 +726,7 @@ static void LoadALCFunc(ALCdevice *device, const char *name, T *x)
#define LOAD_FUNC(x) (LoadALFunc(#x, &x)) #define LOAD_FUNC(x) (LoadALFunc(#x, &x))
#define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x)) #define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x))
OpenALSoundRenderer::OpenALSoundRenderer() OpenALSoundRenderer::OpenALSoundRenderer()
: 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;
@ -940,6 +959,15 @@ OpenALSoundRenderer::~OpenALSoundRenderer()
if(!Device) if(!Device)
return; return;
if(StreamThread.joinable())
{
std::unique_lock<std::mutex> lock(StreamLock);
QuitThread.store(true);
lock.unlock();
StreamWake.notify_all();
StreamThread.join();
}
while(Streams.Size() > 0) while(Streams.Size() > 0)
delete Streams[0]; delete Streams[0];
@ -974,6 +1002,43 @@ OpenALSoundRenderer::~OpenALSoundRenderer()
Device = NULL; Device = NULL;
} }
void OpenALSoundRenderer::BackgroundProc()
{
std::unique_lock<std::mutex> 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<std::mutex> 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<std::mutex> lock(StreamLock);
unsigned int idx = Streams.Find(stream);
if(idx < Streams.Size())
Streams.Delete(idx);
}
void OpenALSoundRenderer::SetSfxVolume(float volume) void OpenALSoundRenderer::SetSfxVolume(float volume)
{ {
SfxVolume = volume; SfxVolume = volume;
@ -1252,6 +1317,8 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) 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);
OpenALSoundStream *stream = new OpenALSoundStream(this); OpenALSoundStream *stream = new OpenALSoundStream(this);
if (!stream->Init(callback, buffbytes, flags, samplerate, userdata)) if (!stream->Init(callback, buffbytes, flags, samplerate, userdata))
{ {
@ -1263,6 +1330,8 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int
SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags) SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags)
{ {
if(StreamThread.get_id() == std::thread::id())
StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this);
OpenALSoundStream *stream = new OpenALSoundStream(this); OpenALSoundStream *stream = new OpenALSoundStream(this);
if (!stream->Init(reader, !!(flags&SoundStream::Loop))) if (!stream->Init(reader, !!(flags&SoundStream::Loop)))
{ {
@ -1460,8 +1529,18 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
} }
dir += listener->position; 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_POSITION, dir[0], dir[1], -dir[2]);
} }
}
else else
{ {
FVector3 dir = pos; FVector3 dir = pos;
@ -1478,12 +1557,21 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
dir += listener->position; 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_POSITION, dir[0], dir[1], -dir[2]);
} }
}
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f);
alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE);
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_MAX_GAIN, SfxVolume); alSourcef(source, AL_MAX_GAIN, SfxVolume);
@ -1724,9 +1812,18 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
dir += listener->position; dir += listener->position;
alDeferUpdatesSOFT(); alDeferUpdatesSOFT();
ALuint source = GET_PTRID(chan->SysChannel); 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_POSITION, dir[0], dir[1], -dir[2]);
}
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
getALError(); getALError();
} }
@ -1852,13 +1949,6 @@ void OpenALSoundRenderer::UpdateSounds()
PurgeStoppedSources(); PurgeStoppedSources();
} }
void OpenALSoundRenderer::UpdateMusic()
{
// For some reason this isn't being called?
for(uint32 i = 0;i < Streams.Size();++i)
Streams[i]->IsEnded();
}
bool OpenALSoundRenderer::IsValid() bool OpenALSoundRenderer::IsValid()
{ {
return Device != NULL; return Device != NULL;

View file

@ -1,6 +1,11 @@
#ifndef OALSOUND_H #ifndef OALSOUND_H
#define OALSOUND_H #define OALSOUND_H
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include "i_sound.h" #include "i_sound.h"
#include "s_sound.h" #include "s_sound.h"
#include "menu/menu.h" #include "menu/menu.h"
@ -114,7 +119,6 @@ public:
virtual void UpdateListener(SoundListener *); virtual void UpdateListener(SoundListener *);
virtual void UpdateSounds(); virtual void UpdateSounds();
virtual void UpdateMusic();
virtual void MarkStartTime(FISoundChannel*); virtual void MarkStartTime(FISoundChannel*);
virtual float GetAudibility(FISoundChannel*); virtual float GetAudibility(FISoundChannel*);
@ -184,10 +188,19 @@ private:
void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device); void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device);
void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device); void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device);
void BackgroundProc();
void AddStream(OpenALSoundStream *stream);
void RemoveStream(OpenALSoundStream *stream);
void LoadReverb(const ReverbContainer *env); void LoadReverb(const ReverbContainer *env);
void PurgeStoppedSources(); void PurgeStoppedSources();
static FSoundChan *FindLowestChannel(); static FSoundChan *FindLowestChannel();
std::thread StreamThread;
std::mutex StreamLock;
std::condition_variable StreamWake;
std::atomic<bool> QuitThread;
ALCdevice *Device; ALCdevice *Device;
ALCcontext *Context; ALCcontext *Context;

View file

@ -54,8 +54,9 @@ SndFileDecoder::~SndFileDecoder()
bool SndFileDecoder::open(FileReader *reader) bool SndFileDecoder::open(FileReader *reader)
{ {
__try #ifdef _MSC_VER
{ __try {
#endif
SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell };
Reader = reader; Reader = reader;
@ -68,11 +69,11 @@ bool SndFileDecoder::open(FileReader *reader)
sf_close(SndFile); sf_close(SndFile);
SndFile = 0; SndFile = 0;
} }
} #ifdef _MSC_VER
__except (CheckException(GetExceptionCode())) } __except (CheckException(GetExceptionCode())) {
{
// this means that the delay loaded decoder DLL was not found. // this means that the delay loaded decoder DLL was not found.
} }
#endif
return false; return false;
} }

View file

@ -561,3 +561,11 @@ enum
GZF_NOPORTALS = 1 << 4, // Don't pass through any portals. GZF_NOPORTALS = 1 << 4, // Don't pass through any portals.
GZF_NO3DFLOOR = 1 << 5, // Pass all 3D floors. GZF_NO3DFLOOR = 1 << 5, // Pass all 3D floors.
}; };
// Flags for A_WeaponOffset
enum
{
WOF_KEEPX = 1,
WOF_KEEPY = 1 << 1,
WOF_ADD = 1 << 2,
};

View file

@ -48,6 +48,7 @@ ACTOR Inventory native
action native A_RestoreSpecialDoomThing(); action native A_RestoreSpecialDoomThing();
action native A_RestoreSpecialThing1(); action native A_RestoreSpecialThing1();
action native A_RestoreSpecialThing2(); action native A_RestoreSpecialThing2();
action native A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0);
States States
{ {

View file

@ -51,6 +51,15 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15
resetplayerspeed resetplayerspeed
} }
5C594C67CF7721005DE71429F9811370 // Eternal Doom map03
{
// fix broken staircase. The compatibility option is not sufficient
// to reliably handle this so clear the tags from the unwanted sectors.
setsectortag 212 0
setsectortag 213 0
setsectortag 214 0
}
6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25 6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25
{ {
stairs stairs