/* =========================================================================== Return to Castle Wolfenstein multiplayer GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”). RTCW MP 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 3 of the License, or (at your option) any later version. RTCW MP 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 RTCW MP Source Code. If not, see . In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ /***************************************************************************** * name: snd_wavelet.c * * desc: * * *****************************************************************************/ #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]]; } }