diff options
author | IronClawTrem <louie.nutman@gmail.com> | 2020-02-16 03:40:06 +0000 |
---|---|---|
committer | IronClawTrem <louie.nutman@gmail.com> | 2020-02-16 03:40:06 +0000 |
commit | 425decdf7e9284d15aa726e3ae96b9942fb0e3ea (patch) | |
tree | 6c0dd7edfefff1be7b9e75fe0b3a0a85fe1595f3 /src/client/snd_mem.cpp | |
parent | ccb0b2e4d6674a7a00c9bf491f08fc73b6898c54 (diff) |
create tremded branch
Diffstat (limited to 'src/client/snd_mem.cpp')
-rw-r--r-- | src/client/snd_mem.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/src/client/snd_mem.cpp b/src/client/snd_mem.cpp new file mode 100644 index 0000000..128a471 --- /dev/null +++ b/src/client/snd_mem.cpp @@ -0,0 +1,297 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2013 Darklegion Development +Copyright (C) 2015-2019 GrangerHub + +This file is part of Tremulous. + +Tremulous is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +Tremulous is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Tremulous; if not, see <https://www.gnu.org/licenses/> + +=========================================================================== +*/ + +/***************************************************************************** + * name: snd_mem.c + * + * desc: sound caching + *****************************************************************************/ + +#include "snd_codec.h" +#include "snd_local.h" + +#include "qcommon/cvar.h" + +#define DEF_COMSOUNDMEGS "8" + +/* +=============================================================================== + +memory management + +=============================================================================== +*/ + +static sndBuffer *buffer = NULL; +static sndBuffer *freelist = NULL; +static int inUse = 0; +static int totalInUse = 0; + +short *sfxScratchBuffer = NULL; +sfx_t *sfxScratchPointer = NULL; +int sfxScratchIndex = 0; + +void SND_free(sndBuffer *v) +{ + *(sndBuffer **)v = freelist; + freelist = (sndBuffer *)v; + inUse += sizeof(sndBuffer); +} + +sndBuffer *SND_malloc(void) +{ + sndBuffer *v; +redo: + if (freelist == NULL) + { + S_FreeOldestSound(); + goto redo; + } + + inUse -= sizeof(sndBuffer); + totalInUse += sizeof(sndBuffer); + + v = freelist; + freelist = *(sndBuffer **)freelist; + v->next = NULL; + + return v; +} + +void SND_setup(void) +{ + cvar_t* cv = Cvar_Get("com_soundMegs", + DEF_COMSOUNDMEGS, CVAR_LATCH | CVAR_ARCHIVE); + int scs = cv->integer * 1536; + + buffer = (sndBuffer*)malloc(scs * sizeof(sndBuffer)); + + // allocate the stack based hunk allocator + sfxScratchBuffer = (short*)malloc(SND_CHUNK_SIZE * sizeof(short) * 4); + sfxScratchPointer = NULL; + + inUse = scs * sizeof(sndBuffer); + sndBuffer* p = buffer; + sndBuffer* q = p + scs; + while (--q > p) + { + *(sndBuffer **)q = q - 1; + } + + *(sndBuffer **)q = NULL; + freelist = p + scs - 1; + + Com_Printf("Sound memory manager started\n"); +} + +void SND_shutdown(void) +{ + free(sfxScratchBuffer); + free(buffer); +} + +/* +================ +ResampleSfx + +resample / decimate to the current source rate +================ +*/ +static int ResampleSfx(sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, bool compressed) +{ + float stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 + int outcount = samples / stepscale; + int fracstep = stepscale * 256 * channels; + sndBuffer* chunk = sfx->soundData; + + int samplefrac = 0; + int srcsample = 0; + + for (int i = 0; i < outcount; i++) + { + srcsample += samplefrac >> 8; + samplefrac &= 255; + samplefrac += fracstep; + + for (int j = 0; j < channels; j++) + { + int sample; + + if (inwidth == 2) + { + sample = ((short *)data)[srcsample + j]; + } + else + { + sample = (int)((unsigned char)(data[srcsample + j]) - 128) << 8; + } + + int part = (i * channels + j) & (SND_CHUNK_SIZE - 1); + if (part == 0) + { + sndBuffer *newchunk = SND_malloc(); + + if (chunk == NULL) + { + sfx->soundData = newchunk; + } + else + { + chunk->next = newchunk; + } + chunk = newchunk; + } + + chunk->sndChunk[part] = sample; + } + } + + return outcount; +} + +/* +================ +ResampleSfxRaw + +resample / decimate to the current source rate +================ +*/ +static int ResampleSfxRaw(short *sfx, int channels, int inrate, int inwidth, int samples, byte *data) +{ + float stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 + int outcount = samples / stepscale; + int fracstep = stepscale * 256 * channels; + + int samplefrac = 0; + int srcsample = 0; + + for (int i = 0; i < outcount; i++) + { + srcsample += samplefrac >> 8; + srcsample &= 255; + samplefrac += fracstep; + + for (int j = 0; j < channels; j++) + { + int sample; + if (inwidth == 2) + { + sample = LittleShort(((short *)data)[srcsample + j]); + } + else + { + sample = (int)((unsigned char)(data[srcsample + j]) - 128) << 8; + } + sfx[i * channels + j] = sample; + } + } + return outcount; +} + +//============================================================================= + +/* +============== +S_LoadSound + +The filename may be different than sfx->name in the case +of a forced fallback of a player specific sound +============== +*/ +bool S_LoadSound(sfx_t *sfx) +{ + snd_info_t info; + byte *data = (byte*)S_CodecLoad(sfx->soundName, &info); + if (!data) + { + return false; + } + + int size_per_sec = info.rate * info.channels * info.width; + if (size_per_sec > 0) + { + sfx->duration = (int)(1000.0f * ((double)info.size / size_per_sec)); + } + + if (info.width == 1) + { + Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit audio file\n", + sfx->soundName); + } + + if (info.rate != 22050) + { + Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", + sfx->soundName); + } + + short* samples = (short*)Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2); + + sfx->lastTimeUsed = Com_Milliseconds() + 1; + + // each of these compression schemes works just fine + // but the 16bit quality is much nicer and with a local + // install assured we can rely upon the sound memory + // manager to do the right thing for us and page + // sound in as needed + + if (info.channels == 1 && sfx->soundCompressed == true) + { + sfx->soundCompressionMethod = 1; + sfx->soundData = NULL; + sfx->soundLength = ResampleSfxRaw( + samples, + info.channels, + info.rate, + info.width, + info.samples, + data + info.dataofs); + S_AdpcmEncodeSound(sfx, samples); + } + else + { + sfx->soundCompressionMethod = 0; + sfx->soundData = NULL; + sfx->soundLength = ResampleSfx( + sfx, + info.channels, + info.rate, + info.width, + info.samples, + data + info.dataofs, + false); + } + + sfx->soundChannels = info.channels; + + Hunk_FreeTempMemory(samples); + Hunk_FreeTempMemory(data); + + return true; +} + +void S_DisplayFreeMemory(void) +{ + Com_Printf("%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse); +} |