newlines fixed
This commit is contained in:
parent
7830940da6
commit
59cce31e75
1121 changed files with 717537 additions and 717537 deletions
File diff suppressed because it is too large
Load diff
3480
code/client/cl_cin.c
3480
code/client/cl_cin.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2400
code/client/cl_ui.c
2400
code/client/cl_ui.c
File diff suppressed because it is too large
Load diff
1038
code/client/client.h
1038
code/client/client.h
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 );
|
||||
|
|
|
@ -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