Itsa me, quake3io!
This commit is contained in:
parent
dbe4ddb103
commit
5b755058f5
1409 changed files with 798983 additions and 798983 deletions
2058
code/client/cl_cgame.c
Normal file → Executable file
2058
code/client/cl_cgame.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
3480
code/client/cl_cin.c
Normal file → Executable file
3480
code/client/cl_cin.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1572
code/client/cl_console.c
Normal file → Executable file
1572
code/client/cl_console.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1802
code/client/cl_input.c
Normal file → Executable file
1802
code/client/cl_input.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2504
code/client/cl_keys.c
Normal file → Executable file
2504
code/client/cl_keys.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
6648
code/client/cl_main.c
Normal file → Executable file
6648
code/client/cl_main.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
334
code/client/cl_net_chan.c
Normal file → Executable file
334
code/client/cl_net_chan.c
Normal file → Executable file
|
@ -1,167 +1,167 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "client.h"
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Encode
|
||||
|
||||
// first 12 bytes of the data are always:
|
||||
long serverId;
|
||||
long messageAcknowledge;
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Encode( msg_t *msg ) {
|
||||
int serverId, messageAcknowledge, reliableAcknowledge;
|
||||
int i, index, srdc, sbit, soob;
|
||||
byte key, *string;
|
||||
|
||||
if ( msg->cursize <= CL_ENCODE_START ) {
|
||||
return;
|
||||
}
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->bit = 0;
|
||||
msg->readcount = 0;
|
||||
msg->oob = 0;
|
||||
|
||||
serverId = MSG_ReadLong(msg);
|
||||
messageAcknowledge = MSG_ReadLong(msg);
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = (byte *)clc.serverCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
//
|
||||
key = clc.challenge ^ serverId ^ messageAcknowledge;
|
||||
for (i = CL_ENCODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last received now acknowledged server command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (string[index] > 127 || string[index] == '%') {
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// encode the data with this key
|
||||
*(msg->data + i) = (*(msg->data + i)) ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Decode
|
||||
|
||||
// first four bytes of the data are always:
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Decode( msg_t *msg ) {
|
||||
long reliableAcknowledge, i, index;
|
||||
byte key, *string;
|
||||
int srdc, sbit, soob;
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->oob = 0;
|
||||
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = clc.reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
// xor the client challenge with the netchan sequence number (need something that changes every message)
|
||||
key = clc.challenge ^ LittleLong( *(unsigned *)msg->data );
|
||||
for (i = msg->readcount + CL_DECODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last sent and with this message acknowledged client command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (string[index] > 127 || string[index] == '%') {
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// decode the data with this key
|
||||
*(msg->data + i) = *(msg->data + i) ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_TransmitNextFragment
|
||||
=================
|
||||
*/
|
||||
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
|
||||
Netchan_TransmitNextFragment( chan );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_Netchan_Transmit
|
||||
================
|
||||
*/
|
||||
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
|
||||
MSG_WriteByte( msg, clc_EOF );
|
||||
|
||||
CL_Netchan_Encode( msg );
|
||||
Netchan_Transmit( chan, msg->cursize, msg->data );
|
||||
}
|
||||
|
||||
extern int oldsize;
|
||||
int newsize = 0;
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_Process
|
||||
=================
|
||||
*/
|
||||
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||
int ret;
|
||||
|
||||
ret = Netchan_Process( chan, msg );
|
||||
if (!ret)
|
||||
return qfalse;
|
||||
CL_Netchan_Decode( msg );
|
||||
newsize += msg->cursize;
|
||||
return qtrue;
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "client.h"
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Encode
|
||||
|
||||
// first 12 bytes of the data are always:
|
||||
long serverId;
|
||||
long messageAcknowledge;
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Encode( msg_t *msg ) {
|
||||
int serverId, messageAcknowledge, reliableAcknowledge;
|
||||
int i, index, srdc, sbit, soob;
|
||||
byte key, *string;
|
||||
|
||||
if ( msg->cursize <= CL_ENCODE_START ) {
|
||||
return;
|
||||
}
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->bit = 0;
|
||||
msg->readcount = 0;
|
||||
msg->oob = 0;
|
||||
|
||||
serverId = MSG_ReadLong(msg);
|
||||
messageAcknowledge = MSG_ReadLong(msg);
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = (byte *)clc.serverCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
//
|
||||
key = clc.challenge ^ serverId ^ messageAcknowledge;
|
||||
for (i = CL_ENCODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last received now acknowledged server command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (string[index] > 127 || string[index] == '%') {
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// encode the data with this key
|
||||
*(msg->data + i) = (*(msg->data + i)) ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Decode
|
||||
|
||||
// first four bytes of the data are always:
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Decode( msg_t *msg ) {
|
||||
long reliableAcknowledge, i, index;
|
||||
byte key, *string;
|
||||
int srdc, sbit, soob;
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->oob = 0;
|
||||
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = clc.reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
// xor the client challenge with the netchan sequence number (need something that changes every message)
|
||||
key = clc.challenge ^ LittleLong( *(unsigned *)msg->data );
|
||||
for (i = msg->readcount + CL_DECODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last sent and with this message acknowledged client command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (string[index] > 127 || string[index] == '%') {
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// decode the data with this key
|
||||
*(msg->data + i) = *(msg->data + i) ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_TransmitNextFragment
|
||||
=================
|
||||
*/
|
||||
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
|
||||
Netchan_TransmitNextFragment( chan );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_Netchan_Transmit
|
||||
================
|
||||
*/
|
||||
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
|
||||
MSG_WriteByte( msg, clc_EOF );
|
||||
|
||||
CL_Netchan_Encode( msg );
|
||||
Netchan_Transmit( chan, msg->cursize, msg->data );
|
||||
}
|
||||
|
||||
extern int oldsize;
|
||||
int newsize = 0;
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_Process
|
||||
=================
|
||||
*/
|
||||
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||
int ret;
|
||||
|
||||
ret = Netchan_Process( chan, msg );
|
||||
if (!ret)
|
||||
return qfalse;
|
||||
CL_Netchan_Decode( msg );
|
||||
newsize += msg->cursize;
|
||||
return qtrue;
|
||||
}
|
||||
|
|
1310
code/client/cl_parse.c
Normal file → Executable file
1310
code/client/cl_parse.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1094
code/client/cl_scrn.c
Normal file → Executable file
1094
code/client/cl_scrn.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2400
code/client/cl_ui.c
Normal file → Executable file
2400
code/client/cl_ui.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1038
code/client/client.h
Normal file → Executable file
1038
code/client/client.h
Normal file → Executable file
File diff suppressed because it is too large
Load diff
114
code/client/keys.h
Normal file → Executable file
114
code/client/keys.h
Normal file → Executable file
|
@ -1,57 +1,57 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../ui/keycodes.h"
|
||||
|
||||
#define MAX_KEYS 256
|
||||
|
||||
typedef struct {
|
||||
qboolean down;
|
||||
int repeats; // if > 1, it is autorepeating
|
||||
char *binding;
|
||||
} qkey_t;
|
||||
|
||||
extern qboolean key_overstrikeMode;
|
||||
extern qkey_t keys[MAX_KEYS];
|
||||
|
||||
// NOTE TTimo the declaration of field_t and Field_Clear is now in qcommon/qcommon.h
|
||||
void Field_KeyDownEvent( field_t *edit, int key );
|
||||
void Field_CharEvent( field_t *edit, int ch );
|
||||
void Field_Draw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
void Field_BigDraw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
|
||||
#define COMMAND_HISTORY 32
|
||||
extern field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
extern field_t g_consoleField;
|
||||
extern field_t chatField;
|
||||
extern qboolean anykeydown;
|
||||
extern qboolean chat_team;
|
||||
extern int chat_playerNum;
|
||||
|
||||
void Key_WriteBindings( fileHandle_t f );
|
||||
void Key_SetBinding( int keynum, const char *binding );
|
||||
char *Key_GetBinding( int keynum );
|
||||
qboolean Key_IsDown( int keynum );
|
||||
qboolean Key_GetOverstrikeMode( void );
|
||||
void Key_SetOverstrikeMode( qboolean state );
|
||||
void Key_ClearStates( void );
|
||||
int Key_GetKey(const char *binding);
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../ui/keycodes.h"
|
||||
|
||||
#define MAX_KEYS 256
|
||||
|
||||
typedef struct {
|
||||
qboolean down;
|
||||
int repeats; // if > 1, it is autorepeating
|
||||
char *binding;
|
||||
} qkey_t;
|
||||
|
||||
extern qboolean key_overstrikeMode;
|
||||
extern qkey_t keys[MAX_KEYS];
|
||||
|
||||
// NOTE TTimo the declaration of field_t and Field_Clear is now in qcommon/qcommon.h
|
||||
void Field_KeyDownEvent( field_t *edit, int key );
|
||||
void Field_CharEvent( field_t *edit, int ch );
|
||||
void Field_Draw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
void Field_BigDraw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
|
||||
#define COMMAND_HISTORY 32
|
||||
extern field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
extern field_t g_consoleField;
|
||||
extern field_t chatField;
|
||||
extern qboolean anykeydown;
|
||||
extern qboolean chat_team;
|
||||
extern int chat_playerNum;
|
||||
|
||||
void Key_WriteBindings( fileHandle_t f );
|
||||
void Key_SetBinding( int keynum, const char *binding );
|
||||
char *Key_GetBinding( int keynum );
|
||||
qboolean Key_IsDown( int keynum );
|
||||
qboolean Key_GetOverstrikeMode( void );
|
||||
void Key_SetOverstrikeMode( qboolean state );
|
||||
void Key_ClearStates( void );
|
||||
int Key_GetKey(const char *binding);
|
||||
|
|
660
code/client/snd_adpcm.c
Normal file → Executable file
660
code/client/snd_adpcm.c
Normal file → Executable file
|
@ -1,330 +1,330 @@
|
|||
/***********************************************************
|
||||
Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
|
||||
Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
** Intel/DVI ADPCM coder/decoder.
|
||||
**
|
||||
** The algorithm for this coder was taken from the IMA Compatability Project
|
||||
** proceedings, Vol 2, Number 2; May 1992.
|
||||
**
|
||||
** Version 1.2, 18-Dec-92.
|
||||
*/
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
|
||||
/* Intel ADPCM step variation table */
|
||||
static int indexTable[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
};
|
||||
|
||||
static int stepsizeTable[89] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
|
||||
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
|
||||
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
|
||||
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
|
||||
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
||||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
|
||||
};
|
||||
|
||||
|
||||
void S_AdpcmEncode( short indata[], char outdata[], int len, struct adpcm_state *state ) {
|
||||
short *inp; /* Input buffer pointer */
|
||||
signed char *outp; /* output buffer pointer */
|
||||
int val; /* Current input sample value */
|
||||
int sign; /* Current adpcm sign bit */
|
||||
int delta; /* Current adpcm output value */
|
||||
int diff; /* Difference between val and sample */
|
||||
int step; /* Stepsize */
|
||||
int valpred; /* Predicted output value */
|
||||
int vpdiff; /* Current change to valpred */
|
||||
int index; /* Current step change index */
|
||||
int outputbuffer; /* place to keep previous 4-bit value */
|
||||
int bufferstep; /* toggle between outputbuffer/output */
|
||||
|
||||
outp = (signed char *)outdata;
|
||||
inp = indata;
|
||||
|
||||
valpred = state->sample;
|
||||
index = state->index;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
outputbuffer = 0; // quiet a compiler warning
|
||||
bufferstep = 1;
|
||||
|
||||
for ( ; len > 0 ; len-- ) {
|
||||
val = *inp++;
|
||||
|
||||
/* Step 1 - compute difference with previous value */
|
||||
diff = val - valpred;
|
||||
sign = (diff < 0) ? 8 : 0;
|
||||
if ( sign ) diff = (-diff);
|
||||
|
||||
/* Step 2 - Divide and clamp */
|
||||
/* Note:
|
||||
** This code *approximately* computes:
|
||||
** delta = diff*4/step;
|
||||
** vpdiff = (delta+0.5)*step/4;
|
||||
** but in shift step bits are dropped. The net result of this is
|
||||
** that even if you have fast mul/div hardware you cannot put it to
|
||||
** good use since the fixup would be too expensive.
|
||||
*/
|
||||
delta = 0;
|
||||
vpdiff = (step >> 3);
|
||||
|
||||
if ( diff >= step ) {
|
||||
delta = 4;
|
||||
diff -= step;
|
||||
vpdiff += step;
|
||||
}
|
||||
step >>= 1;
|
||||
if ( diff >= step ) {
|
||||
delta |= 2;
|
||||
diff -= step;
|
||||
vpdiff += step;
|
||||
}
|
||||
step >>= 1;
|
||||
if ( diff >= step ) {
|
||||
delta |= 1;
|
||||
vpdiff += step;
|
||||
}
|
||||
|
||||
/* Step 3 - Update previous value */
|
||||
if ( sign )
|
||||
valpred -= vpdiff;
|
||||
else
|
||||
valpred += vpdiff;
|
||||
|
||||
/* Step 4 - Clamp previous value to 16 bits */
|
||||
if ( valpred > 32767 )
|
||||
valpred = 32767;
|
||||
else if ( valpred < -32768 )
|
||||
valpred = -32768;
|
||||
|
||||
/* Step 5 - Assemble value, update index and step values */
|
||||
delta |= sign;
|
||||
|
||||
index += indexTable[delta];
|
||||
if ( index < 0 ) index = 0;
|
||||
if ( index > 88 ) index = 88;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
/* Step 6 - Output value */
|
||||
if ( bufferstep ) {
|
||||
outputbuffer = (delta << 4) & 0xf0;
|
||||
} else {
|
||||
*outp++ = (delta & 0x0f) | outputbuffer;
|
||||
}
|
||||
bufferstep = !bufferstep;
|
||||
}
|
||||
|
||||
/* Output last step, if needed */
|
||||
if ( !bufferstep )
|
||||
*outp++ = outputbuffer;
|
||||
|
||||
state->sample = valpred;
|
||||
state->index = index;
|
||||
}
|
||||
|
||||
|
||||
/* static */ void S_AdpcmDecode( const char indata[], short *outdata, int len, struct adpcm_state *state ) {
|
||||
signed char *inp; /* Input buffer pointer */
|
||||
int outp; /* output buffer pointer */
|
||||
int sign; /* Current adpcm sign bit */
|
||||
int delta; /* Current adpcm output value */
|
||||
int step; /* Stepsize */
|
||||
int valpred; /* Predicted value */
|
||||
int vpdiff; /* Current change to valpred */
|
||||
int index; /* Current step change index */
|
||||
int inputbuffer; /* place to keep next 4-bit value */
|
||||
int bufferstep; /* toggle between inputbuffer/input */
|
||||
|
||||
outp = 0;
|
||||
inp = (signed char *)indata;
|
||||
|
||||
valpred = state->sample;
|
||||
index = state->index;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
bufferstep = 0;
|
||||
inputbuffer = 0; // quiet a compiler warning
|
||||
for ( ; len > 0 ; len-- ) {
|
||||
|
||||
/* Step 1 - get the delta value */
|
||||
if ( bufferstep ) {
|
||||
delta = inputbuffer & 0xf;
|
||||
} else {
|
||||
inputbuffer = *inp++;
|
||||
delta = (inputbuffer >> 4) & 0xf;
|
||||
}
|
||||
bufferstep = !bufferstep;
|
||||
|
||||
/* Step 2 - Find new index value (for later) */
|
||||
index += indexTable[delta];
|
||||
if ( index < 0 ) index = 0;
|
||||
if ( index > 88 ) index = 88;
|
||||
|
||||
/* Step 3 - Separate sign and magnitude */
|
||||
sign = delta & 8;
|
||||
delta = delta & 7;
|
||||
|
||||
/* Step 4 - Compute difference and new predicted value */
|
||||
/*
|
||||
** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
|
||||
** in adpcm_coder.
|
||||
*/
|
||||
vpdiff = step >> 3;
|
||||
if ( delta & 4 ) vpdiff += step;
|
||||
if ( delta & 2 ) vpdiff += step>>1;
|
||||
if ( delta & 1 ) vpdiff += step>>2;
|
||||
|
||||
if ( sign )
|
||||
valpred -= vpdiff;
|
||||
else
|
||||
valpred += vpdiff;
|
||||
|
||||
/* Step 5 - clamp output value */
|
||||
if ( valpred > 32767 )
|
||||
valpred = 32767;
|
||||
else if ( valpred < -32768 )
|
||||
valpred = -32768;
|
||||
|
||||
/* Step 6 - Update step value */
|
||||
step = stepsizeTable[index];
|
||||
|
||||
/* Step 7 - Output value */
|
||||
outdata[outp] = valpred;
|
||||
outp++;
|
||||
}
|
||||
|
||||
state->sample = valpred;
|
||||
state->index = index;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmMemoryNeeded
|
||||
|
||||
Returns the amount of memory (in bytes) needed to store the samples in out internal adpcm format
|
||||
====================
|
||||
*/
|
||||
int S_AdpcmMemoryNeeded( const wavinfo_t *info ) {
|
||||
float scale;
|
||||
int scaledSampleCount;
|
||||
int sampleMemory;
|
||||
int blockCount;
|
||||
int headerMemory;
|
||||
|
||||
// determine scale to convert from input sampling rate to desired sampling rate
|
||||
scale = (float)info->rate / dma.speed;
|
||||
|
||||
// calc number of samples at playback sampling rate
|
||||
scaledSampleCount = info->samples / scale;
|
||||
|
||||
// calc memory need to store those samples using ADPCM at 4 bits per sample
|
||||
sampleMemory = scaledSampleCount / 2;
|
||||
|
||||
// calc number of sample blocks needed of PAINTBUFFER_SIZE
|
||||
blockCount = scaledSampleCount / PAINTBUFFER_SIZE;
|
||||
if( scaledSampleCount % PAINTBUFFER_SIZE ) {
|
||||
blockCount++;
|
||||
}
|
||||
|
||||
// calc memory needed to store the block headers
|
||||
headerMemory = blockCount * sizeof(adpcm_state_t);
|
||||
|
||||
return sampleMemory + headerMemory;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmGetSamples
|
||||
====================
|
||||
*/
|
||||
void S_AdpcmGetSamples(sndBuffer *chunk, short *to) {
|
||||
adpcm_state_t state;
|
||||
byte *out;
|
||||
|
||||
// get the starting state from the block header
|
||||
state.index = chunk->adpcm.index;
|
||||
state.sample = chunk->adpcm.sample;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
// get samples
|
||||
S_AdpcmDecode( out, to, SND_CHUNK_SIZE_BYTE*2, &state );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmEncodeSound
|
||||
====================
|
||||
*/
|
||||
void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
|
||||
adpcm_state_t state;
|
||||
int inOffset;
|
||||
int count;
|
||||
int n;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
inOffset = 0;
|
||||
count = sfx->soundLength;
|
||||
state.index = 0;
|
||||
state.sample = samples[0];
|
||||
|
||||
chunk = NULL;
|
||||
while( count ) {
|
||||
n = count;
|
||||
if( n > SND_CHUNK_SIZE_BYTE*2 ) {
|
||||
n = SND_CHUNK_SIZE_BYTE*2;
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
|
||||
// output the header
|
||||
chunk->adpcm.index = state.index;
|
||||
chunk->adpcm.sample = state.sample;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
|
||||
// encode the samples
|
||||
S_AdpcmEncode( samples + inOffset, out, n, &state );
|
||||
|
||||
inOffset += n;
|
||||
count -= n;
|
||||
}
|
||||
}
|
||||
/***********************************************************
|
||||
Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
|
||||
Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
** Intel/DVI ADPCM coder/decoder.
|
||||
**
|
||||
** The algorithm for this coder was taken from the IMA Compatability Project
|
||||
** proceedings, Vol 2, Number 2; May 1992.
|
||||
**
|
||||
** Version 1.2, 18-Dec-92.
|
||||
*/
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
|
||||
/* Intel ADPCM step variation table */
|
||||
static int indexTable[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
};
|
||||
|
||||
static int stepsizeTable[89] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
|
||||
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
|
||||
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
|
||||
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
|
||||
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
||||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
|
||||
};
|
||||
|
||||
|
||||
void S_AdpcmEncode( short indata[], char outdata[], int len, struct adpcm_state *state ) {
|
||||
short *inp; /* Input buffer pointer */
|
||||
signed char *outp; /* output buffer pointer */
|
||||
int val; /* Current input sample value */
|
||||
int sign; /* Current adpcm sign bit */
|
||||
int delta; /* Current adpcm output value */
|
||||
int diff; /* Difference between val and sample */
|
||||
int step; /* Stepsize */
|
||||
int valpred; /* Predicted output value */
|
||||
int vpdiff; /* Current change to valpred */
|
||||
int index; /* Current step change index */
|
||||
int outputbuffer; /* place to keep previous 4-bit value */
|
||||
int bufferstep; /* toggle between outputbuffer/output */
|
||||
|
||||
outp = (signed char *)outdata;
|
||||
inp = indata;
|
||||
|
||||
valpred = state->sample;
|
||||
index = state->index;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
outputbuffer = 0; // quiet a compiler warning
|
||||
bufferstep = 1;
|
||||
|
||||
for ( ; len > 0 ; len-- ) {
|
||||
val = *inp++;
|
||||
|
||||
/* Step 1 - compute difference with previous value */
|
||||
diff = val - valpred;
|
||||
sign = (diff < 0) ? 8 : 0;
|
||||
if ( sign ) diff = (-diff);
|
||||
|
||||
/* Step 2 - Divide and clamp */
|
||||
/* Note:
|
||||
** This code *approximately* computes:
|
||||
** delta = diff*4/step;
|
||||
** vpdiff = (delta+0.5)*step/4;
|
||||
** but in shift step bits are dropped. The net result of this is
|
||||
** that even if you have fast mul/div hardware you cannot put it to
|
||||
** good use since the fixup would be too expensive.
|
||||
*/
|
||||
delta = 0;
|
||||
vpdiff = (step >> 3);
|
||||
|
||||
if ( diff >= step ) {
|
||||
delta = 4;
|
||||
diff -= step;
|
||||
vpdiff += step;
|
||||
}
|
||||
step >>= 1;
|
||||
if ( diff >= step ) {
|
||||
delta |= 2;
|
||||
diff -= step;
|
||||
vpdiff += step;
|
||||
}
|
||||
step >>= 1;
|
||||
if ( diff >= step ) {
|
||||
delta |= 1;
|
||||
vpdiff += step;
|
||||
}
|
||||
|
||||
/* Step 3 - Update previous value */
|
||||
if ( sign )
|
||||
valpred -= vpdiff;
|
||||
else
|
||||
valpred += vpdiff;
|
||||
|
||||
/* Step 4 - Clamp previous value to 16 bits */
|
||||
if ( valpred > 32767 )
|
||||
valpred = 32767;
|
||||
else if ( valpred < -32768 )
|
||||
valpred = -32768;
|
||||
|
||||
/* Step 5 - Assemble value, update index and step values */
|
||||
delta |= sign;
|
||||
|
||||
index += indexTable[delta];
|
||||
if ( index < 0 ) index = 0;
|
||||
if ( index > 88 ) index = 88;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
/* Step 6 - Output value */
|
||||
if ( bufferstep ) {
|
||||
outputbuffer = (delta << 4) & 0xf0;
|
||||
} else {
|
||||
*outp++ = (delta & 0x0f) | outputbuffer;
|
||||
}
|
||||
bufferstep = !bufferstep;
|
||||
}
|
||||
|
||||
/* Output last step, if needed */
|
||||
if ( !bufferstep )
|
||||
*outp++ = outputbuffer;
|
||||
|
||||
state->sample = valpred;
|
||||
state->index = index;
|
||||
}
|
||||
|
||||
|
||||
/* static */ void S_AdpcmDecode( const char indata[], short *outdata, int len, struct adpcm_state *state ) {
|
||||
signed char *inp; /* Input buffer pointer */
|
||||
int outp; /* output buffer pointer */
|
||||
int sign; /* Current adpcm sign bit */
|
||||
int delta; /* Current adpcm output value */
|
||||
int step; /* Stepsize */
|
||||
int valpred; /* Predicted value */
|
||||
int vpdiff; /* Current change to valpred */
|
||||
int index; /* Current step change index */
|
||||
int inputbuffer; /* place to keep next 4-bit value */
|
||||
int bufferstep; /* toggle between inputbuffer/input */
|
||||
|
||||
outp = 0;
|
||||
inp = (signed char *)indata;
|
||||
|
||||
valpred = state->sample;
|
||||
index = state->index;
|
||||
step = stepsizeTable[index];
|
||||
|
||||
bufferstep = 0;
|
||||
inputbuffer = 0; // quiet a compiler warning
|
||||
for ( ; len > 0 ; len-- ) {
|
||||
|
||||
/* Step 1 - get the delta value */
|
||||
if ( bufferstep ) {
|
||||
delta = inputbuffer & 0xf;
|
||||
} else {
|
||||
inputbuffer = *inp++;
|
||||
delta = (inputbuffer >> 4) & 0xf;
|
||||
}
|
||||
bufferstep = !bufferstep;
|
||||
|
||||
/* Step 2 - Find new index value (for later) */
|
||||
index += indexTable[delta];
|
||||
if ( index < 0 ) index = 0;
|
||||
if ( index > 88 ) index = 88;
|
||||
|
||||
/* Step 3 - Separate sign and magnitude */
|
||||
sign = delta & 8;
|
||||
delta = delta & 7;
|
||||
|
||||
/* Step 4 - Compute difference and new predicted value */
|
||||
/*
|
||||
** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
|
||||
** in adpcm_coder.
|
||||
*/
|
||||
vpdiff = step >> 3;
|
||||
if ( delta & 4 ) vpdiff += step;
|
||||
if ( delta & 2 ) vpdiff += step>>1;
|
||||
if ( delta & 1 ) vpdiff += step>>2;
|
||||
|
||||
if ( sign )
|
||||
valpred -= vpdiff;
|
||||
else
|
||||
valpred += vpdiff;
|
||||
|
||||
/* Step 5 - clamp output value */
|
||||
if ( valpred > 32767 )
|
||||
valpred = 32767;
|
||||
else if ( valpred < -32768 )
|
||||
valpred = -32768;
|
||||
|
||||
/* Step 6 - Update step value */
|
||||
step = stepsizeTable[index];
|
||||
|
||||
/* Step 7 - Output value */
|
||||
outdata[outp] = valpred;
|
||||
outp++;
|
||||
}
|
||||
|
||||
state->sample = valpred;
|
||||
state->index = index;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmMemoryNeeded
|
||||
|
||||
Returns the amount of memory (in bytes) needed to store the samples in out internal adpcm format
|
||||
====================
|
||||
*/
|
||||
int S_AdpcmMemoryNeeded( const wavinfo_t *info ) {
|
||||
float scale;
|
||||
int scaledSampleCount;
|
||||
int sampleMemory;
|
||||
int blockCount;
|
||||
int headerMemory;
|
||||
|
||||
// determine scale to convert from input sampling rate to desired sampling rate
|
||||
scale = (float)info->rate / dma.speed;
|
||||
|
||||
// calc number of samples at playback sampling rate
|
||||
scaledSampleCount = info->samples / scale;
|
||||
|
||||
// calc memory need to store those samples using ADPCM at 4 bits per sample
|
||||
sampleMemory = scaledSampleCount / 2;
|
||||
|
||||
// calc number of sample blocks needed of PAINTBUFFER_SIZE
|
||||
blockCount = scaledSampleCount / PAINTBUFFER_SIZE;
|
||||
if( scaledSampleCount % PAINTBUFFER_SIZE ) {
|
||||
blockCount++;
|
||||
}
|
||||
|
||||
// calc memory needed to store the block headers
|
||||
headerMemory = blockCount * sizeof(adpcm_state_t);
|
||||
|
||||
return sampleMemory + headerMemory;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmGetSamples
|
||||
====================
|
||||
*/
|
||||
void S_AdpcmGetSamples(sndBuffer *chunk, short *to) {
|
||||
adpcm_state_t state;
|
||||
byte *out;
|
||||
|
||||
// get the starting state from the block header
|
||||
state.index = chunk->adpcm.index;
|
||||
state.sample = chunk->adpcm.sample;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
// get samples
|
||||
S_AdpcmDecode( out, to, SND_CHUNK_SIZE_BYTE*2, &state );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
S_AdpcmEncodeSound
|
||||
====================
|
||||
*/
|
||||
void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
|
||||
adpcm_state_t state;
|
||||
int inOffset;
|
||||
int count;
|
||||
int n;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
inOffset = 0;
|
||||
count = sfx->soundLength;
|
||||
state.index = 0;
|
||||
state.sample = samples[0];
|
||||
|
||||
chunk = NULL;
|
||||
while( count ) {
|
||||
n = count;
|
||||
if( n > SND_CHUNK_SIZE_BYTE*2 ) {
|
||||
n = SND_CHUNK_SIZE_BYTE*2;
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
|
||||
// output the header
|
||||
chunk->adpcm.index = state.index;
|
||||
chunk->adpcm.sample = state.sample;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
|
||||
// encode the samples
|
||||
S_AdpcmEncode( samples + inOffset, out, n, &state );
|
||||
|
||||
inOffset += n;
|
||||
count -= n;
|
||||
}
|
||||
}
|
||||
|
|
3272
code/client/snd_dma.c
Normal file → Executable file
3272
code/client/snd_dma.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
408
code/client/snd_local.h
Normal file → Executable file
408
code/client/snd_local.h
Normal file → Executable file
|
@ -1,204 +1,204 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "snd_public.h"
|
||||
|
||||
#define PAINTBUFFER_SIZE 4096 // this is in samples
|
||||
|
||||
#define SND_CHUNK_SIZE 1024 // samples
|
||||
#define SND_CHUNK_SIZE_FLOAT (SND_CHUNK_SIZE/2) // floats
|
||||
#define SND_CHUNK_SIZE_BYTE (SND_CHUNK_SIZE*2) // floats
|
||||
|
||||
typedef struct {
|
||||
int left; // the final values will be clamped to +/- 0x00ffff00 and shifted down
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
typedef struct adpcm_state {
|
||||
short sample; /* Previous output value */
|
||||
char index; /* Index into stepsize table */
|
||||
} adpcm_state_t;
|
||||
|
||||
typedef struct sndBuffer_s {
|
||||
short sndChunk[SND_CHUNK_SIZE];
|
||||
struct sndBuffer_s *next;
|
||||
int size;
|
||||
adpcm_state_t adpcm;
|
||||
} sndBuffer;
|
||||
|
||||
typedef struct sfx_s {
|
||||
sndBuffer *soundData;
|
||||
qboolean defaultSound; // couldn't be loaded, so use buzz
|
||||
qboolean inMemory; // not in Memory
|
||||
qboolean soundCompressed; // not in Memory
|
||||
int soundCompressionMethod;
|
||||
int soundLength;
|
||||
char soundName[MAX_QPATH];
|
||||
int lastTimeUsed;
|
||||
struct sfx_s *next;
|
||||
} sfx_t;
|
||||
|
||||
typedef struct {
|
||||
int channels;
|
||||
int samples; // mono samples in buffer
|
||||
int submission_chunk; // don't mix less than this #
|
||||
int samplebits;
|
||||
int speed;
|
||||
byte *buffer;
|
||||
} dma_t;
|
||||
|
||||
#define START_SAMPLE_IMMEDIATE 0x7fffffff
|
||||
|
||||
typedef struct loopSound_s {
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
sfx_t *sfx;
|
||||
int mergeFrame;
|
||||
qboolean active;
|
||||
qboolean kill;
|
||||
qboolean doppler;
|
||||
float dopplerScale;
|
||||
float oldDopplerScale;
|
||||
int framenum;
|
||||
} loopSound_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int allocTime;
|
||||
int startSample; // START_SAMPLE_IMMEDIATE = set immediately on next mix
|
||||
int entnum; // to allow overriding a specific sound
|
||||
int entchannel; // to allow overriding a specific sound
|
||||
int leftvol; // 0-255 volume after spatialization
|
||||
int rightvol; // 0-255 volume after spatialization
|
||||
int master_vol; // 0-255 volume before spatialization
|
||||
float dopplerScale;
|
||||
float oldDopplerScale;
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
qboolean fixed_origin; // use origin instead of fetching entnum's origin
|
||||
sfx_t *thesfx; // sfx structure
|
||||
qboolean doppler;
|
||||
} channel_t;
|
||||
|
||||
|
||||
#define WAV_FORMAT_PCM 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
int format;
|
||||
int rate;
|
||||
int width;
|
||||
int channels;
|
||||
int samples;
|
||||
int dataofs; // chunk starts this many bytes from file start
|
||||
} wavinfo_t;
|
||||
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
SYSTEM SPECIFIC FUNCTIONS
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
// initializes cycling through a DMA buffer and returns information on it
|
||||
qboolean SNDDMA_Init(void);
|
||||
|
||||
// gets the current DMA position
|
||||
int SNDDMA_GetDMAPos(void);
|
||||
|
||||
// shutdown the DMA xfer.
|
||||
void SNDDMA_Shutdown(void);
|
||||
|
||||
void SNDDMA_BeginPainting (void);
|
||||
|
||||
void SNDDMA_Submit(void);
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_CHANNELS 96
|
||||
|
||||
extern channel_t s_channels[MAX_CHANNELS];
|
||||
extern channel_t loop_channels[MAX_CHANNELS];
|
||||
extern int numLoopChannels;
|
||||
|
||||
extern int s_paintedtime;
|
||||
extern int s_rawend;
|
||||
extern vec3_t listener_forward;
|
||||
extern vec3_t listener_right;
|
||||
extern vec3_t listener_up;
|
||||
extern dma_t dma;
|
||||
|
||||
#define MAX_RAW_SAMPLES 16384
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
|
||||
extern cvar_t *s_volume;
|
||||
extern cvar_t *s_nosound;
|
||||
extern cvar_t *s_khz;
|
||||
extern cvar_t *s_show;
|
||||
extern cvar_t *s_mixahead;
|
||||
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_separation;
|
||||
|
||||
qboolean S_LoadSound( sfx_t *sfx );
|
||||
|
||||
void SND_free(sndBuffer *v);
|
||||
sndBuffer* SND_malloc();
|
||||
void SND_setup();
|
||||
|
||||
void S_PaintChannels(int endtime);
|
||||
|
||||
void S_memoryLoad(sfx_t *sfx);
|
||||
portable_samplepair_t *S_GetRawSamplePointer();
|
||||
|
||||
// spatializes a channel
|
||||
void S_Spatialize(channel_t *ch);
|
||||
|
||||
// adpcm functions
|
||||
int S_AdpcmMemoryNeeded( const wavinfo_t *info );
|
||||
void S_AdpcmEncodeSound( sfx_t *sfx, short *samples );
|
||||
void S_AdpcmGetSamples(sndBuffer *chunk, short *to);
|
||||
|
||||
// wavelet function
|
||||
|
||||
#define SENTINEL_MULAW_ZERO_RUN 127
|
||||
#define SENTINEL_MULAW_FOUR_BIT_RUN 126
|
||||
|
||||
void S_FreeOldestSound();
|
||||
|
||||
#define NXStream byte
|
||||
|
||||
void encodeWavelet(sfx_t *sfx, short *packets);
|
||||
void decodeWavelet( sndBuffer *stream, short *packets);
|
||||
|
||||
void encodeMuLaw( sfx_t *sfx, short *packets);
|
||||
extern short mulawToShort[256];
|
||||
|
||||
extern short *sfxScratchBuffer;
|
||||
extern sfx_t *sfxScratchPointer;
|
||||
extern int sfxScratchIndex;
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "snd_public.h"
|
||||
|
||||
#define PAINTBUFFER_SIZE 4096 // this is in samples
|
||||
|
||||
#define SND_CHUNK_SIZE 1024 // samples
|
||||
#define SND_CHUNK_SIZE_FLOAT (SND_CHUNK_SIZE/2) // floats
|
||||
#define SND_CHUNK_SIZE_BYTE (SND_CHUNK_SIZE*2) // floats
|
||||
|
||||
typedef struct {
|
||||
int left; // the final values will be clamped to +/- 0x00ffff00 and shifted down
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
typedef struct adpcm_state {
|
||||
short sample; /* Previous output value */
|
||||
char index; /* Index into stepsize table */
|
||||
} adpcm_state_t;
|
||||
|
||||
typedef struct sndBuffer_s {
|
||||
short sndChunk[SND_CHUNK_SIZE];
|
||||
struct sndBuffer_s *next;
|
||||
int size;
|
||||
adpcm_state_t adpcm;
|
||||
} sndBuffer;
|
||||
|
||||
typedef struct sfx_s {
|
||||
sndBuffer *soundData;
|
||||
qboolean defaultSound; // couldn't be loaded, so use buzz
|
||||
qboolean inMemory; // not in Memory
|
||||
qboolean soundCompressed; // not in Memory
|
||||
int soundCompressionMethod;
|
||||
int soundLength;
|
||||
char soundName[MAX_QPATH];
|
||||
int lastTimeUsed;
|
||||
struct sfx_s *next;
|
||||
} sfx_t;
|
||||
|
||||
typedef struct {
|
||||
int channels;
|
||||
int samples; // mono samples in buffer
|
||||
int submission_chunk; // don't mix less than this #
|
||||
int samplebits;
|
||||
int speed;
|
||||
byte *buffer;
|
||||
} dma_t;
|
||||
|
||||
#define START_SAMPLE_IMMEDIATE 0x7fffffff
|
||||
|
||||
typedef struct loopSound_s {
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
sfx_t *sfx;
|
||||
int mergeFrame;
|
||||
qboolean active;
|
||||
qboolean kill;
|
||||
qboolean doppler;
|
||||
float dopplerScale;
|
||||
float oldDopplerScale;
|
||||
int framenum;
|
||||
} loopSound_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int allocTime;
|
||||
int startSample; // START_SAMPLE_IMMEDIATE = set immediately on next mix
|
||||
int entnum; // to allow overriding a specific sound
|
||||
int entchannel; // to allow overriding a specific sound
|
||||
int leftvol; // 0-255 volume after spatialization
|
||||
int rightvol; // 0-255 volume after spatialization
|
||||
int master_vol; // 0-255 volume before spatialization
|
||||
float dopplerScale;
|
||||
float oldDopplerScale;
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
qboolean fixed_origin; // use origin instead of fetching entnum's origin
|
||||
sfx_t *thesfx; // sfx structure
|
||||
qboolean doppler;
|
||||
} channel_t;
|
||||
|
||||
|
||||
#define WAV_FORMAT_PCM 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
int format;
|
||||
int rate;
|
||||
int width;
|
||||
int channels;
|
||||
int samples;
|
||||
int dataofs; // chunk starts this many bytes from file start
|
||||
} wavinfo_t;
|
||||
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
SYSTEM SPECIFIC FUNCTIONS
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
// initializes cycling through a DMA buffer and returns information on it
|
||||
qboolean SNDDMA_Init(void);
|
||||
|
||||
// gets the current DMA position
|
||||
int SNDDMA_GetDMAPos(void);
|
||||
|
||||
// shutdown the DMA xfer.
|
||||
void SNDDMA_Shutdown(void);
|
||||
|
||||
void SNDDMA_BeginPainting (void);
|
||||
|
||||
void SNDDMA_Submit(void);
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_CHANNELS 96
|
||||
|
||||
extern channel_t s_channels[MAX_CHANNELS];
|
||||
extern channel_t loop_channels[MAX_CHANNELS];
|
||||
extern int numLoopChannels;
|
||||
|
||||
extern int s_paintedtime;
|
||||
extern int s_rawend;
|
||||
extern vec3_t listener_forward;
|
||||
extern vec3_t listener_right;
|
||||
extern vec3_t listener_up;
|
||||
extern dma_t dma;
|
||||
|
||||
#define MAX_RAW_SAMPLES 16384
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
|
||||
extern cvar_t *s_volume;
|
||||
extern cvar_t *s_nosound;
|
||||
extern cvar_t *s_khz;
|
||||
extern cvar_t *s_show;
|
||||
extern cvar_t *s_mixahead;
|
||||
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_separation;
|
||||
|
||||
qboolean S_LoadSound( sfx_t *sfx );
|
||||
|
||||
void SND_free(sndBuffer *v);
|
||||
sndBuffer* SND_malloc();
|
||||
void SND_setup();
|
||||
|
||||
void S_PaintChannels(int endtime);
|
||||
|
||||
void S_memoryLoad(sfx_t *sfx);
|
||||
portable_samplepair_t *S_GetRawSamplePointer();
|
||||
|
||||
// spatializes a channel
|
||||
void S_Spatialize(channel_t *ch);
|
||||
|
||||
// adpcm functions
|
||||
int S_AdpcmMemoryNeeded( const wavinfo_t *info );
|
||||
void S_AdpcmEncodeSound( sfx_t *sfx, short *samples );
|
||||
void S_AdpcmGetSamples(sndBuffer *chunk, short *to);
|
||||
|
||||
// wavelet function
|
||||
|
||||
#define SENTINEL_MULAW_ZERO_RUN 127
|
||||
#define SENTINEL_MULAW_FOUR_BIT_RUN 126
|
||||
|
||||
void S_FreeOldestSound();
|
||||
|
||||
#define NXStream byte
|
||||
|
||||
void encodeWavelet(sfx_t *sfx, short *packets);
|
||||
void decodeWavelet( sndBuffer *stream, short *packets);
|
||||
|
||||
void encodeMuLaw( sfx_t *sfx, short *packets);
|
||||
extern short mulawToShort[256];
|
||||
|
||||
extern short *sfxScratchBuffer;
|
||||
extern sfx_t *sfxScratchPointer;
|
||||
extern int sfxScratchIndex;
|
||||
|
||||
|
|
808
code/client/snd_mem.c
Normal file → Executable file
808
code/client/snd_mem.c
Normal file → Executable file
|
@ -1,404 +1,404 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; 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"
|
||||
|
||||
#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() {
|
||||
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() {
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
WAV loading
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static byte *data_p;
|
||||
static byte *iff_end;
|
||||
static byte *last_chunk;
|
||||
static byte *iff_data;
|
||||
static int iff_chunk_len;
|
||||
|
||||
static short GetLittleShort(void)
|
||||
{
|
||||
short val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
data_p += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int GetLittleLong(void)
|
||||
{
|
||||
int val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
val = val + (*(data_p+2)<<16);
|
||||
val = val + (*(data_p+3)<<24);
|
||||
data_p += 4;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void FindNextChunk(char *name)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
data_p=last_chunk;
|
||||
|
||||
if (data_p >= iff_end)
|
||||
{ // didn't find the chunk
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
iff_chunk_len = GetLittleLong();
|
||||
if (iff_chunk_len < 0)
|
||||
{
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
data_p -= 8;
|
||||
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
|
||||
if (!strncmp((char *)data_p, name, 4))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void FindChunk(char *name)
|
||||
{
|
||||
last_chunk = iff_data;
|
||||
FindNextChunk (name);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
GetWavinfo
|
||||
============
|
||||
*/
|
||||
static wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
|
||||
{
|
||||
wavinfo_t info;
|
||||
|
||||
Com_Memset (&info, 0, sizeof(info));
|
||||
|
||||
if (!wav)
|
||||
return info;
|
||||
|
||||
iff_data = wav;
|
||||
iff_end = wav + wavlength;
|
||||
|
||||
// find "RIFF" chunk
|
||||
FindChunk("RIFF");
|
||||
if (!(data_p && !strncmp((char *)data_p+8, "WAVE", 4)))
|
||||
{
|
||||
Com_Printf("Missing RIFF/WAVE chunks\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
// get "fmt " chunk
|
||||
iff_data = data_p + 12;
|
||||
// DumpChunks ();
|
||||
|
||||
FindChunk("fmt ");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing fmt chunk\n");
|
||||
return info;
|
||||
}
|
||||
data_p += 8;
|
||||
info.format = GetLittleShort();
|
||||
info.channels = GetLittleShort();
|
||||
info.rate = GetLittleLong();
|
||||
data_p += 4+2;
|
||||
info.width = GetLittleShort() / 8;
|
||||
|
||||
if (info.format != 1)
|
||||
{
|
||||
Com_Printf("Microsoft PCM format only\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
// find data chunk
|
||||
FindChunk("data");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing data chunk\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
info.samples = GetLittleLong () / info.width;
|
||||
info.dataofs = data_p - wav;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
ResampleSfx
|
||||
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) {
|
||||
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 = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
part = (i&(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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ResampleSfx
|
||||
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) {
|
||||
int outcount;
|
||||
int srcsample;
|
||||
float stepscale;
|
||||
int i;
|
||||
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;
|
||||
|
||||
for (i=0 ; i<outcount ; i++)
|
||||
{
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
if( inwidth == 2 ) {
|
||||
sample = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
sfx[i] = 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;
|
||||
wavinfo_t info;
|
||||
int size;
|
||||
|
||||
// player specific sounds are never directly loaded
|
||||
if ( sfx->soundName[0] == '*') {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// load it in
|
||||
size = FS_ReadFile( sfx->soundName, (void **)&data );
|
||||
if ( !data ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
info = GetWavinfo( sfx->soundName, data, size );
|
||||
if ( info.channels != 1 ) {
|
||||
Com_Printf ("%s is a stereo wav file\n", sfx->soundName);
|
||||
FS_FreeFile (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);
|
||||
}
|
||||
|
||||
samples = Hunk_AllocateTempMemory(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( sfx->soundCompressed == qtrue) {
|
||||
sfx->soundCompressionMethod = 1;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
S_AdpcmEncodeSound(sfx, samples);
|
||||
#if 0
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 3;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeMuLaw( sfx, samples);
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 2;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeWavelet( sfx, samples);
|
||||
#endif
|
||||
} else {
|
||||
sfx->soundCompressionMethod = 0;
|
||||
sfx->soundLength = info.samples;
|
||||
sfx->soundData = NULL;
|
||||
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse );
|
||||
}
|
||||
|
||||
Hunk_FreeTempMemory(samples);
|
||||
FS_FreeFile( data );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
void S_DisplayFreeMemory() {
|
||||
Com_Printf("%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse);
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; 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"
|
||||
|
||||
#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() {
|
||||
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() {
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
WAV loading
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static byte *data_p;
|
||||
static byte *iff_end;
|
||||
static byte *last_chunk;
|
||||
static byte *iff_data;
|
||||
static int iff_chunk_len;
|
||||
|
||||
static short GetLittleShort(void)
|
||||
{
|
||||
short val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
data_p += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int GetLittleLong(void)
|
||||
{
|
||||
int val = 0;
|
||||
val = *data_p;
|
||||
val = val + (*(data_p+1)<<8);
|
||||
val = val + (*(data_p+2)<<16);
|
||||
val = val + (*(data_p+3)<<24);
|
||||
data_p += 4;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void FindNextChunk(char *name)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
data_p=last_chunk;
|
||||
|
||||
if (data_p >= iff_end)
|
||||
{ // didn't find the chunk
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
iff_chunk_len = GetLittleLong();
|
||||
if (iff_chunk_len < 0)
|
||||
{
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
data_p -= 8;
|
||||
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
|
||||
if (!strncmp((char *)data_p, name, 4))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void FindChunk(char *name)
|
||||
{
|
||||
last_chunk = iff_data;
|
||||
FindNextChunk (name);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
GetWavinfo
|
||||
============
|
||||
*/
|
||||
static wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
|
||||
{
|
||||
wavinfo_t info;
|
||||
|
||||
Com_Memset (&info, 0, sizeof(info));
|
||||
|
||||
if (!wav)
|
||||
return info;
|
||||
|
||||
iff_data = wav;
|
||||
iff_end = wav + wavlength;
|
||||
|
||||
// find "RIFF" chunk
|
||||
FindChunk("RIFF");
|
||||
if (!(data_p && !strncmp((char *)data_p+8, "WAVE", 4)))
|
||||
{
|
||||
Com_Printf("Missing RIFF/WAVE chunks\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
// get "fmt " chunk
|
||||
iff_data = data_p + 12;
|
||||
// DumpChunks ();
|
||||
|
||||
FindChunk("fmt ");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing fmt chunk\n");
|
||||
return info;
|
||||
}
|
||||
data_p += 8;
|
||||
info.format = GetLittleShort();
|
||||
info.channels = GetLittleShort();
|
||||
info.rate = GetLittleLong();
|
||||
data_p += 4+2;
|
||||
info.width = GetLittleShort() / 8;
|
||||
|
||||
if (info.format != 1)
|
||||
{
|
||||
Com_Printf("Microsoft PCM format only\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
// find data chunk
|
||||
FindChunk("data");
|
||||
if (!data_p)
|
||||
{
|
||||
Com_Printf("Missing data chunk\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
info.samples = GetLittleLong () / info.width;
|
||||
info.dataofs = data_p - wav;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
ResampleSfx
|
||||
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) {
|
||||
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 = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
part = (i&(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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ResampleSfx
|
||||
|
||||
resample / decimate to the current source rate
|
||||
================
|
||||
*/
|
||||
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) {
|
||||
int outcount;
|
||||
int srcsample;
|
||||
float stepscale;
|
||||
int i;
|
||||
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;
|
||||
|
||||
for (i=0 ; i<outcount ; i++)
|
||||
{
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
if( inwidth == 2 ) {
|
||||
sample = LittleShort ( ((short *)data)[srcsample] );
|
||||
} else {
|
||||
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
|
||||
}
|
||||
sfx[i] = 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;
|
||||
wavinfo_t info;
|
||||
int size;
|
||||
|
||||
// player specific sounds are never directly loaded
|
||||
if ( sfx->soundName[0] == '*') {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// load it in
|
||||
size = FS_ReadFile( sfx->soundName, (void **)&data );
|
||||
if ( !data ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
info = GetWavinfo( sfx->soundName, data, size );
|
||||
if ( info.channels != 1 ) {
|
||||
Com_Printf ("%s is a stereo wav file\n", sfx->soundName);
|
||||
FS_FreeFile (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);
|
||||
}
|
||||
|
||||
samples = Hunk_AllocateTempMemory(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( sfx->soundCompressed == qtrue) {
|
||||
sfx->soundCompressionMethod = 1;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
S_AdpcmEncodeSound(sfx, samples);
|
||||
#if 0
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 3;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeMuLaw( sfx, samples);
|
||||
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
|
||||
sfx->soundCompressionMethod = 2;
|
||||
sfx->soundData = NULL;
|
||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
||||
encodeWavelet( sfx, samples);
|
||||
#endif
|
||||
} else {
|
||||
sfx->soundCompressionMethod = 0;
|
||||
sfx->soundLength = info.samples;
|
||||
sfx->soundData = NULL;
|
||||
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse );
|
||||
}
|
||||
|
||||
Hunk_FreeTempMemory(samples);
|
||||
FS_FreeFile( data );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
void S_DisplayFreeMemory() {
|
||||
Com_Printf("%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse);
|
||||
}
|
||||
|
|
1362
code/client/snd_mix.c
Normal file → Executable file
1362
code/client/snd_mix.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
144
code/client/snd_public.h
Normal file → Executable file
144
code/client/snd_public.h
Normal file → Executable file
|
@ -1,72 +1,72 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
void S_Init( void );
|
||||
void S_Shutdown( void );
|
||||
|
||||
// if origin is NULL, the sound will be dynamically sourced from the entity
|
||||
void S_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx );
|
||||
void S_StartLocalSound( sfxHandle_t sfx, int channelNum );
|
||||
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop );
|
||||
void S_StopBackgroundTrack( void );
|
||||
|
||||
// cinematics and voice-over-network will send raw samples
|
||||
// 1.0 volume will be direct output of source samples
|
||||
void S_RawSamples (int samples, int rate, int width, int channels,
|
||||
const byte *data, float volume);
|
||||
|
||||
// stop all sounds and the background track
|
||||
void S_StopAllSounds( void );
|
||||
|
||||
// all continuous looping sounds must be added before calling S_Update
|
||||
void S_ClearLoopingSounds( qboolean killall );
|
||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void S_StopLoopingSound(int entityNum );
|
||||
|
||||
// recompute the reletive volumes for all running sounds
|
||||
// reletive to the given entityNum / orientation
|
||||
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
||||
|
||||
// let the sound system know where an entity currently is
|
||||
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
|
||||
|
||||
void S_Update( void );
|
||||
|
||||
void S_DisableSounds( void );
|
||||
|
||||
void S_BeginRegistration( void );
|
||||
|
||||
// RegisterSound will allways return a valid sample, even if it
|
||||
// has to create a placeholder. This prevents continuous filesystem
|
||||
// checks for missing files
|
||||
sfxHandle_t S_RegisterSound( const char *sample, qboolean compressed );
|
||||
|
||||
void S_DisplayFreeMemory(void);
|
||||
|
||||
void S_ClearSoundBuffer( void );
|
||||
|
||||
void SNDDMA_Activate( void );
|
||||
|
||||
void S_UpdateBackgroundTrack( void );
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
void S_Init( void );
|
||||
void S_Shutdown( void );
|
||||
|
||||
// if origin is NULL, the sound will be dynamically sourced from the entity
|
||||
void S_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx );
|
||||
void S_StartLocalSound( sfxHandle_t sfx, int channelNum );
|
||||
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop );
|
||||
void S_StopBackgroundTrack( void );
|
||||
|
||||
// cinematics and voice-over-network will send raw samples
|
||||
// 1.0 volume will be direct output of source samples
|
||||
void S_RawSamples (int samples, int rate, int width, int channels,
|
||||
const byte *data, float volume);
|
||||
|
||||
// stop all sounds and the background track
|
||||
void S_StopAllSounds( void );
|
||||
|
||||
// all continuous looping sounds must be added before calling S_Update
|
||||
void S_ClearLoopingSounds( qboolean killall );
|
||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
void S_StopLoopingSound(int entityNum );
|
||||
|
||||
// recompute the reletive volumes for all running sounds
|
||||
// reletive to the given entityNum / orientation
|
||||
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
||||
|
||||
// let the sound system know where an entity currently is
|
||||
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
|
||||
|
||||
void S_Update( void );
|
||||
|
||||
void S_DisableSounds( void );
|
||||
|
||||
void S_BeginRegistration( void );
|
||||
|
||||
// RegisterSound will allways return a valid sample, even if it
|
||||
// has to create a placeholder. This prevents continuous filesystem
|
||||
// checks for missing files
|
||||
sfxHandle_t S_RegisterSound( const char *sample, qboolean compressed );
|
||||
|
||||
void S_DisplayFreeMemory(void);
|
||||
|
||||
void S_ClearSoundBuffer( void );
|
||||
|
||||
void SNDDMA_Activate( void );
|
||||
|
||||
void S_UpdateBackgroundTrack( void );
|
||||
|
|
506
code/client/snd_wavelet.c
Normal file → Executable file
506
code/client/snd_wavelet.c
Normal file → Executable file
|
@ -1,253 +1,253 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
long myftol( float f );
|
||||
|
||||
#define C0 0.4829629131445341
|
||||
#define C1 0.8365163037378079
|
||||
#define C2 0.2241438680420134
|
||||
#define C3 -0.1294095225512604
|
||||
|
||||
void daub4(float b[], unsigned long n, int isign)
|
||||
{
|
||||
float wksp[4097];
|
||||
float *a=b-1; // numerical recipies so a[1] = b[0]
|
||||
|
||||
unsigned long nh,nh1,i,j;
|
||||
|
||||
if (n < 4) return;
|
||||
|
||||
nh1=(nh=n >> 1)+1;
|
||||
if (isign >= 0) {
|
||||
for (i=1,j=1;j<=n-3;j+=2,i++) {
|
||||
wksp[i] = C0*a[j]+C1*a[j+1]+C2*a[j+2]+C3*a[j+3];
|
||||
wksp[i+nh] = C3*a[j]-C2*a[j+1]+C1*a[j+2]-C0*a[j+3];
|
||||
}
|
||||
wksp[i ] = C0*a[n-1]+C1*a[n]+C2*a[1]+C3*a[2];
|
||||
wksp[i+nh] = C3*a[n-1]-C2*a[n]+C1*a[1]-C0*a[2];
|
||||
} else {
|
||||
wksp[1] = C2*a[nh]+C1*a[n]+C0*a[1]+C3*a[nh1];
|
||||
wksp[2] = C3*a[nh]-C0*a[n]+C1*a[1]-C2*a[nh1];
|
||||
for (i=1,j=3;i<nh;i++) {
|
||||
wksp[j++] = C2*a[i]+C1*a[i+nh]+C0*a[i+1]+C3*a[i+nh1];
|
||||
wksp[j++] = C3*a[i]-C0*a[i+nh]+C1*a[i+1]-C2*a[i+nh1];
|
||||
}
|
||||
}
|
||||
for (i=1;i<=n;i++) {
|
||||
a[i]=wksp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void wt1(float a[], unsigned long n, int isign)
|
||||
{
|
||||
unsigned long nn;
|
||||
int inverseStartLength = n/4;
|
||||
if (n < inverseStartLength) return;
|
||||
if (isign >= 0) {
|
||||
for (nn=n;nn>=inverseStartLength;nn>>=1) daub4(a,nn,isign);
|
||||
} else {
|
||||
for (nn=inverseStartLength;nn<=n;nn<<=1) daub4(a,nn,isign);
|
||||
}
|
||||
}
|
||||
|
||||
/* The number of bits required by each value */
|
||||
static unsigned char numBits[] = {
|
||||
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
};
|
||||
|
||||
byte MuLawEncode(short s) {
|
||||
unsigned long adjusted;
|
||||
byte sign, exponent, mantissa;
|
||||
|
||||
sign = (s<0)?0:0x80;
|
||||
|
||||
if (s<0) s=-s;
|
||||
adjusted = (long)s << (16-sizeof(short)*8);
|
||||
adjusted += 128L + 4L;
|
||||
if (adjusted > 32767) adjusted = 32767;
|
||||
exponent = numBits[(adjusted>>7)&0xff] - 1;
|
||||
mantissa = (adjusted>>(exponent+3))&0xf;
|
||||
return ~(sign | (exponent<<4) | mantissa);
|
||||
}
|
||||
|
||||
short MuLawDecode(byte uLaw) {
|
||||
signed long adjusted;
|
||||
byte exponent, mantissa;
|
||||
|
||||
uLaw = ~uLaw;
|
||||
exponent = (uLaw>>4) & 0x7;
|
||||
mantissa = (uLaw&0xf) + 16;
|
||||
adjusted = (mantissa << (exponent +3)) - 128 - 4;
|
||||
|
||||
return (uLaw & 0x80)? adjusted : -adjusted;
|
||||
}
|
||||
|
||||
short mulawToShort[256];
|
||||
static qboolean madeTable = qfalse;
|
||||
|
||||
static int NXStreamCount;
|
||||
|
||||
void NXPutc(NXStream *stream, char out) {
|
||||
stream[NXStreamCount++] = out;
|
||||
}
|
||||
|
||||
|
||||
void encodeWavelet( sfx_t *sfx, short *packets) {
|
||||
float wksp[4097], temp;
|
||||
int i, samples, size;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
if (!madeTable) {
|
||||
for (i=0;i<256;i++) {
|
||||
mulawToShort[i] = (float)MuLawDecode((byte)i);
|
||||
}
|
||||
madeTable = qtrue;
|
||||
}
|
||||
chunk = NULL;
|
||||
|
||||
samples = sfx->soundLength;
|
||||
while(samples>0) {
|
||||
size = samples;
|
||||
if (size>(SND_CHUNK_SIZE*2)) {
|
||||
size = (SND_CHUNK_SIZE*2);
|
||||
}
|
||||
|
||||
if (size<4) {
|
||||
size = 4;
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
for(i=0; i<size; i++) {
|
||||
wksp[i] = *packets;
|
||||
packets++;
|
||||
}
|
||||
wt1(wksp, size, 1);
|
||||
out = (byte *)chunk->sndChunk;
|
||||
|
||||
for(i=0;i<size;i++) {
|
||||
temp = wksp[i];
|
||||
if (temp > 32767) temp = 32767; else if (temp<-32768) temp = -32768;
|
||||
out[i] = MuLawEncode((short)temp);
|
||||
}
|
||||
|
||||
chunk->size = size;
|
||||
samples -= size;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeWavelet(sndBuffer *chunk, short *to) {
|
||||
float wksp[4097];
|
||||
int i;
|
||||
byte *out;
|
||||
|
||||
int size = chunk->size;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0;i<size;i++) {
|
||||
wksp[i] = mulawToShort[out[i]];
|
||||
}
|
||||
|
||||
wt1(wksp, size, -1);
|
||||
|
||||
if (!to) return;
|
||||
|
||||
for(i=0; i<size; i++) {
|
||||
to[i] = wksp[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void encodeMuLaw( sfx_t *sfx, short *packets) {
|
||||
int i, samples, size, grade, poop;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
if (!madeTable) {
|
||||
for (i=0;i<256;i++) {
|
||||
mulawToShort[i] = (float)MuLawDecode((byte)i);
|
||||
}
|
||||
madeTable = qtrue;
|
||||
}
|
||||
|
||||
chunk = NULL;
|
||||
samples = sfx->soundLength;
|
||||
grade = 0;
|
||||
|
||||
while(samples>0) {
|
||||
size = samples;
|
||||
if (size>(SND_CHUNK_SIZE*2)) {
|
||||
size = (SND_CHUNK_SIZE*2);
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0; i<size; i++) {
|
||||
poop = packets[0]+grade;
|
||||
if (poop>32767) {
|
||||
poop = 32767;
|
||||
} else if (poop<-32768) {
|
||||
poop = -32768;
|
||||
}
|
||||
out[i] = MuLawEncode((short)poop);
|
||||
grade = poop - mulawToShort[out[i]];
|
||||
packets++;
|
||||
}
|
||||
chunk->size = size;
|
||||
samples -= size;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeMuLaw(sndBuffer *chunk, short *to) {
|
||||
int i;
|
||||
byte *out;
|
||||
|
||||
int size = chunk->size;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0;i<size;i++) {
|
||||
to[i] = mulawToShort[out[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
long myftol( float f );
|
||||
|
||||
#define C0 0.4829629131445341
|
||||
#define C1 0.8365163037378079
|
||||
#define C2 0.2241438680420134
|
||||
#define C3 -0.1294095225512604
|
||||
|
||||
void daub4(float b[], unsigned long n, int isign)
|
||||
{
|
||||
float wksp[4097];
|
||||
float *a=b-1; // numerical recipies so a[1] = b[0]
|
||||
|
||||
unsigned long nh,nh1,i,j;
|
||||
|
||||
if (n < 4) return;
|
||||
|
||||
nh1=(nh=n >> 1)+1;
|
||||
if (isign >= 0) {
|
||||
for (i=1,j=1;j<=n-3;j+=2,i++) {
|
||||
wksp[i] = C0*a[j]+C1*a[j+1]+C2*a[j+2]+C3*a[j+3];
|
||||
wksp[i+nh] = C3*a[j]-C2*a[j+1]+C1*a[j+2]-C0*a[j+3];
|
||||
}
|
||||
wksp[i ] = C0*a[n-1]+C1*a[n]+C2*a[1]+C3*a[2];
|
||||
wksp[i+nh] = C3*a[n-1]-C2*a[n]+C1*a[1]-C0*a[2];
|
||||
} else {
|
||||
wksp[1] = C2*a[nh]+C1*a[n]+C0*a[1]+C3*a[nh1];
|
||||
wksp[2] = C3*a[nh]-C0*a[n]+C1*a[1]-C2*a[nh1];
|
||||
for (i=1,j=3;i<nh;i++) {
|
||||
wksp[j++] = C2*a[i]+C1*a[i+nh]+C0*a[i+1]+C3*a[i+nh1];
|
||||
wksp[j++] = C3*a[i]-C0*a[i+nh]+C1*a[i+1]-C2*a[i+nh1];
|
||||
}
|
||||
}
|
||||
for (i=1;i<=n;i++) {
|
||||
a[i]=wksp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void wt1(float a[], unsigned long n, int isign)
|
||||
{
|
||||
unsigned long nn;
|
||||
int inverseStartLength = n/4;
|
||||
if (n < inverseStartLength) return;
|
||||
if (isign >= 0) {
|
||||
for (nn=n;nn>=inverseStartLength;nn>>=1) daub4(a,nn,isign);
|
||||
} else {
|
||||
for (nn=inverseStartLength;nn<=n;nn<<=1) daub4(a,nn,isign);
|
||||
}
|
||||
}
|
||||
|
||||
/* The number of bits required by each value */
|
||||
static unsigned char numBits[] = {
|
||||
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
};
|
||||
|
||||
byte MuLawEncode(short s) {
|
||||
unsigned long adjusted;
|
||||
byte sign, exponent, mantissa;
|
||||
|
||||
sign = (s<0)?0:0x80;
|
||||
|
||||
if (s<0) s=-s;
|
||||
adjusted = (long)s << (16-sizeof(short)*8);
|
||||
adjusted += 128L + 4L;
|
||||
if (adjusted > 32767) adjusted = 32767;
|
||||
exponent = numBits[(adjusted>>7)&0xff] - 1;
|
||||
mantissa = (adjusted>>(exponent+3))&0xf;
|
||||
return ~(sign | (exponent<<4) | mantissa);
|
||||
}
|
||||
|
||||
short MuLawDecode(byte uLaw) {
|
||||
signed long adjusted;
|
||||
byte exponent, mantissa;
|
||||
|
||||
uLaw = ~uLaw;
|
||||
exponent = (uLaw>>4) & 0x7;
|
||||
mantissa = (uLaw&0xf) + 16;
|
||||
adjusted = (mantissa << (exponent +3)) - 128 - 4;
|
||||
|
||||
return (uLaw & 0x80)? adjusted : -adjusted;
|
||||
}
|
||||
|
||||
short mulawToShort[256];
|
||||
static qboolean madeTable = qfalse;
|
||||
|
||||
static int NXStreamCount;
|
||||
|
||||
void NXPutc(NXStream *stream, char out) {
|
||||
stream[NXStreamCount++] = out;
|
||||
}
|
||||
|
||||
|
||||
void encodeWavelet( sfx_t *sfx, short *packets) {
|
||||
float wksp[4097], temp;
|
||||
int i, samples, size;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
if (!madeTable) {
|
||||
for (i=0;i<256;i++) {
|
||||
mulawToShort[i] = (float)MuLawDecode((byte)i);
|
||||
}
|
||||
madeTable = qtrue;
|
||||
}
|
||||
chunk = NULL;
|
||||
|
||||
samples = sfx->soundLength;
|
||||
while(samples>0) {
|
||||
size = samples;
|
||||
if (size>(SND_CHUNK_SIZE*2)) {
|
||||
size = (SND_CHUNK_SIZE*2);
|
||||
}
|
||||
|
||||
if (size<4) {
|
||||
size = 4;
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
for(i=0; i<size; i++) {
|
||||
wksp[i] = *packets;
|
||||
packets++;
|
||||
}
|
||||
wt1(wksp, size, 1);
|
||||
out = (byte *)chunk->sndChunk;
|
||||
|
||||
for(i=0;i<size;i++) {
|
||||
temp = wksp[i];
|
||||
if (temp > 32767) temp = 32767; else if (temp<-32768) temp = -32768;
|
||||
out[i] = MuLawEncode((short)temp);
|
||||
}
|
||||
|
||||
chunk->size = size;
|
||||
samples -= size;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeWavelet(sndBuffer *chunk, short *to) {
|
||||
float wksp[4097];
|
||||
int i;
|
||||
byte *out;
|
||||
|
||||
int size = chunk->size;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0;i<size;i++) {
|
||||
wksp[i] = mulawToShort[out[i]];
|
||||
}
|
||||
|
||||
wt1(wksp, size, -1);
|
||||
|
||||
if (!to) return;
|
||||
|
||||
for(i=0; i<size; i++) {
|
||||
to[i] = wksp[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void encodeMuLaw( sfx_t *sfx, short *packets) {
|
||||
int i, samples, size, grade, poop;
|
||||
sndBuffer *newchunk, *chunk;
|
||||
byte *out;
|
||||
|
||||
if (!madeTable) {
|
||||
for (i=0;i<256;i++) {
|
||||
mulawToShort[i] = (float)MuLawDecode((byte)i);
|
||||
}
|
||||
madeTable = qtrue;
|
||||
}
|
||||
|
||||
chunk = NULL;
|
||||
samples = sfx->soundLength;
|
||||
grade = 0;
|
||||
|
||||
while(samples>0) {
|
||||
size = samples;
|
||||
if (size>(SND_CHUNK_SIZE*2)) {
|
||||
size = (SND_CHUNK_SIZE*2);
|
||||
}
|
||||
|
||||
newchunk = SND_malloc();
|
||||
if (sfx->soundData == NULL) {
|
||||
sfx->soundData = newchunk;
|
||||
} else {
|
||||
chunk->next = newchunk;
|
||||
}
|
||||
chunk = newchunk;
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0; i<size; i++) {
|
||||
poop = packets[0]+grade;
|
||||
if (poop>32767) {
|
||||
poop = 32767;
|
||||
} else if (poop<-32768) {
|
||||
poop = -32768;
|
||||
}
|
||||
out[i] = MuLawEncode((short)poop);
|
||||
grade = poop - mulawToShort[out[i]];
|
||||
packets++;
|
||||
}
|
||||
chunk->size = size;
|
||||
samples -= size;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeMuLaw(sndBuffer *chunk, short *to) {
|
||||
int i;
|
||||
byte *out;
|
||||
|
||||
int size = chunk->size;
|
||||
|
||||
out = (byte *)chunk->sndChunk;
|
||||
for(i=0;i<size;i++) {
|
||||
to[i] = mulawToShort[out[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue