mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-12-11 21:12:06 +00:00
164 lines
4 KiB
C++
164 lines
4 KiB
C++
|
/*
|
||
|
===========================================================================
|
||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||
|
|
||
|
This file is part of Quake III Arena source code.
|
||
|
|
||
|
Quake III Arena source code 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 2 of the License,
|
||
|
or (at your option) any later version.
|
||
|
|
||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
===========================================================================
|
||
|
*/
|
||
|
|
||
|
#include "snd_local.h"
|
||
|
#include "snd_codec.h"
|
||
|
|
||
|
|
||
|
#define DEF_COMSOUNDMEGS "8"
|
||
|
|
||
|
static sndBuffer* sndbuffers = NULL;
|
||
|
static sndBuffer* freelist = NULL;
|
||
|
static int sndmem_avail = 0;
|
||
|
static int sndmem_inuse = 0;
|
||
|
|
||
|
|
||
|
void SND_free( sndBuffer* v )
|
||
|
{
|
||
|
*(sndBuffer **)v = freelist;
|
||
|
freelist = (sndBuffer*)v;
|
||
|
sndmem_avail += sizeof(sndBuffer);
|
||
|
}
|
||
|
|
||
|
sndBuffer* SND_malloc()
|
||
|
{
|
||
|
while (!freelist) {
|
||
|
S_FreeOldestSound();
|
||
|
}
|
||
|
|
||
|
sndmem_avail -= sizeof(sndBuffer);
|
||
|
sndmem_inuse += sizeof(sndBuffer);
|
||
|
|
||
|
sndBuffer* v = freelist;
|
||
|
freelist = *(sndBuffer **)freelist;
|
||
|
v->next = NULL;
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
|
||
|
void SND_setup()
|
||
|
{
|
||
|
sndBuffer *p, *q;
|
||
|
|
||
|
// a sndBuffer is actually 2K+, so this isn't even REMOTELY close to actual megs
|
||
|
const cvar_t* cv = Cvar_Get( "com_soundMegs", DEF_COMSOUNDMEGS, CVAR_LATCH | CVAR_ARCHIVE );
|
||
|
int scs = cv->integer * 1024;
|
||
|
|
||
|
sndbuffers = (sndBuffer*)Hunk_Alloc( scs * sizeof(sndBuffer), h_high );
|
||
|
sndmem_avail = scs * sizeof(sndBuffer);
|
||
|
|
||
|
p = sndbuffers;
|
||
|
q = p + scs;
|
||
|
while (--q > p)
|
||
|
*(sndBuffer **)q = q-1;
|
||
|
|
||
|
*(sndBuffer **)q = NULL;
|
||
|
freelist = p + scs - 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
void S_DisplayFreeMemory()
|
||
|
{
|
||
|
Com_Printf( "%d bytes sound buffer memory in use, %d free \n", sndmem_inuse, sndmem_avail );
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// resample / decimate to the current source rate
|
||
|
|
||
|
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data )
|
||
|
{
|
||
|
int outcount;
|
||
|
int srcsample;
|
||
|
float stepscale;
|
||
|
int i;
|
||
|
int sample, samplefrac, fracstep;
|
||
|
int part;
|
||
|
sndBuffer *chunk;
|
||
|
|
||
|
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
|
||
|
|
||
|
outcount = sfx->soundLength / stepscale;
|
||
|
sfx->soundLength = outcount;
|
||
|
|
||
|
samplefrac = 0;
|
||
|
fracstep = stepscale * 256;
|
||
|
chunk = sfx->soundData;
|
||
|
|
||
|
for (i=0 ; i<outcount ; i++)
|
||
|
{
|
||
|
srcsample = samplefrac >> 8;
|
||
|
samplefrac += fracstep;
|
||
|
if( inwidth == 2 ) {
|
||
|
sample = ( ((short *)data)[srcsample] );
|
||
|
} else {
|
||
|
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||
|
}
|
||
|
part = (i&(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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
qbool S_LoadSound( sfx_t* sfx )
|
||
|
{
|
||
|
// player specific sounds are never directly loaded
|
||
|
if (sfx->soundName[0] == '*') {
|
||
|
return qfalse;
|
||
|
}
|
||
|
|
||
|
snd_info_t info;
|
||
|
byte* data = S_CodecLoad( sfx->soundName, &info );
|
||
|
if (!data)
|
||
|
return qfalse;
|
||
|
|
||
|
if ( info.width == 1 ) {
|
||
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: %s is a 8 bit wav file\n", sfx->soundName );
|
||
|
}
|
||
|
|
||
|
if ( info.rate != 22050 ) {
|
||
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: %s is not a 22kHz wav file\n", sfx->soundName );
|
||
|
}
|
||
|
|
||
|
sfx->lastTimeUsed = Com_Milliseconds();
|
||
|
|
||
|
sfx->soundLength = info.samples;
|
||
|
sfx->soundData = NULL;
|
||
|
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs );
|
||
|
|
||
|
Z_Free(data);
|
||
|
|
||
|
return qtrue;
|
||
|
}
|