diff options
Diffstat (limited to 'games/ioquake3/files/extra-patch-mp3')
-rw-r--r-- | games/ioquake3/files/extra-patch-mp3 | 753 |
1 files changed, 0 insertions, 753 deletions
diff --git a/games/ioquake3/files/extra-patch-mp3 b/games/ioquake3/files/extra-patch-mp3 deleted file mode 100644 index b33f2a660571..000000000000 --- a/games/ioquake3/files/extra-patch-mp3 +++ /dev/null @@ -1,753 +0,0 @@ -Index: code/client/snd_codec.c -=================================================================== ---- code/client/snd_codec.c (revision 917) -+++ code/client/snd_codec.c (working copy) -@@ -105,6 +105,9 @@ - #if USE_CODEC_VORBIS - S_CodecRegister(&ogg_codec); - #endif -+#if USE_CODEC_MP3 -+ S_CodecRegister(&mp3_codec); -+#endif - } - - /* -Index: code/client/snd_codec.h -=================================================================== ---- code/client/snd_codec.h (revision 917) -+++ code/client/snd_codec.h (working copy) -@@ -95,4 +95,13 @@ - int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer); - #endif // USE_CODEC_VORBIS - -+// MP3 codec -+#ifdef USE_CODEC_MP3 -+extern snd_codec_t mp3_codec; -+void *S_MP3_CodecLoad(const char *filename, snd_info_t *info); -+snd_stream_t *S_MP3_CodecOpenStream(const char *filename); -+void S_MP3_CodecCloseStream(snd_stream_t *stream); -+int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer); -+#endif // USE_CODEC_MP3 -+ - #endif // !_SND_CODEC_H_ -Index: code/client/snd_codec_mp3.c -=================================================================== ---- code/client/snd_codec_mp3.c (revision 0) -+++ code/client/snd_codec_mp3.c (revision 0) -@@ -0,0 +1,716 @@ -+/* -+=========================================================================== -+Copyright (C) 1999-2005 Id Software, Inc. -+Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com) -+Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de> -+Copyright (C) 2006 Thilo Schulz <arny@ats.s.bawue.de> -+ -+This file is part of Quake III Arena source code. -+ -+Quake III Arena source code is free software; you can redistribute it -+and/or modify it under the terms of the GNU General Public License as -+published by the Free Software Foundation; either version 2 of the License, -+or (at your option) any later version. -+ -+Quake III Arena source code is distributed in the hope that it will be -+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with Quake III Arena source code; if not, write to the Free Software -+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+=========================================================================== -+*/ -+ -+// MP3 support is enabled by this define -+#if USE_CODEC_MP3 -+ -+// includes for the Q3 sound system -+#include "client.h" -+#include "snd_codec.h" -+ -+// includes for the MP3 codec -+#include <mad.h> -+ -+#define MP3_SAMPLE_WIDTH 2 -+#define MP3_PCMSAMPLES_PERSLICE 32 -+ -+// buffer size used when reading through the mp3 -+#define MP3_DATA_BUFSIZ 128*1024 -+ -+// undefine this if you don't want any dithering. -+#define MP3_DITHERING -+ -+// Q3 MP3 codec -+snd_codec_t mp3_codec = -+{ -+ ".mp3", -+ S_MP3_CodecLoad, -+ S_MP3_CodecOpenStream, -+ S_MP3_CodecReadStream, -+ S_MP3_CodecCloseStream, -+ NULL -+}; -+ -+// structure used for info purposes -+struct snd_codec_mp3_info -+{ -+ byte encbuf[MP3_DATA_BUFSIZ]; // left over bytes not consumed -+ // by the decoder. -+ struct mad_stream madstream; // uses encbuf as buffer. -+ struct mad_frame madframe; // control structures for libmad. -+ struct mad_synth madsynth; -+ -+ byte *pcmbuf; // buffer for not-used samples. -+ int buflen; // length of buffer data. -+ int pcmbufsize; // amount of allocated memory for -+ // pcmbuf. This should have at least -+ // the size of a decoded mp3 frame. -+ -+ byte *dest; // copy decoded data here. -+ int destlen; // amount of already copied data. -+ int destsize; // amount of bytes we must decode. -+}; -+ -+/*************** MP3 utility functions ***************/ -+ -+/* -+================= -+S_MP3_ReadData -+================= -+*/ -+ -+// feed libmad with data -+int S_MP3_ReadData(snd_stream_t *stream, struct mad_stream *madstream, byte *encbuf, int encbufsize) -+{ -+ int retval; -+ int leftover; -+ -+ if(!stream) -+ return -1; -+ -+ leftover = madstream->bufend - madstream->next_frame; -+ if(leftover > 0) -+ memmove(encbuf, madstream->this_frame, leftover); -+ -+ -+ // Fill the buffer right to the end -+ -+ retval = FS_Read(&encbuf[leftover], encbufsize - leftover, stream->file); -+ -+ if(retval <= 0) -+ { -+ // EOF reached, that's ok. -+ return 0; -+ } -+ -+ mad_stream_buffer(madstream, encbuf, retval + leftover); -+ -+ return retval; -+} -+ -+ -+/* -+================= -+S_MP3_Scanfile -+ -+to determine the samplecount, we apparently must get *all* headers :( -+I basically used the xmms-mad plugin source to see how this stuff works. -+ -+returns a value < 0 on error. -+================= -+*/ -+ -+int S_MP3_Scanfile(snd_stream_t *stream) -+{ -+ struct mad_stream madstream; -+ struct mad_header madheader; -+ int retval; -+ int samplecount; -+ byte encbuf[MP3_DATA_BUFSIZ]; -+ -+ // error out on invalid input. -+ if(!stream) -+ return -1; -+ -+ mad_stream_init(&madstream); -+ mad_header_init(&madheader); -+ -+ while(1) -+ { -+ retval = S_MP3_ReadData(stream, &madstream, encbuf, sizeof(encbuf)); -+ if(retval < 0) -+ return -1; -+ else if(retval == 0) -+ break; -+ -+ // Start decoding the headers. -+ while(1) -+ { -+ if((retval = mad_header_decode(&madheader, &madstream)) < 0) -+ { -+ if(madstream.error == MAD_ERROR_BUFLEN) -+ { -+ // We need to read more data -+ break; -+ } -+ -+ if(!MAD_RECOVERABLE (madstream.error)) -+ { -+ // unrecoverable error... we must bail out. -+ return retval; -+ } -+ -+ mad_stream_skip(&madstream, madstream.skiplen); -+ continue; -+ } -+ -+ // we got a valid header. -+ -+ if(madheader.layer != MAD_LAYER_III) -+ { -+ // we don't support non-mp3s -+ return -1; -+ } -+ -+ if(!stream->info.samples) -+ { -+ // This here is the very first frame. Set initial values now, -+ // that we expect to stay constant throughout the whole mp3. -+ -+ stream->info.rate = madheader.samplerate; -+ stream->info.width = MP3_SAMPLE_WIDTH; -+ stream->info.channels = MAD_NCHANNELS(&madheader); -+ stream->info.samples = 0; -+ stream->info.size = 0; // same here. -+ stream->info.dataofs = 0; -+ } -+ else -+ { -+ // Check whether something changed that shouldn't. -+ -+ if(stream->info.rate != madheader.samplerate || -+ stream->info.channels != MAD_NCHANNELS(&madheader)) -+ return -1; -+ } -+ -+ // Update the counters -+ samplecount = MAD_NSBSAMPLES(&madheader) * MP3_PCMSAMPLES_PERSLICE; -+ stream->info.samples += samplecount; -+ stream->info.size += samplecount * stream->info.channels * stream->info.width; -+ } -+ } -+ -+ // Reset the file pointer so we can do the real decoding. -+ FS_Seek(stream->file, 0, FS_SEEK_SET); -+ -+ return 0; -+} -+ -+/************************ dithering functions ***************************/ -+ -+#ifdef MP3_DITHERING -+ -+// All dithering done here is taken from the GPL'ed xmms-mad plugin. -+ -+/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ -+/* Any feedback is very welcome. For any question, comments, */ -+/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */ -+/* matumoto@math.keio.ac.jp */ -+ -+/* Period parameters */ -+#define MP3_DITH_N 624 -+#define MP3_DITH_M 397 -+#define MATRIX_A 0x9908b0df /* constant vector a */ -+#define UPPER_MASK 0x80000000 /* most significant w-r bits */ -+#define LOWER_MASK 0x7fffffff /* least significant r bits */ -+ -+/* Tempering parameters */ -+#define TEMPERING_MASK_B 0x9d2c5680 -+#define TEMPERING_MASK_C 0xefc60000 -+#define TEMPERING_SHIFT_U(y) (y >> 11) -+#define TEMPERING_SHIFT_S(y) (y << 7) -+#define TEMPERING_SHIFT_T(y) (y << 15) -+#define TEMPERING_SHIFT_L(y) (y >> 18) -+ -+static unsigned long mt[MP3_DITH_N]; /* the array for the state vector */ -+static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */ -+ -+/* initializing the array with a NONZERO seed */ -+void sgenrand(unsigned long seed) -+{ -+ /* setting initial seeds to mt[MP3_DITH_N] using */ -+ /* the generator Line 25 of Table 1 in */ -+ /* [KNUTH 1981, The Art of Computer Programming */ -+ /* Vol. 2 (2nd Ed.), pp102] */ -+ mt[0]= seed & 0xffffffff; -+ for (mti=1; mti<MP3_DITH_N; mti++) -+ mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; -+} -+ -+unsigned long genrand(void) -+{ -+ unsigned long y; -+ static unsigned long mag01[2]={0x0, MATRIX_A}; -+ /* mag01[x] = x * MATRIX_A for x=0,1 */ -+ -+ if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */ -+ int kk; -+ -+ if (mti == MP3_DITH_N+1) /* if sgenrand() has not been called, */ -+ sgenrand(4357); /* a default initial seed is used */ -+ -+ for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) { -+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); -+ mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1]; -+ } -+ for (;kk<MP3_DITH_N-1;kk++) { -+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); -+ mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1]; -+ } -+ y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); -+ mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1]; -+ -+ mti = 0; -+ } -+ -+ y = mt[mti++]; -+ y ^= TEMPERING_SHIFT_U(y); -+ y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; -+ y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; -+ y ^= TEMPERING_SHIFT_L(y); -+ -+ return y; -+} -+ -+long triangular_dither_noise(int nbits) { -+ // parameter nbits : the peak-to-peak amplitude desired (in bits) -+ // use with nbits set to 2 + nber of bits to be trimmed. -+ // (because triangular is made from two uniformly distributed processes, -+ // it starts at 2 bits peak-to-peak amplitude) -+ // see The Theory of Dithered Quantization by Robert Alexander Wannamaker -+ // for complete proof of why that's optimal -+ -+ long v = (genrand()/2 - genrand()/2); // in ]-2^31, 2^31[ -+ //int signe = (v>0) ? 1 : -1; -+ long P = 1 << (32 - nbits); // the power of 2 -+ v /= P; -+ // now v in ]-2^(nbits-1), 2^(nbits-1) [ -+ -+ return v; -+} -+ -+#endif // MP3_DITHERING -+ -+/************************ decoder functions ***************************/ -+ -+/* -+================= -+S_MP3_Scale -+ -+Converts the signal to 16 bit LE-PCM data and does dithering. -+ -+- borrowed from xmms-mad plugin source. -+================= -+*/ -+ -+/* -+ * xmms-mad - mp3 plugin for xmms -+ * Copyright (C) 2001-2002 Sam Clegg -+ */ -+ -+signed int S_MP3_Scale(mad_fixed_t sample) -+{ -+ int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16; -+#ifdef MP3_DITHERING -+ int dither; -+#endif -+ -+ // round -+ sample += (1L << (n_bits_to_loose - 1)); -+ -+#ifdef MP3_DITHERING -+ dither = triangular_dither_noise(n_bits_to_loose + 1); -+ sample += dither; -+#endif -+ -+ /* clip */ -+ if (sample >= MAD_F_ONE) -+ sample = MAD_F_ONE - 1; -+ else if (sample < -MAD_F_ONE) -+ sample = -MAD_F_ONE; -+ -+ /* quantize */ -+ return sample >> n_bits_to_loose; -+} -+ -+ -+ -+/* -+================= -+S_MP3_PCMCopy -+ -+Copy and convert pcm data until bytecount bytes have been written. -+return the position in pcm->samples. -+indicate the amount of actually written bytes in wrotecnt. -+================= -+*/ -+ -+int S_MP3_PCMCopy(byte *buf, struct mad_pcm *pcm, int bufofs, -+ int sampleofs, int bytecount, int *wrotecnt) -+{ -+ int written = 0; -+ signed int sample; -+ int framesize = pcm->channels * MP3_SAMPLE_WIDTH; -+ -+ // add new pcm data. -+ while(written < bytecount && sampleofs < pcm->length) -+ { -+ sample = S_MP3_Scale(pcm->samples[0][sampleofs]); -+ -+#ifdef Q3_BIG_ENDIAN -+ // output to 16 bit big endian PCM -+ buf[bufofs++] = (sample >> 8) & 0xff; -+ buf[bufofs++] = sample & 0xff; -+#else -+ // output to 16 bit little endian PCM -+ buf[bufofs++] = sample & 0xff; -+ buf[bufofs++] = (sample >> 8) & 0xff; -+#endif -+ -+ if(pcm->channels == 2) -+ { -+ sample = S_MP3_Scale(pcm->samples[1][sampleofs]); -+ -+#ifdef Q3_BIG_ENDIAN -+ buf[bufofs++] = (sample >> 8) & 0xff; -+ buf[bufofs++] = sample & 0xff; -+#else -+ buf[bufofs++] = sample & 0xff; -+ buf[bufofs++] = (sample >> 8) & 0xff; -+#endif -+ } -+ -+ sampleofs++; -+ written += framesize; -+ } -+ -+ if(wrotecnt) -+ *wrotecnt = written; -+ -+ return sampleofs; -+} -+ -+ -+/* -+================= -+S_MP3_Decode -+================= -+*/ -+ -+// gets executed for every decoded frame. -+int S_MP3_Decode(snd_stream_t *stream) -+{ -+ struct snd_codec_mp3_info *mp3info; -+ struct mad_stream *madstream; -+ struct mad_frame *madframe; -+ struct mad_synth *madsynth; -+ struct mad_pcm *pcm; -+ int cursize; -+ int samplecount; -+ int needcount; -+ int wrote; -+ int retval; -+ -+ if(!stream) -+ return -1; -+ -+ mp3info = stream->ptr; -+ madstream = &mp3info->madstream; -+ madframe = &mp3info->madframe; -+ -+ if(mad_frame_decode(madframe, madstream)) -+ { -+ if(madstream->error == MAD_ERROR_BUFLEN) -+ { -+ // we need more data. Read another chunk. -+ retval = S_MP3_ReadData(stream, madstream, mp3info->encbuf, sizeof(mp3info->encbuf)); -+ -+ // call myself again now that buffer is full. -+ if(retval > 0) -+ retval = S_MP3_Decode(stream); -+ } -+ else if(MAD_RECOVERABLE(madstream->error)) -+ { -+ mad_stream_skip(madstream, madstream->skiplen); -+ return S_MP3_Decode(stream); -+ } -+ else -+ retval = -1; -+ -+ return retval; -+ } -+ -+ // check whether this really is an mp3 -+ if(madframe->header.layer != MAD_LAYER_III) -+ return -1; -+ -+ // generate pcm data -+ madsynth = &mp3info->madsynth; -+ mad_synth_frame(madsynth, madframe); -+ -+ pcm = &madsynth->pcm; -+ -+ // perform a few checks to see whether something changed that shouldn't. -+ -+ if(stream->info.rate != pcm->samplerate || -+ stream->info.channels != pcm->channels) -+ { -+ return -1; -+ } -+ // see whether we have got enough data now. -+ cursize = pcm->length * pcm->channels * stream->info.width; -+ needcount = mp3info->destsize - mp3info->destlen; -+ -+ // Copy exactly as many samples as required. -+ samplecount = S_MP3_PCMCopy(mp3info->dest, pcm, -+ mp3info->destlen, 0, needcount, &wrote); -+ mp3info->destlen += wrote; -+ -+ if(samplecount < pcm->length) -+ { -+ // Not all samples got copied. Copy the rest into the pcm buffer. -+ samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm, -+ mp3info->buflen, -+ samplecount, -+ mp3info->pcmbufsize - mp3info->buflen, -+ &wrote); -+ mp3info->buflen += wrote; -+ -+ -+ if(samplecount < pcm->length) -+ { -+ // The pcm buffer was not large enough. Make it bigger. -+ byte *newbuf = Z_Malloc(cursize); -+ -+ if(mp3info->pcmbuf) -+ { -+ memcpy(newbuf, mp3info->pcmbuf, mp3info->buflen); -+ Z_Free(mp3info->pcmbuf); -+ } -+ -+ mp3info->pcmbuf = newbuf; -+ mp3info->pcmbufsize = cursize; -+ -+ samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm, -+ mp3info->buflen, -+ samplecount, -+ mp3info->pcmbufsize - mp3info->buflen, -+ &wrote); -+ mp3info->buflen += wrote; -+ } -+ -+ // we're definitely done. -+ retval = 0; -+ } -+ else if(mp3info->destlen >= mp3info->destsize) -+ retval = 0; -+ else -+ retval = 1; -+ -+ return retval; -+} -+ -+/*************** Callback functions for quake3 ***************/ -+ -+/* -+================= -+S_MP3_CodecOpenStream -+================= -+*/ -+ -+snd_stream_t *S_MP3_CodecOpenStream(const char *filename) -+{ -+ snd_stream_t *stream; -+ struct snd_codec_mp3_info *mp3info; -+ -+ // Open the stream -+ stream = S_CodecUtilOpen(filename, &mp3_codec); -+ if(!stream || stream->length <= 0) -+ return NULL; -+ -+ // We have to scan through the MP3 to determine the important mp3 info. -+ if(S_MP3_Scanfile(stream) < 0) -+ { -+ // scanning didn't work out... -+ S_CodecUtilClose(stream); -+ return NULL; -+ } -+ -+ // Initialize the mp3 info structure we need for streaming -+ mp3info = Z_Malloc(sizeof(*mp3info)); -+ if(!mp3info) -+ { -+ S_CodecUtilClose(stream); -+ return NULL; -+ } -+ -+ stream->ptr = mp3info; -+ -+ // initialize the libmad control structures. -+ mad_stream_init(&mp3info->madstream); -+ mad_frame_init(&mp3info->madframe); -+ mad_synth_init(&mp3info->madsynth); -+ -+ if(S_MP3_ReadData(stream, &mp3info->madstream, mp3info->encbuf, sizeof(mp3info->encbuf)) <= 0) -+ { -+ // we didnt read anything, that's bad. -+ S_MP3_CodecCloseStream(stream); -+ return NULL; -+ } -+ -+ return stream; -+} -+ -+/* -+================= -+S_MP3_CodecCloseStream -+================= -+*/ -+ -+// free all memory we allocated. -+void S_MP3_CodecCloseStream(snd_stream_t *stream) -+{ -+ struct snd_codec_mp3_info *mp3info; -+ -+ if(!stream) -+ return; -+ -+ // free all data in our mp3info tree -+ -+ if(stream->ptr) -+ { -+ mp3info = stream->ptr; -+ -+ if(mp3info->pcmbuf) -+ Z_Free(mp3info->pcmbuf); -+ -+ mad_synth_finish(&mp3info->madsynth); -+ mad_frame_finish(&mp3info->madframe); -+ mad_stream_finish(&mp3info->madstream); -+ -+ Z_Free(stream->ptr); -+ } -+ -+ S_CodecUtilClose(stream); -+} -+ -+/* -+================= -+S_MP3_CodecReadStream -+================= -+*/ -+int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer) -+{ -+ struct snd_codec_mp3_info *mp3info; -+ int retval; -+ -+ if(!stream) -+ return -1; -+ -+ mp3info = stream->ptr; -+ -+ // Make sure we get complete frames all the way through. -+ bytes -= bytes % (stream->info.channels * stream->info.width); -+ -+ if(mp3info->buflen) -+ { -+ if(bytes < mp3info->buflen) -+ { -+ // we still have enough bytes in our decoded pcm buffer -+ memcpy(buffer, mp3info->pcmbuf, bytes); -+ -+ // remove the portion from our buffer. -+ mp3info->buflen -= bytes; -+ memmove(mp3info->pcmbuf, &mp3info->pcmbuf[bytes], mp3info->buflen); -+ return bytes; -+ } -+ else -+ { -+ // copy over the samples we already have. -+ memcpy(buffer, mp3info->pcmbuf, mp3info->buflen); -+ mp3info->destlen = mp3info->buflen; -+ mp3info->buflen = 0; -+ } -+ } -+ else -+ mp3info->destlen = 0; -+ -+ mp3info->dest = buffer; -+ mp3info->destsize = bytes; -+ -+ do -+ { -+ retval = S_MP3_Decode(stream); -+ } while(retval > 0); -+ -+ // if there was an error return nothing. -+ if(retval < 0) -+ return 0; -+ -+ return mp3info->destlen; -+} -+ -+/* -+===================================================================== -+S_MP3_CodecLoad -+ -+We handle S_MP3_CodecLoad as a special case of the streaming functions -+where we read the whole stream at once. -+====================================================================== -+*/ -+void *S_MP3_CodecLoad(const char *filename, snd_info_t *info) -+{ -+ snd_stream_t *stream; -+ byte *pcmbuffer; -+ -+ // check if input is valid -+ if(!filename) -+ return NULL; -+ -+ stream = S_MP3_CodecOpenStream(filename); -+ -+ if(!stream) -+ return NULL; -+ -+ // copy over the info -+ info->rate = stream->info.rate; -+ info->width = stream->info.width; -+ info->channels = stream->info.channels; -+ info->samples = stream->info.samples; -+ info->dataofs = stream->info.dataofs; -+ -+ // allocate enough buffer for all pcm data -+ pcmbuffer = Z_Malloc(stream->info.size); -+ if(!pcmbuffer) -+ { -+ S_MP3_CodecCloseStream(stream); -+ return NULL; -+ } -+ -+ info->size = S_MP3_CodecReadStream(stream, stream->info.size, pcmbuffer); -+ -+ if(info->size <= 0) -+ { -+ // we didn't read anything at all. darn. -+ Z_Free(pcmbuffer); -+ pcmbuffer = NULL; -+ } -+ -+ S_MP3_CodecCloseStream(stream); -+ -+ return pcmbuffer; -+} -+ -+#endif // USE_CODEC_MP3 |