mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
281 lines
7.1 KiB
C
281 lines
7.1 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
|
||
|
===========================================================================
|
||
|
*/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* name: snd_mem.c
|
||
|
*
|
||
|
* desc: sound caching
|
||
|
*
|
||
|
* $Archive: /MissionPack/code/client/snd_mem.c $
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "snd_local.h"
|
||
|
#include "snd_codec.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 ) {
|
||
|
sndBuffer *p, *q;
|
||
|
cvar_t *cv;
|
||
|
int scs;
|
||
|
|
||
|
cv = Cvar_Get( "com_soundMegs", DEF_COMSOUNDMEGS, CVAR_LATCH | CVAR_ARCHIVE );
|
||
|
|
||
|
scs = ( cv->integer * 1536 );
|
||
|
|
||
|
buffer = malloc( scs*sizeof( sndBuffer ) );
|
||
|
// allocate the stack based hunk allocator
|
||
|
sfxScratchBuffer = malloc( SND_CHUNK_SIZE * sizeof( short ) * 4 ); //Hunk_Alloc(SND_CHUNK_SIZE * sizeof(short) * 4);
|
||
|
sfxScratchPointer = NULL;
|
||
|
|
||
|
inUse = scs*sizeof( sndBuffer );
|
||
|
p = buffer;;
|
||
|
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, qboolean compressed ) {
|
||
|
int outcount;
|
||
|
int srcsample;
|
||
|
float stepscale;
|
||
|
int i, j;
|
||
|
int sample, samplefrac, fracstep;
|
||
|
int part;
|
||
|
sndBuffer *chunk;
|
||
|
|
||
|
stepscale = ( float )inrate / dma.speed; // this is usually 0.5, 1, or 2
|
||
|
|
||
|
outcount = samples / stepscale;
|
||
|
|
||
|
samplefrac = 0;
|
||
|
fracstep = stepscale * 256 * channels;
|
||
|
chunk = sfx->soundData;
|
||
|
|
||
|
for( i = 0; i<outcount; i++ )
|
||
|
{
|
||
|
srcsample = samplefrac >> 8;
|
||
|
samplefrac += fracstep;
|
||
|
for( j = 0; j<channels; j++ )
|
||
|
{
|
||
|
if( inwidth == 2 ) {
|
||
|
sample = ( ( ( short * )data )[ srcsample + j ] );
|
||
|
}
|
||
|
else {
|
||
|
sample = ( int )( ( unsigned char )( data[ srcsample + j ] ) - 128 ) << 8;
|
||
|
}
|
||
|
part = ( i*channels + j )&( SND_CHUNK_SIZE - 1 );
|
||
|
if( part == 0 ) {
|
||
|
sndBuffer *newchunk;
|
||
|
newchunk = SND_malloc();
|
||
|
if( chunk == NULL ) {
|
||
|
sfx->soundData = newchunk;
|
||
|
}
|
||
|
else {
|
||
|
chunk->next = newchunk;
|
||
|
}
|
||
|
chunk = newchunk;
|
||
|
}
|
||
|
|
||
|
chunk->sndChunk[ part ] = sample;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return outcount;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
ResampleSfx
|
||
|
|
||
|
resample / decimate to the current source rate
|
||
|
================
|
||
|
*/
|
||
|
static int ResampleSfxRaw( short *sfx, int channels, int inrate, int inwidth, int samples, byte *data ) {
|
||
|
int outcount;
|
||
|
int srcsample;
|
||
|
float stepscale;
|
||
|
int i, j;
|
||
|
int sample, samplefrac, fracstep;
|
||
|
|
||
|
stepscale = ( float )inrate / dma.speed; // this is usually 0.5, 1, or 2
|
||
|
|
||
|
outcount = samples / stepscale;
|
||
|
|
||
|
samplefrac = 0;
|
||
|
fracstep = stepscale * 256 * channels;
|
||
|
|
||
|
for( i = 0; i<outcount; i++ )
|
||
|
{
|
||
|
srcsample = samplefrac >> 8;
|
||
|
samplefrac += fracstep;
|
||
|
for( j = 0; j<channels; j++ )
|
||
|
{
|
||
|
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
|
||
|
==============
|
||
|
*/
|
||
|
qboolean S_LoadSound( sfx_t *sfx )
|
||
|
{
|
||
|
byte *data;
|
||
|
short *samples;
|
||
|
snd_info_t info;
|
||
|
// int size;
|
||
|
|
||
|
// load it in
|
||
|
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 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 );
|
||
|
}
|
||
|
|
||
|
samples = 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 == qtrue ) {
|
||
|
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 );
|
||
|
#if 0
|
||
|
}
|
||
|
else if( info.channels == 1 && info.samples>( SND_CHUNK_SIZE * 16 ) && info.width >1 ) {
|
||
|
sfx->soundCompressionMethod = 3;
|
||
|
sfx->soundData = NULL;
|
||
|
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, ( data + info.dataofs ) );
|
||
|
encodeMuLaw( sfx, samples );
|
||
|
}
|
||
|
else if( info.channels == 1 && info.samples>( SND_CHUNK_SIZE * 6400 ) && info.width >1 ) {
|
||
|
sfx->soundCompressionMethod = 2;
|
||
|
sfx->soundData = NULL;
|
||
|
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, ( data + info.dataofs ) );
|
||
|
encodeWavelet( sfx, samples );
|
||
|
#endif
|
||
|
}
|
||
|
else {
|
||
|
sfx->soundCompressionMethod = 0;
|
||
|
sfx->soundData = NULL;
|
||
|
sfx->soundLength = ResampleSfx( sfx, info.channels, info.rate, info.width, info.samples, data + info.dataofs, qfalse );
|
||
|
}
|
||
|
|
||
|
sfx->soundChannels = info.channels;
|
||
|
|
||
|
Hunk_FreeTempMemory( samples );
|
||
|
Hunk_FreeTempMemory( data );
|
||
|
|
||
|
return qtrue;
|
||
|
}
|
||
|
|
||
|
void S_DisplayFreeMemory( void ) {
|
||
|
Com_Printf( "%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse );
|
||
|
}
|