From a17ec55d0dee70f76f5d9720136c6bd00af790c8 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sun, 1 May 2016 11:30:09 +0200 Subject: [PATCH 1/5] - Fixed drop style gameinfo inconsistency. The gameinfo option was ignored when deciding the initial spawn height position. --- src/p_enemy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 56437e133..fcc18ae55 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3158,7 +3158,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c int style = sv_dropstyle; if (style == 0) { - style = (gameinfo.gametype == GAME_Strife) ? 2 : 1; + style = gameinfo.defaultdropstyle; } if (style == 2) { @@ -3206,7 +3206,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c void P_TossItem (AActor *item) { int style = sv_dropstyle; - if (style==0) style= gameinfo.defaultdropstyle; + if (style==0) style = gameinfo.defaultdropstyle; if (style==2) { From 3aee8a3eeebd4c820b41b87f097ef39c11db7c14 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sun, 1 May 2016 17:07:39 +0200 Subject: [PATCH 2/5] - Fixed a mistake in GiveInventory refactoring. 'give item' stopped working because commit 7b35f32f3de012ccb0ccabe9086cffddcfe0bd00 and 6aca7604eb37ba8e436261015603b4c9a2f1d311 didn't take account that give cheat with zero amount should not touch the item amount. --- src/p_mobj.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b7d887195..ecd6b8d1c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -638,20 +638,23 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat) // This shouldn't count for the item statistics! item->ClearCounters(); - if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) + if (!givecheat || amount > 0) { - static_cast(item)->SaveAmount *= amount; - } - else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) - { - static_cast(item)->SaveAmount *= amount; - } - else - { - if (!givecheat) - item->Amount = amount; + if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) + { + static_cast(item)->SaveAmount *= amount; + } + else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) + { + static_cast(item)->SaveAmount *= amount; + } else - item->Amount = MIN (amount, item->MaxAmount); + { + if (!givecheat) + item->Amount = amount; + else + item->Amount = MIN (amount, item->MaxAmount); + } } if (!item->CallTryPickup (this)) { From b443ac8f719e02050382efd1b7c097d6d75d6113 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 May 2016 19:30:51 +0200 Subject: [PATCH 3/5] - let Trace() be a bit smarter about checking 3D slopes. If one matches right up with the floor or ceiling at the line where the trace enters a sector, check a second point to see whether we deal with something inside valid sector bounds or not. --- src/p_trace.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 8a3664ac8..67a516f9c 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -494,6 +494,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit) // clip to the part of the sector we are in if (hit.Z > ff_top) { + // 3D floor height is the same as the floor height. We need to test a second spot to see if it is above or below + if (fabs(bf - ff_top) < EQUAL_EPSILON) + { + double cf = entersector->floorplane.ZatPoint(entersector->centerspot); + double ffc = rover->top.plane->ZatPoint(entersector->centerspot); + if (ffc > cf) + { + bf = ff_top - EQUAL_EPSILON; + } + } + // above if (bf < ff_top) { @@ -505,6 +516,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit) } else if (hit.Z < ff_bottom) { + // 3D floor height is the same as the ceiling height. We need to test a second spot to see if it is above or below + if (fabs(bc - ff_bottom) < EQUAL_EPSILON) + { + double cc = entersector->ceilingplane.ZatPoint(entersector->centerspot); + double fcc = rover->bottom.plane->ZatPoint(entersector->centerspot); + if (fcc < cc) + { + bc = ff_bottom + EQUAL_EPSILON; + } + } + //below if (bc > ff_bottom) { From 0d402618a3d24c8194604f1a760aa3f89a86f6cd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 1 May 2016 11:01:59 -0700 Subject: [PATCH 4/5] Load mono copies of multichannel sounds that are used in 3D --- src/s_advsound.cpp | 1 + src/s_sound.cpp | 73 +++++++++++++++++++++++++++++++++---- src/s_sound.h | 3 ++ src/sound/fmodsound.cpp | 18 ++++----- src/sound/fmodsound.h | 4 +- src/sound/i_sound.cpp | 12 +++--- src/sound/i_sound.h | 7 ++-- src/sound/i_soundinternal.h | 5 +++ src/sound/oalsound.cpp | 69 +++++++++++++++++++++++++++++------ src/sound/oalsound.h | 4 +- 10 files changed, 154 insertions(+), 42 deletions(-) diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 6c7bb97df..8bc1b4868 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -500,6 +500,7 @@ int S_AddSoundLump (const char *logicalname, int lump) sfxinfo_t newsfx; newsfx.data.Clear(); + newsfx.data3d.Clear(); newsfx.name = logicalname; newsfx.lumpnum = lump; newsfx.next = 0; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ac4dbc78f..d888c9ec2 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -98,6 +98,7 @@ extern float S_GetMusicVolume (const char *music); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static void S_LoadSound3D(sfxinfo_t *sfx); static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, float limit_range, AActor *actor, int channel); static bool S_IsChannelUsed(AActor *actor, int channel, int *seen); static void S_ActivatePlayList(bool goBack); @@ -546,8 +547,11 @@ void S_UnloadSound (sfxinfo_t *sfx) { if (sfx->data.isValid()) { + if(sfx->data3d.isValid() && sfx->data != sfx->data3d) + GSnd->UnloadSound(sfx->data3d); GSnd->UnloadSound(sfx->data); sfx->data.Clear(); + sfx->data3d.Clear(); DPrintf("Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); } } @@ -1098,9 +1102,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO if (attenuation > 0) { + S_LoadSound3D(sfx); SoundListener listener; S_SetListener(listener, players[consoleplayer].camera); - chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); + chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); } else { @@ -1194,12 +1199,13 @@ void S_RestartSound(FSoundChan *chan) return; } + S_LoadSound3D(sfx); SoundListener listener; S_SetListener(listener, players[consoleplayer].camera); chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME); - ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, - chan->Priority, pos, vel, chan->EntChannel, startflags, chan); + ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data3d, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, + chan->Priority, pos, vel, chan->EntChannel, startflags, chan); } else { @@ -1339,31 +1345,35 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) BYTE *sfxdata = new BYTE[size]; wlump.Read(sfxdata, size); SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]); + std::pair snd; // If the sound is voc, use the custom loader. if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0) { - sfx->data = GSnd->LoadSoundVoc(sfxdata, size); + snd = GSnd->LoadSoundVoc(sfxdata, size); } // If the sound is raw, just load it as such. else if (sfx->bLoadRAW) { - sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart); + snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart); } // Otherwise, try the sound as DMX format. else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8) { int frequency = LittleShort(((WORD *)sfxdata)[1]); if (frequency == 0) frequency = 11025; - sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart); + snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart); } // If that fails, let the sound system try and figure it out. else { - sfx->data = GSnd->LoadSound(sfxdata, size); + snd = GSnd->LoadSound(sfxdata, size); } - delete[] sfxdata; + + sfx->data = snd.first; + if(snd.second) + sfx->data3d = sfx->data; } if (!sfx->data.isValid()) @@ -1379,6 +1389,53 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) return sfx; } +static void S_LoadSound3D(sfxinfo_t *sfx) +{ + if (GSnd->IsNull()) return; + + if(sfx->data3d.isValid()) + return; + + unsigned int i; + + DPrintf("Loading monoized sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); + + int size = Wads.LumpLength(sfx->lumpnum); + if(size <= 0) return; + + FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum); + BYTE *sfxdata = new BYTE[size]; + wlump.Read(sfxdata, size); + SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]); + std::pair snd; + + // If the sound is voc, use the custom loader. + if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0) + { + snd = GSnd->LoadSoundVoc(sfxdata, size, true); + } + // If the sound is raw, just load it as such. + else if (sfx->bLoadRAW) + { + snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart, true); + } + // Otherwise, try the sound as DMX format. + else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8) + { + int frequency = LittleShort(((WORD *)sfxdata)[1]); + if (frequency == 0) frequency = 11025; + snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart, -1, true); + } + // If that fails, let the sound system try and figure it out. + else + { + snd = GSnd->LoadSound(sfxdata, size, true); + } + delete[] sfxdata; + + sfx->data3d = snd.first; +} + //========================================================================== // // S_CheckSingular diff --git a/src/s_sound.h b/src/s_sound.h index ad06195e1..acdee2a2c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -36,6 +36,9 @@ struct sfxinfo_t // Next field is for use by the system sound interface. // A non-null data means the sound has been loaded. SoundHandle data; + // Also for the sound interface. Used for 3D positional + // sounds, may be the same as data. + SoundHandle data3d; FString name; // [RH] Sound name defined in SNDINFO int lumpnum; // lump number of sfx diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index a62998d3d..72e3c0a05 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -2510,7 +2510,7 @@ void FMODSoundRenderer::UpdateSounds() // //========================================================================== -SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) +std::pair FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { FMOD_CREATESOUNDEXINFO exinfo; SoundHandle retval = { NULL }; @@ -2518,7 +2518,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ if (length <= 0) { - return retval; + return std::make_pair(retval, true); } InitCreateSoundExInfo(&exinfo); @@ -2550,7 +2550,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ break; default: - return retval; + return std::make_pair(retval, true); } const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_OPENRAW; @@ -2561,7 +2561,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ if (result != FMOD_OK) { DPrintf("Failed to allocate sample: Error %d\n", result); - return retval; + return std::make_pair(retval, true); } if (loopstart >= 0) @@ -2572,7 +2572,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ } retval.data = sample; - return retval; + return std::make_pair(retval, true); } //========================================================================== @@ -2581,12 +2581,12 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ // //========================================================================== -SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length) +std::pair FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize) { FMOD_CREATESOUNDEXINFO exinfo; SoundHandle retval = { NULL }; - if (length == 0) return retval; + if (length == 0) return std::make_pair(retval, true); InitCreateSoundExInfo(&exinfo); exinfo.length = length; @@ -2599,11 +2599,11 @@ SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length) if (result != FMOD_OK) { DPrintf("Failed to allocate sample: Error %d\n", result); - return retval; + return std::make_pair(retval, true); } SetCustomLoopPts(sample); retval.data = sample; - return retval; + return std::make_pair(retval, true); } //========================================================================== diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index eaf643c85..33b1f4bf7 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -15,8 +15,8 @@ public: void SetSfxVolume (float volume); void SetMusicVolume (float volume); - SoundHandle LoadSound(BYTE *sfxdata, int length); - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); + std::pair LoadSound(BYTE *sfxdata, int length, bool monoize); + std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false); void UnloadSound (SoundHandle sfx); unsigned int GetMSLength(SoundHandle sfx); unsigned int GetSampleLength(SoundHandle sfx); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 894951d1b..f19e080c3 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -135,15 +135,15 @@ public: void SetMusicVolume (float volume) { } - SoundHandle LoadSound(BYTE *sfxdata, int length) + std::pair LoadSound(BYTE *sfxdata, int length, bool monoize) { SoundHandle retval = { NULL }; - return retval; + return std::make_pair(retval, true); } - SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) + std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { SoundHandle retval = { NULL }; - return retval; + return std::make_pair(retval, true); } void UnloadSound (SoundHandle sfx) { @@ -456,7 +456,7 @@ FString SoundStream::GetStats() // //========================================================================== -SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) +std::pair SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length, bool monoize) { BYTE * data = NULL; int len, frequency, channels, bits, loopstart, loopend; @@ -600,7 +600,7 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) } } while (false); - SoundHandle retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend); + std::pair retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend, monoize); if (data) delete[] data; return retval; } diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 836d62019..ef0743c05 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -95,9 +95,10 @@ public: virtual bool IsNull() { return false; } virtual void SetSfxVolume (float volume) = 0; virtual void SetMusicVolume (float volume) = 0; - virtual SoundHandle LoadSound(BYTE *sfxdata, int length) = 0; - SoundHandle LoadSoundVoc(BYTE *sfxdata, int length); - virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1) = 0; + // Returns a pair containing a sound handle and a boolean indicating the sound can be used in 3D. + virtual std::pair LoadSound(BYTE *sfxdata, int length, bool monoize=false) = 0; + std::pair LoadSoundVoc(BYTE *sfxdata, int length, bool monoize=false); + virtual std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false) = 0; virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index 279ffdf88..c86c6cdaa 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -91,6 +91,11 @@ struct SoundHandle bool isValid() const { return data != NULL; } void Clear() { data = NULL; } + + bool operator==(const SoundHandle &rhs) const + { return data == rhs.data; } + bool operator!=(const SoundHandle &rhs) const + { return !(*this == rhs); } }; struct FISoundChannel diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 9b7de9e43..56dfb4a4c 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1019,11 +1019,11 @@ float OpenALSoundRenderer::GetOutputRate() } -SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend) +std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize) { SoundHandle retval = { NULL }; - if(length == 0) return retval; + if(length == 0) return std::make_pair(retval, true); if(bits == -8) { @@ -1033,6 +1033,33 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre 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; + } + ALenum format = AL_NONE; if(bits == 16) { @@ -1048,7 +1075,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre if(format == AL_NONE || frequency <= 0) { Printf("Unhandled format: %d bit, %d channel, %d hz\n", bits, channels, frequency); - return retval; + return std::make_pair(retval, true); } length -= length%(channels*bits/8); @@ -1061,7 +1088,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre Printf("Failed to buffer data: %s\n", alGetString(err)); alDeleteBuffers(1, &buffer); getALError(); - return retval; + return std::make_pair(retval, true); } if((loopstart > 0 || loopend > 0) && AL.SOFT_loop_points) @@ -1085,10 +1112,10 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre } retval.data = MAKE_PTRID(buffer); - return retval; + return std::make_pair(retval, channels==1); } -SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) +std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize) { SoundHandle retval = { NULL }; MemoryReader reader((const char*)sfxdata, length); @@ -1098,15 +1125,15 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) int srate; SoundDecoder *decoder = CreateDecoder(&reader); - if(!decoder) return retval; + if(!decoder) return std::make_pair(retval, true); decoder->getInfo(&srate, &chans, &type); - if(chans == ChannelConfig_Mono) + if(chans == ChannelConfig_Mono || monoize) { if(type == SampleType_UInt8) format = AL_FORMAT_MONO8; if(type == SampleType_Int16) format = AL_FORMAT_MONO16; } - if(chans == ChannelConfig_Stereo) + else if(chans == ChannelConfig_Stereo) { if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8; if(type == SampleType_Int16) format = AL_FORMAT_STEREO16; @@ -1117,10 +1144,28 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), GetSampleTypeName(type)); delete decoder; - return retval; + 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); + 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; + } + 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; + } + data.Resize(data.Size()/2); + } ALuint buffer = 0; alGenBuffers(1, &buffer); @@ -1133,12 +1178,12 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length) alDeleteBuffers(1, &buffer); getALError(); delete decoder; - return retval; + return std::make_pair(retval, true); } retval.data = MAKE_PTRID(buffer); delete decoder; - return retval; + return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); } void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index f528dbc6a..2644b171a 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -71,8 +71,8 @@ public: virtual void SetSfxVolume(float volume); virtual void SetMusicVolume(float volume); - virtual SoundHandle LoadSound(BYTE *sfxdata, int length); - virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); + virtual std::pair LoadSound(BYTE *sfxdata, int length, bool monoize); + virtual std::pair LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false); virtual void UnloadSound(SoundHandle sfx); virtual unsigned int GetMSLength(SoundHandle sfx); virtual unsigned int GetSampleLength(SoundHandle sfx); From 65e1589543edd9d1d86628cd5c1616bada75e149 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 May 2016 22:47:36 +0200 Subject: [PATCH 5/5] - allow specifying actor classes whose graphics to precache through MAPINFO. - some reorganization of texture precaching so that the renderer can decide what to do with actors. Just marking the sprite textures loses too much info if more is needed than just loading the images into memory. --- src/g_level.h | 1 + src/g_mapinfo.cpp | 12 +++++ src/p_setup.cpp | 79 ++++++++++++++++++++++++++++++++- src/r_renderer.h | 2 +- src/r_swrenderer.cpp | 49 ++++++++++++++++++++ src/r_swrenderer.h | 3 +- src/textures/texturemanager.cpp | 38 ---------------- src/textures/textures.h | 1 - src/v_video.cpp | 77 -------------------------------- src/v_video.h | 3 +- 10 files changed, 144 insertions(+), 121 deletions(-) diff --git a/src/g_level.h b/src/g_level.h index a5b3006ac..8360bd45e 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -338,6 +338,7 @@ struct level_info_t TArray PrecacheSounds; TArray PrecacheTextures; + TArray PrecacheClasses; level_info_t() { diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index b6c3a376a..78ba9142b 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1083,6 +1083,18 @@ DEFINE_MAP_OPTION(PrecacheTextures, true) } while (parse.sc.CheckString(",")); } +DEFINE_MAP_OPTION(PrecacheClasses, true) +{ + parse.ParseAssign(); + + do + { + parse.sc.MustGetString(); + //the class list is not initialized here so all we can do is store the class's name. + info->PrecacheClasses.Push(parse.sc.String); + } while (parse.sc.CheckString(",")); +} + DEFINE_MAP_OPTION(redirect, true) { parse.ParseAssign(); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 762f4b794..cdb180e60 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3366,6 +3366,83 @@ void P_GetPolySpots (MapData * map, TArray &spots, TAr } } + +//=========================================================================== +// +// P_PrecacheLevel +// +// Preloads all relevant graphics for the level. +// +//=========================================================================== + +static void P_PrecacheLevel() +{ + int i; + BYTE *hitlist; + TMap actorhitlist; + int cnt = TexMan.NumTextures(); + + if (demoplayback) + return; + + hitlist = new BYTE[cnt]; + memset(hitlist, 0, cnt); + + AActor *actor; + TThinkerIterator iterator; + + while ((actor = iterator.Next())) + { + actorhitlist[actor->GetClass()] = true; + } + + for (unsigned i = 0; i < level.info->PrecacheClasses.Size(); i++) + { + // level.info can only store names, no class pointers. + PClassActor *cls = PClass::FindActor(level.info->PrecacheClasses[i]); + if (cls != NULL) actorhitlist[cls] = true; + } + + for (i = numsectors - 1; i >= 0; i--) + { + hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat; + } + + for (i = numsides - 1; i >= 0; i--) + { + hitlist[sides[i].GetTexture(side_t::top).GetIndex()] |= FTextureManager::HIT_Wall; + hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] |= FTextureManager::HIT_Wall; + hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall; + } + + // Sky texture is always present. + // Note that F_SKY1 is the name used to + // indicate a sky floor/ceiling as a flat, + // while the sky texture is stored like + // a wall texture, with an episode dependant + // name. + + if (sky1texture.isValid()) + { + hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky; + } + if (sky2texture.isValid()) + { + hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky; + } + + for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++) + { + FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall; + } + + Renderer->Precache(hitlist, actorhitlist); + + delete[] hitlist; +} + extern polyblock_t **PolyBlockMap; void P_FreeLevelData () @@ -4094,7 +4171,7 @@ void P_SetupLevel (const char *lumpname, int position) // preload graphics and sounds if (precache) { - TexMan.PrecacheLevel (); + P_PrecacheLevel (); S_PrecacheLevel (); } times[17].Unclock(); diff --git a/src/r_renderer.h b/src/r_renderer.h index 115ac64c9..6c65fc12f 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -28,7 +28,7 @@ struct FRenderer virtual bool UsesColormap() const = 0; // precache one texture - virtual void PrecacheTexture(FTexture *tex, int cache) = 0; + virtual void Precache(BYTE *texhitlist, TMap &actorhitlist) = 0; // render 3D view virtual void RenderView(player_t *player) = 0; diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index d563986f7..07edf25e9 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -98,6 +98,55 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache) } } +void FSoftwareRenderer::Precache(BYTE *texhitlist, TMap &actorhitlist) +{ + BYTE *spritelist = new BYTE[sprites.Size()]; + TMap::Iterator it(actorhitlist); + TMap::Pair *pair; + + memset(spritelist, 0, sprites.Size()); + + while (it.NextPair(pair)) + { + PClassActor *cls = pair->Key; + + for (int i = 0; i < cls->NumOwnedStates; i++) + { + spritelist[cls->OwnedStates[i].sprite] = true; + } + } + + // Precache textures (and sprites). + + for (int i = (int)(sprites.Size() - 1); i >= 0; i--) + { + if (spritelist[i]) + { + int j, k; + for (j = 0; j < sprites[i].numframes; j++) + { + const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; + + for (k = 0; k < 16; k++) + { + FTextureID pic = frame->Texture[k]; + if (pic.isValid()) + { + texhitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite; + } + } + } + } + } + delete[] spritelist; + + int cnt = TexMan.NumTextures(); + for (int i = cnt - 1; i >= 0; i--) + { + PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]); + } +} + //=========================================================================== // // Render the view diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 939547797..3e5fed9bc 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -9,7 +9,8 @@ struct FSoftwareRenderer : public FRenderer virtual bool UsesColormap() const; // precache one texture - virtual void PrecacheTexture(FTexture *tex, int cache); + void PrecacheTexture(FTexture *tex, int cache); + virtual void Precache(BYTE *texhitlist, TMap &actorhitlist); // render 3D view virtual void RenderView(player_t *player); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 1147f5168..95c976f8c 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1226,44 +1226,6 @@ int FTextureManager::CountLumpTextures (int lumpnum) return 0; } -//=========================================================================== -// -// R_PrecacheLevel -// - -// Preloads all relevant graphics for the level. -// -//=========================================================================== - -void FTextureManager::PrecacheLevel (void) -{ - BYTE *hitlist; - int cnt = NumTextures(); - - if (demoplayback) - return; - - hitlist = new BYTE[cnt]; - memset (hitlist, 0, cnt); - - screen->GetHitlist(hitlist); - - for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++) - { - FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst); - if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall; - } - - for (int i = cnt - 1; i >= 0; i--) - { - Renderer->PrecacheTexture(ByIndex(i), hitlist[i]); - } - - delete[] hitlist; -} - - - //========================================================================== // diff --git a/src/textures/textures.h b/src/textures/textures.h index 55ad583ff..14667093c 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -379,7 +379,6 @@ public: void UnloadAll (); int NumTextures () const { return (int)Textures.Size(); } - void PrecacheLevel (void); void WriteTexture (FArchive &arc, int picnum); int ReadTexture (FArchive &arc); diff --git a/src/v_video.cpp b/src/v_video.cpp index 52b8fdc86..01a73950b 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1207,83 +1207,6 @@ void DFrameBuffer::WipeCleanup() wipe_Cleanup(); } -//=========================================================================== -// -// Create texture hitlist -// -//=========================================================================== - -void DFrameBuffer::GetHitlist(BYTE *hitlist) -{ - BYTE *spritelist; - int i; - - spritelist = new BYTE[sprites.Size()]; - - // Precache textures (and sprites). - memset (spritelist, 0, sprites.Size()); - - { - AActor *actor; - TThinkerIterator iterator; - - while ( (actor = iterator.Next ()) ) - spritelist[actor->sprite] = 1; - } - - for (i = (int)(sprites.Size () - 1); i >= 0; i--) - { - if (spritelist[i]) - { - int j, k; - for (j = 0; j < sprites[i].numframes; j++) - { - const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; - - for (k = 0; k < 16; k++) - { - FTextureID pic = frame->Texture[k]; - if (pic.isValid()) - { - hitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite; - } - } - } - } - } - - delete[] spritelist; - - for (i = numsectors - 1; i >= 0; i--) - { - hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] = - hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat; - } - - for (i = numsides - 1; i >= 0; i--) - { - hitlist[sides[i].GetTexture(side_t::top).GetIndex()] = - hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] = - hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall; - } - - // Sky texture is always present. - // Note that F_SKY1 is the name used to - // indicate a sky floor/ceiling as a flat, - // while the sky texture is stored like - // a wall texture, with an episode dependant - // name. - - if (sky1texture.isValid()) - { - hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky; - } - if (sky2texture.isValid()) - { - hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky; - } -} - //========================================================================== // // DFrameBuffer :: GameRestart diff --git a/src/v_video.h b/src/v_video.h index 693bfa687..fa1ce83df 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -395,8 +395,7 @@ public: virtual FNativePalette *CreatePalette(FRemapTable *remap); // Precaches or unloads a texture - virtual void GetHitlist(BYTE *hitlist); - + // Report a game restart virtual void GameRestart();