shithub: aacenc

Download patch

ref: 2fbc12a1a1ee88dc8e023bcdb71a6e6f440781aa
parent: a45b7e2efb17f0ace411d91fa90657a167248c6e
author: menno <menno>
date: Wed Feb 28 13:39:34 EST 2001

- added TNS support
- some other cleanups

--- a/include/faac.h
+++ b/include/faac.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: faac.h,v 1.2 2001/01/17 15:51:15 menno Exp $
+ * $Id: faac.h,v 1.3 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef FAACLIB_H
@@ -40,13 +40,24 @@
 #define FAACENC_VERSION 1.0
 #define FAACENC_VERSIONB 1 /* If 1 this version is still in beta */
 
+/* AAC profiles */
+#define MAIN 0
+#define LOW  1
+#define SSR  2
+
 typedef struct faacEncConfiguration
 {
+	/* AAC profile */
+	unsigned int aacProfile;
 
 	/* Allow mid/side coding */
 	unsigned int allowMidside;
+
 	/* Use one of the channels as LFE channel */
 	unsigned int useLfe;
+
+	/* Use Temporal Noise Shaping */
+	unsigned int useTns;
 
 	/* bitrate / channel of AAC file */
 	unsigned long bitRate;
--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: aacquant.c,v 1.3 2001/02/04 17:50:47 oxygene2000 Exp $
+ * $Id: aacquant.c,v 1.4 2001/02/28 18:39:34 menno Exp $
  */
 
 #include <math.h>
@@ -27,7 +27,7 @@
 #include "coder.h"
 #include "huffman.h"
 #include "psych.h"
-
+#include "util.h"
 
 
 #define XRPOW_FTOI(src,dest) ((dest) = (int)(src))
--- a/libfaac/bitstream.c
+++ b/libfaac/bitstream.c
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: bitstream.c,v 1.3 2001/02/04 17:50:47 oxygene2000 Exp $
+ * $Id: bitstream.c,v 1.4 2001/02/28 18:39:34 menno Exp $
  */
 
 #include <stdlib.h>
@@ -183,7 +183,7 @@
 		PutBit(bitStream, 1, 1); /* ID */
 		PutBit(bitStream, 0, 2); /* layer */
 		PutBit(bitStream, 1, 1); /* protection absent */
-		PutBit(bitStream, hEncoder->aacProfile, 2); /* profile */
+		PutBit(bitStream, hEncoder->config.aacProfile, 2); /* profile */
 		PutBit(bitStream, hEncoder->sampleRateIdx, 4); /* sampling rate */
 		PutBit(bitStream, 0, 1); /* private bit */
 		PutBit(bitStream, 1, 3); /* ch. config (must be > 0) */
@@ -411,13 +411,83 @@
 						int writeFlag)
 {
 	int bits = 0;
+	int numWindows;
+	int len_tns_nfilt;
+	int len_tns_length;
+	int len_tns_order;
+	int filtNumber;
+	int resInBits;
+	int bitsToTransmit;
+	unsigned long unsignedIndex;
+	int w;
 
+	TnsInfo* tnsInfoPtr = &coderInfo->tnsInfo;
+
 	if (writeFlag) {
-		PutBit(bitStream, 0, LEN_TNS_PRES);
+		PutBit(bitStream,tnsInfoPtr->tnsDataPresent,LEN_TNS_PRES);
 	}
-
 	bits += LEN_TNS_PRES;
 
+	/* If TNS is not present, bail */
+	if (!tnsInfoPtr->tnsDataPresent) {
+		return bits;
+	}
+
+	/* Set window-dependent TNS parameters */
+	if (coderInfo->block_type == ONLY_SHORT_WINDOW) {
+		numWindows = MAX_SHORT_WINDOWS;
+		len_tns_nfilt = LEN_TNS_NFILTS;
+		len_tns_length = LEN_TNS_LENGTHS;
+		len_tns_order = LEN_TNS_ORDERS;
+	}
+	else {
+		numWindows = 1;
+		len_tns_nfilt = LEN_TNS_NFILTL;
+		len_tns_length = LEN_TNS_LENGTHL;
+		len_tns_order = LEN_TNS_ORDERL;
+	}
+
+	/* Write TNS data */
+	bits += (numWindows * len_tns_nfilt);
+	for (w=0;w<numWindows;w++) {
+		TnsWindowData* windowDataPtr = &tnsInfoPtr->windowData[w];
+		int numFilters = windowDataPtr->numFilters;
+		if (writeFlag) {
+			PutBit(bitStream,numFilters,len_tns_nfilt); /* n_filt[] = 0 */
+		}
+		if (numFilters) {
+			bits += LEN_TNS_COEFF_RES;
+			resInBits = windowDataPtr->coefResolution;
+			if (writeFlag) {
+				PutBit(bitStream,resInBits-DEF_TNS_RES_OFFSET,LEN_TNS_COEFF_RES);
+			}
+			bits += numFilters * (len_tns_length+len_tns_order);
+			for (filtNumber=0;filtNumber<numFilters;filtNumber++) {
+				TnsFilterData* tnsFilterPtr=&windowDataPtr->tnsFilter[filtNumber];
+				int order = tnsFilterPtr->order;
+				if (writeFlag) {
+					PutBit(bitStream,tnsFilterPtr->length,len_tns_length);
+					PutBit(bitStream,order,len_tns_order);
+				}
+				if (order) {
+					bits += (LEN_TNS_DIRECTION + LEN_TNS_COMPRESS);
+					if (writeFlag) {
+						PutBit(bitStream,tnsFilterPtr->direction,LEN_TNS_DIRECTION);
+						PutBit(bitStream,tnsFilterPtr->coefCompress,LEN_TNS_COMPRESS);
+					}
+					bitsToTransmit = resInBits - tnsFilterPtr->coefCompress;
+					bits += order * bitsToTransmit;
+					if (writeFlag) {
+						int i;
+						for (i=1;i<=order;i++) {
+							unsignedIndex = (unsigned long) (tnsFilterPtr->index[i])&(~(~0<<bitsToTransmit));
+							PutBit(bitStream,unsignedIndex,bitsToTransmit);
+						}
+					}
+				}
+			}
+		}
+	}
 	return bits;
 }
 
--- a/libfaac/bitstream.h
+++ b/libfaac/bitstream.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: bitstream.h,v 1.2 2001/01/23 13:46:18 menno Exp $
+ * $Id: bitstream.h,v 1.3 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef BITSTREAM_H
@@ -96,6 +96,10 @@
 #define ID_FIL 6
 #define ID_END 7
 
+/* AAC profiles */
+#define MAIN 0
+#define LOW  1
+#define SSR  2
 
 
 #define BYTE_NUMBIT 8		/* bits in byte (char) */
--- a/libfaac/channels.c
+++ b/libfaac/channels.c
@@ -16,12 +16,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: channels.c,v 1.1 2001/01/17 11:21:40 menno Exp $
+ * $Id: channels.c,v 1.2 2001/02/28 18:39:34 menno Exp $
  */
 
 #include "channels.h"
 #include "coder.h"
-
+#include "util.h"
 
 /* If LFE present                                                       */
 /*  Num channels       # of SCE's       # of CPE's       #of LFE's      */ 
--- a/libfaac/channels.h
+++ b/libfaac/channels.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: channels.h,v 1.3 2001/02/26 14:07:55 oxygene Exp $
+ * $Id: channels.h,v 1.4 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef CHANNEL_H
@@ -25,10 +25,6 @@
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
-
-#ifdef __unix__
-#define min(a,b) ( (a) < (b) ? (a) : (b) )
-#endif
 
 #include "coder.h"
 
--- a/libfaac/coder.h
+++ b/libfaac/coder.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: coder.h,v 1.2 2001/02/04 17:50:47 oxygene2000 Exp $
+ * $Id: coder.h,v 1.3 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef CODER_H
@@ -44,7 +44,45 @@
 	SHORT_LONG_WINDOW
 };
 
+/* Added TNS defines and structures here to get it to compile */
+#define TNS_MAX_ORDER 20
+#define DEF_TNS_GAIN_THRESH 1.4
+#define DEF_TNS_COEFF_THRESH 0.1
+#define DEF_TNS_COEFF_RES 4
+#define DEF_TNS_RES_OFFSET 3
+#define LEN_TNS_NFILTL 2
+#define LEN_TNS_NFILTS 1
+
 typedef struct {
+	int order;                           /* Filter order */
+	int direction;		                 /* Filtering direction */
+	int coefCompress;		             /* Are coeffs compressed? */
+	int length;                          /* Length, in bands */                     
+	double aCoeffs[TNS_MAX_ORDER+1];     /* AR Coefficients */
+	double kCoeffs[TNS_MAX_ORDER+1];     /* Reflection Coefficients */
+	int index[TNS_MAX_ORDER+1];	         /* Coefficient indices */
+} TnsFilterData;
+
+typedef struct {
+	int numFilters;				                /* Number of filters */
+	int coefResolution;				            /* Coefficient resolution */
+	TnsFilterData tnsFilter[1<<LEN_TNS_NFILTL];	/* TNS filters */
+} TnsWindowData;
+
+typedef struct {
+	int tnsDataPresent;
+	int tnsMinBandNumberLong;
+	int tnsMinBandNumberShort;
+	int tnsMaxBandsLong;
+	int tnsMaxBandsShort;
+	int tnsMaxOrderLong;
+	int tnsMaxOrderShort;
+	TnsWindowData windowData[MAX_SHORT_WINDOWS]; /* TNS data per window */
+} TnsInfo;
+/* End of TNS defines and structures */
+
+
+typedef struct {
 	int window_shape;
 	int prev_window_shape;
 	int block_type;
@@ -72,6 +110,8 @@
 
 	/* Lengths of spectral bitstream elements */
 	int *len;
+
+	TnsInfo tnsInfo;
 
 } CoderInfo;
 
--- a/libfaac/filtbank.c
+++ b/libfaac/filtbank.c
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: filtbank.c,v 1.3 2001/02/25 18:41:16 menno Exp $
+ * $Id: filtbank.c,v 1.4 2001/02/28 18:39:34 menno Exp $
  */
 
 /*
@@ -34,8 +34,9 @@
 #include "filtbank.h"
 #include "frame.h"
 #include "fft.h"
+#include "util.h"
 
-#define  TWOPI       6.28318530717958647692
+#define  TWOPI       2*M_PI
 
 
 void FilterBankInit(faacEncHandle hEncoder)
--- a/libfaac/filtbank.h
+++ b/libfaac/filtbank.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: filtbank.h,v 1.4 2001/02/25 18:41:16 menno Exp $
+ * $Id: filtbank.h,v 1.5 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef FILTBANK_H
@@ -29,14 +29,6 @@
 #include "frame.h"
 
 #define NFLAT_LS 448
-
-#ifndef M_PI
-#define M_PI        3.14159265358979323846
-#endif
-
-#ifndef M_PI_2
-#define M_PI_2      1.57079632679489661923
-#endif
 
 
 #define SINE_WINDOW 0
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,12 +16,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: frame.c,v 1.9 2001/02/12 14:39:14 menno Exp $
+ * $Id: frame.c,v 1.10 2001/02/28 18:39:34 menno Exp $
  */
 
 /*
  * CHANGES:
  *  2001/01/17: menno: Added frequency cut off filter.
+ *  2001/02/28: menno: Added Temporal Noise Shaping.
  *
  */
 
@@ -39,6 +40,7 @@
 #include "util.h"
 #include "huffman.h"
 #include "psych.h"
+#include "tns.h"
 
 
 faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder)
@@ -53,7 +55,16 @@
 {
 	hEncoder->config.allowMidside = config->allowMidside;
 	hEncoder->config.useLfe = config->useLfe;
+	hEncoder->config.useTns = config->useTns;
+	hEncoder->config.aacProfile = config->aacProfile;
 
+	 /* No SSR supported yet */
+	if ((hEncoder->config.aacProfile != MAIN)&&(hEncoder->config.aacProfile != LOW))
+		return 0;
+
+	/* Re-init TNS for new profile */
+	TnsInit(hEncoder);
+
 	/* Check for correct bitrate */
 	if (config->bitRate > MaxBitrate(hEncoder->sampleRate))
 		return 0;
@@ -83,9 +94,12 @@
 	/* Initialize variables to default values */
 	hEncoder->frameNum = 0;
 	hEncoder->flushFrame = 0;
-	hEncoder->aacProfile = 0; /* MAIN = 0, LOW = 1, SSR = 2 */
+
+	/* Default configuration */
+	hEncoder->config.aacProfile = MAIN;
 	hEncoder->config.allowMidside = 1;
 	hEncoder->config.useLfe = 0;
+	hEncoder->config.useTns = 0;
 	hEncoder->config.bitRate = 64000; /* default bitrate / channel */
 	hEncoder->config.bandWidth = 18000; /* default bandwidth */
 
@@ -110,6 +124,8 @@
 
 	FilterBankInit(hEncoder);
 
+    TnsInit(hEncoder);
+
 	AACQuantizeInit(hEncoder->coderInfo, hEncoder->numChannels);
 
 	HuffmanInit(hEncoder->coderInfo, hEncoder->numChannels);
@@ -160,7 +176,9 @@
 	CoderInfo *coderInfo = hEncoder->coderInfo;
 	unsigned int numChannels = hEncoder->numChannels;
 	unsigned int sampleRate = hEncoder->sampleRate;
+	unsigned int aacProfile = hEncoder->config.aacProfile;
 	unsigned int useLfe = hEncoder->config.useLfe;
+	unsigned int useTns = hEncoder->config.useTns;
 	unsigned int allowMidside = hEncoder->config.allowMidside;
 	unsigned int bitRate = hEncoder->config.bitRate;
 	unsigned int bandWidth = hEncoder->config.bandWidth;
@@ -272,6 +290,20 @@
 				offset += hEncoder->srInfo->cb_width_long[sb];
 			}
 			coderInfo[channel].sfb_offset[coderInfo[channel].nr_of_sfb] = offset;
+		}
+	}
+
+	/* Perform TNS analysis and filtering */
+	for (channel = 0; channel < numChannels; channel++) {
+		if ((!channelInfo[channel].lfe) && (useTns)) {
+			TnsEncode(&(coderInfo[channel].tnsInfo),
+				coderInfo[channel].max_sfb,
+				coderInfo[channel].max_sfb,
+				coderInfo[channel].block_type,
+				coderInfo[channel].sfb_offset,
+				hEncoder->freqBuff[channel]);
+		} else {
+			coderInfo[channel].tnsInfo.tnsDataPresent = 0;      /* TNS not used for LFE */
 		}
 	}
 
--- a/libfaac/frame.h
+++ b/libfaac/frame.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: frame.h,v 1.4 2001/02/04 17:50:47 oxygene2000 Exp $
+ * $Id: frame.h,v 1.5 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef FRAME_H
@@ -41,16 +41,23 @@
   #endif
 #endif
 
+
 static SR_INFO srInfo[12+1];
 
 typedef struct faacEncConfiguration
 {
+	/* AAC profile */
+	unsigned int aacProfile;
 
 	/* Allow mid/side coding */
 	unsigned int allowMidside;
+
 	/* Use one of the channels as LFE channel */
 	unsigned int useLfe;
 
+	/* Use Temporal Noise Shaping */
+	unsigned int useTns;
+
 	/* bitrate / channel of AAC file */
 	unsigned long bitRate;
 
@@ -67,7 +74,6 @@
 	unsigned long sampleRate;
 	unsigned int sampleRateIdx;
 
-	unsigned int aacProfile;
 	unsigned int usedBytes;
 
 	/* frame number */
--- a/libfaac/joint.c
+++ b/libfaac/joint.c
@@ -16,11 +16,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: joint.c,v 1.2 2001/01/23 13:23:04 menno Exp $
+ * $Id: joint.c,v 1.3 2001/02/28 18:39:34 menno Exp $
  */
 
-#include <stdlib.h> /* for max() define */
 #include "channels.h"
+#include "util.h"
 
 void MSEncode(CoderInfo *coderInfo,
 			  ChannelInfo *channelInfo,
--- a/libfaac/libfaac.dsp
+++ b/libfaac/libfaac.dsp
@@ -25,7 +25,7 @@
 # PROP AllowPerConfigDependencies 0
 # PROP Scc_ProjName ""
 # PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
 RSC=rc.exe
 
 !IF  "$(CFG)" == "libfaac - Win32 Release"
@@ -41,13 +41,13 @@
 # PROP Intermediate_Dir "Release"
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /W3 /GX- /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
 # ADD BASE RSC /l 0x413 /d "NDEBUG"
 # ADD RSC /l 0x413 /d "NDEBUG"
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo
 
@@ -70,7 +70,7 @@
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo
 
@@ -121,6 +121,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\tns.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\util.c
 # End Source File
 # End Group
@@ -174,6 +178,10 @@
 # Begin Source File
 
 SOURCE=.\psych.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tns.h
 # End Source File
 # Begin Source File
 
--- a/libfaac/psych.c
+++ b/libfaac/psych.c
@@ -16,16 +16,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: psych.c,v 1.6 2001/02/12 14:39:14 menno Exp $
+ * $Id: psych.c,v 1.7 2001/02/28 18:39:34 menno Exp $
  */
 
-#include <stdlib.h>
-#include <memory.h>
+#include <malloc.h>
 #include <math.h>
 
 #include "psych.h"
 #include "coder.h"
 #include "fft.h"
+#include "util.h"
 
 #define NS_INTERP(x,y,r) (pow((x),(r))*pow((y),1-(r)))
 #define SQRT2 1.41421356237309504880
--- a/libfaac/psych.h
+++ b/libfaac/psych.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: psych.h,v 1.5 2001/02/26 14:08:34 oxygene Exp $
+ * $Id: psych.h,v 1.6 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef PSYCH_H
@@ -25,15 +25,6 @@
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
-
-#ifndef M_PI
-#define M_PI        3.14159265358979323846
-#endif
-
-#ifdef __unix__
-#define min(a,b) ( (a) < (b) ? (a) : (b) )
-#define max(a,b) ( (a) > (b) ? (a) : (b) )
-#endif
 
 #include "coder.h"
 #include "channels.h"
--- /dev/null
+++ b/libfaac/tns.c
@@ -1,0 +1,583 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * $Id: tns.c,v 1.1 2001/02/28 18:39:34 menno Exp $
+ */
+
+#include <malloc.h>
+#include "frame.h"
+#include "coder.h"
+#include "bitstream.h"
+#include "tns.h"
+#include "util.h"
+
+/***********************************************/
+/* TNS Profile/Frequency Dependent Parameters  */
+/***********************************************/
+static unsigned long tnsSupportedSamplingRates[13] =
+{ 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0 };
+
+/* Limit bands to > 2.0 kHz */
+static unsigned short tnsMinBandNumberLong[12] =
+{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
+static unsigned short tnsMinBandNumberShort[12] = 
+{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
+       
+/**************************************/
+/* Main/Low Profile TNS Parameters    */
+/**************************************/
+static unsigned short tnsMaxBandsLongMainLow[12] = 
+{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
+
+static unsigned short tnsMaxBandsShortMainLow[12] = 
+{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
+
+static unsigned short tnsMaxOrderLongMain = 20;
+static unsigned short tnsMaxOrderLongLow = 12;
+static unsigned short tnsMaxOrderShortMainLow = 7;
+
+/**************************************/
+/* SSR Profile TNS Parameters         */
+/**************************************/
+static unsigned short tnsMaxBandsLongSSR[12] = 
+{ 28, 28, 27, 26, 26, 26, 29, 29, 23, 23, 23, 19 };
+
+static unsigned short tnsMaxBandsShortSSR[12] = 
+{ 7, 7, 7, 6, 6, 6, 7, 7, 8, 8, 8, 7 };
+
+static unsigned short tnsMaxOrderLongSSR = 12;
+static unsigned short tnsMaxOrderShortSSR = 7;
+
+
+/*****************************************************/
+/* InitTns:                                          */
+/*****************************************************/
+void TnsInit(faacEncHandle hEncoder)
+{
+	unsigned int channel;
+	int fsIndex = hEncoder->sampleRateIdx;
+	int profile = hEncoder->config.aacProfile;
+
+	for (channel = 0; channel < hEncoder->numChannels; channel++) {
+		TnsInfo *tnsInfo = &hEncoder->coderInfo[channel].tnsInfo;
+
+		switch( profile ) {
+		case MAIN :
+			tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
+			tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
+			tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongMain;
+			tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
+			break;
+		case LOW :
+			tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
+			tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
+			tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongLow;
+			tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
+			break;
+		case SSR :
+			tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongSSR[fsIndex];
+			tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortSSR[fsIndex];
+			tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongSSR;
+			tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortSSR;
+			break;
+		}
+		tnsInfo->tnsMinBandNumberLong = tnsMinBandNumberLong[fsIndex];
+		tnsInfo->tnsMinBandNumberShort = tnsMinBandNumberShort[fsIndex];
+	}
+}
+
+
+/*****************************************************/
+/* TnsEncode:                                        */
+/*****************************************************/
+void TnsEncode(TnsInfo* tnsInfo,       /* TNS info */
+			   int numberOfBands,       /* Number of bands per window */
+			   int maxSfb,              /* max_sfb */
+			   enum WINDOW_TYPE blockType,   /* block type */
+			   int* sfbOffsetTable,     /* Scalefactor band offset table */
+			   double* spec)            /* Spectral data array */
+{
+	int numberOfWindows,windowSize;
+	int startBand,stopBand,order;    /* Bands over which to apply TNS */
+	int lengthInBands;               /* Length to filter, in bands */
+	int w;
+	int startIndex,length;
+	double gain;
+
+	switch( blockType ) {
+	case ONLY_SHORT_WINDOW :
+
+		/* TNS not used for short blocks currently */
+		tnsInfo->tnsDataPresent = 0;
+		return;
+
+		numberOfWindows = MAX_SHORT_WINDOWS;
+		windowSize = BLOCK_LEN_SHORT;
+		startBand = tnsInfo->tnsMinBandNumberShort;
+		stopBand = numberOfBands; 
+		lengthInBands = stopBand-startBand;
+		order = tnsInfo->tnsMaxOrderShort;
+		startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
+		break;
+
+	default: 
+		numberOfWindows = 1;
+		windowSize = BLOCK_LEN_SHORT;
+		startBand = tnsInfo->tnsMinBandNumberLong;
+		stopBand = numberOfBands;
+		lengthInBands = stopBand - startBand;
+		order = tnsInfo->tnsMaxOrderLong;
+		startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
+		break;
+	}
+	
+	/* Make sure that start and stop bands < maxSfb */
+	/* Make sure that start and stop bands >= 0 */
+	startBand = min(startBand,maxSfb);
+	stopBand = min(stopBand,maxSfb);
+	startBand = max(startBand,0);
+	stopBand = max(stopBand,0);
+
+	tnsInfo->tnsDataPresent = 0;     /* default TNS not used */
+	
+	/* Perform analysis and filtering for each window */
+	for (w=0;w<numberOfWindows;w++) {
+
+		TnsWindowData* windowData = &tnsInfo->windowData[w];
+		TnsFilterData* tnsFilter = windowData->tnsFilter;
+		double* k = tnsFilter->kCoeffs;    /* reflection coeffs */
+		double* a = tnsFilter->aCoeffs;    /* prediction coeffs */
+
+		windowData->numFilters=0;
+		windowData->coefResolution = DEF_TNS_COEFF_RES;
+		startIndex = w * windowSize + sfbOffsetTable[startBand];
+		length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
+		gain = LevinsonDurbin(order,length,&spec[startIndex],k);
+
+		if (gain>DEF_TNS_GAIN_THRESH) {  /* Use TNS */
+			int truncatedOrder;
+			windowData->numFilters++;
+			tnsInfo->tnsDataPresent=1;
+			tnsFilter->direction = 0;
+			tnsFilter->coefCompress = 0;
+			tnsFilter->length = lengthInBands;
+			QuantizeReflectionCoeffs(order,DEF_TNS_COEFF_RES,k,tnsFilter->index);
+			truncatedOrder = TruncateCoeffs(order,DEF_TNS_COEFF_THRESH,k);
+			tnsFilter->order = truncatedOrder;
+			StepUp(truncatedOrder,k,a);    /* Compute predictor coefficients */
+			TnsInvFilter(length,&spec[startIndex],tnsFilter);      /* Filter */      
+		}
+	}
+}
+
+
+/*****************************************************/
+/* TnsEncodeFilterOnly:                              */
+/* This is a stripped-down version of TnsEncode()    */
+/* which performs TNS analysis filtering only        */
+/*****************************************************/
+void TnsEncodeFilterOnly(TnsInfo* tnsInfo,           /* TNS info */
+						 int numberOfBands,          /* Number of bands per window */
+						 int maxSfb,                 /* max_sfb */
+						 enum WINDOW_TYPE blockType, /* block type */
+						 int* sfbOffsetTable,        /* Scalefactor band offset table */
+						 double* spec)               /* Spectral data array */
+{
+	int numberOfWindows,windowSize;
+	int startBand,stopBand;    /* Bands over which to apply TNS */
+	int w;
+	int startIndex,length;
+
+	switch( blockType ) {
+    case ONLY_SHORT_WINDOW :
+		numberOfWindows = MAX_SHORT_WINDOWS;
+		windowSize = BLOCK_LEN_SHORT;
+		startBand = tnsInfo->tnsMinBandNumberShort;
+		stopBand = numberOfBands; 
+		startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
+		break;
+		
+    default: 
+		numberOfWindows = 1;
+		windowSize = BLOCK_LEN_LONG;
+		startBand = tnsInfo->tnsMinBandNumberLong;
+		stopBand = numberOfBands;
+		startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
+		break;
+	}
+	
+	/* Make sure that start and stop bands < maxSfb */
+	/* Make sure that start and stop bands >= 0 */
+	startBand = min(startBand,maxSfb);
+	stopBand = min(stopBand,maxSfb);
+	startBand = max(startBand,0);
+	stopBand = max(stopBand,0);
+	
+	
+	/* Perform filtering for each window */
+	for(w=0;w<numberOfWindows;w++) 
+	{
+		TnsWindowData* windowData = &tnsInfo->windowData[w];
+		TnsFilterData* tnsFilter = windowData->tnsFilter;
+		
+		startIndex = w * windowSize + sfbOffsetTable[startBand];
+		length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
+		
+		if (tnsInfo->tnsDataPresent  &&  windowData->numFilters) {  /* Use TNS */
+			TnsInvFilter(length,&spec[startIndex],tnsFilter);   
+		}
+	}
+}
+
+
+/*****************************************************/
+/* TnsDecodeFilterOnly:                              */
+/* This is a stripped-down version of TnsEncode()    */
+/* which performs TNS synthesis filtering only       */
+/*****************************************************/
+void TnsDecodeFilterOnly(TnsInfo* tnsInfo,           /* TNS info */
+						 int numberOfBands,          /* Number of bands per window */
+						 int maxSfb,                 /* max_sfb */
+						 enum WINDOW_TYPE blockType, /* block type */
+						 int* sfbOffsetTable,        /* Scalefactor band offset table */
+						 double* spec)               /* Spectral data array */
+{
+	int numberOfWindows,windowSize;
+	int startBand,stopBand;    /* Bands over which to apply TNS */
+	int w;
+	int startIndex,length;
+
+	switch( blockType ) {
+    case ONLY_SHORT_WINDOW :
+		numberOfWindows = MAX_SHORT_WINDOWS;
+		windowSize = BLOCK_LEN_SHORT;
+		startBand = tnsInfo->tnsMinBandNumberShort;
+		stopBand = numberOfBands; 
+		startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
+		break;
+		
+    default: 
+		numberOfWindows = 1;
+		windowSize = BLOCK_LEN_LONG;
+		startBand = tnsInfo->tnsMinBandNumberLong;
+		stopBand = numberOfBands;
+		startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
+		stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
+		break;
+	}
+	
+	/* Make sure that start and stop bands < maxSfb */
+	/* Make sure that start and stop bands >= 0 */
+	startBand = min(startBand,maxSfb);
+	stopBand = min(stopBand,maxSfb);
+	startBand = max(startBand,0);
+	stopBand = max(stopBand,0);
+	
+	
+	/* Perform filtering for each window */
+	for(w=0;w<numberOfWindows;w++) 
+	{
+		TnsWindowData* windowData = &tnsInfo->windowData[w];
+		TnsFilterData* tnsFilter = windowData->tnsFilter;
+		
+		startIndex = w * windowSize + sfbOffsetTable[startBand];
+		length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
+		
+		if (tnsInfo->tnsDataPresent  &&  windowData->numFilters) {  /* Use TNS */
+			TnsFilter(length,&spec[startIndex],tnsFilter);   
+		}
+	}
+}
+
+
+/*****************************************************/
+/* TnsFilter:                                        */
+/*   Filter the given spec with specified length     */
+/*   using the coefficients specified in filter.     */
+/*   Not that the order and direction are specified  */
+/*   withing the TNS_FILTER_DATA structure.          */
+/*****************************************************/
+static void TnsFilter(int length,double* spec,TnsFilterData* filter)
+{
+	int i,j,k=0;
+	int order=filter->order;
+	double* a=filter->aCoeffs;
+
+	/* Determine loop parameters for given direction */
+	if (filter->direction) {
+
+		/* Startup, initial state is zero */
+		for (i=length-2;i>(length-1-order);i--) {
+			k++;
+			for (j=1;j<=k;j++) {
+				spec[i]-=spec[i+j]*a[j];
+			}
+		}
+		
+		/* Now filter completely inplace */
+		for	(i=length-1-order;i>=0;i--) {
+			for (j=1;j<=order;j++) {
+				spec[i]-=spec[i+j]*a[j];
+			}
+		}
+
+
+	} else {
+
+		/* Startup, initial state is zero */
+		for (i=1;i<order;i++) {
+			for (j=1;j<=i;j++) {
+				spec[i]-=spec[i-j]*a[j];
+			}
+		}
+		
+		/* Now filter completely inplace */
+		for	(i=order;i<length;i++) {
+			for (j=1;j<=order;j++) {
+				spec[i]-=spec[i-j]*a[j];
+			}
+		}
+	}
+}
+
+
+/********************************************************/
+/* TnsInvFilter:                                        */
+/*   Inverse filter the given spec with specified       */
+/*   length using the coefficients specified in filter. */
+/*   Not that the order and direction are specified     */
+/*   withing the TNS_FILTER_DATA structure.             */
+/********************************************************/
+static void TnsInvFilter(int length,double* spec,TnsFilterData* filter)
+{
+	int i,j,k=0;
+	int order=filter->order;
+	double* a=filter->aCoeffs;
+	double* temp;
+
+    temp = (double *) malloc (length * sizeof (double));
+
+	/* Determine loop parameters for given direction */
+	if (filter->direction) {
+
+		/* Startup, initial state is zero */
+		temp[length-1]=spec[length-1];
+		for (i=length-2;i>(length-1-order);i--) {
+			temp[i]=spec[i];
+			k++;
+			for (j=1;j<=k;j++) {
+				spec[i]+=temp[i+j]*a[j];
+			}
+		}
+		
+		/* Now filter the rest */
+		for	(i=length-1-order;i>=0;i--) {
+			temp[i]=spec[i];
+			for (j=1;j<=order;j++) {
+				spec[i]+=temp[i+j]*a[j];
+			}
+		}
+
+
+	} else {
+
+		/* Startup, initial state is zero */
+		temp[0]=spec[0];
+		for (i=1;i<order;i++) {
+			temp[i]=spec[i];
+			for (j=1;j<=i;j++) {
+				spec[i]+=temp[i-j]*a[j];
+			}
+		}
+		
+		/* Now filter the rest */
+		for	(i=order;i<length;i++) {
+			temp[i]=spec[i];
+			for (j=1;j<=order;j++) {
+				spec[i]+=temp[i-j]*a[j];
+			}
+		}
+	}
+	if (temp) free(temp);
+}
+
+
+
+
+
+/*****************************************************/
+/* TruncateCoeffs:                                   */
+/*   Truncate the given reflection coeffs by zeroing */
+/*   coefficients in the tail with absolute value    */
+/*   less than the specified threshold.  Return the  */
+/*   truncated filter order.                         */
+/*****************************************************/
+static int TruncateCoeffs(int fOrder,double threshold,double* kArray)
+{
+	int i;
+
+	for (i = fOrder; i >= 0; i--) {
+		kArray[i] = (fabs(kArray[i])>threshold) ? kArray[i] : 0.0;
+		if (kArray[i]!=0.0) return i;
+	}
+
+	return 0;
+}
+
+/*****************************************************/
+/* QuantizeReflectionCoeffs:                         */
+/*   Quantize the given array of reflection coeffs   */
+/*   to the specified resolution in bits.            */
+/*****************************************************/
+static void QuantizeReflectionCoeffs(int fOrder,
+							  int coeffRes,
+							  double* kArray,
+							  int* indexArray)
+{
+	double iqfac,iqfac_m;
+	int i;
+
+	iqfac = ((1<<(coeffRes-1))-0.5)/(M_PI/2);
+	iqfac_m = ((1<<(coeffRes-1))+0.5)/(M_PI/2);
+
+	/* Quantize and inverse quantize */
+	for (i=1;i<=fOrder;i++) {
+		indexArray[i] = (int)(0.5+(asin(kArray[i])*((kArray[i]>=0)?iqfac:iqfac_m)));
+		kArray[i] = sin((double)indexArray[i]/((indexArray[i]>=0)?iqfac:iqfac_m));
+	}
+}
+
+/*****************************************************/
+/* Autocorrelation,                                  */
+/*   Compute the autocorrelation function            */
+/*   estimate for the given data.                    */
+/*****************************************************/
+static void Autocorrelation(int maxOrder,        /* Maximum autocorr order */
+					 int dataSize,		  /* Size of the data array */
+					 double* data,		  /* Data array */
+					 double* rArray)  	  /* Autocorrelation array */
+{
+	int order,index;
+
+	for (order=0;order<=maxOrder;order++) {
+		rArray[order]=0.0;
+		for (index=0;index<dataSize;index++) {
+			rArray[order]+=data[index]*data[index+order];
+		}
+		dataSize--;
+	}
+}
+
+
+
+/*****************************************************/
+/* LevinsonDurbin:                                   */
+/*   Compute the reflection coefficients for the     */
+/*   given data using LevinsonDurbin recursion.      */
+/*   Return the prediction gain.                     */
+/*****************************************************/
+static double LevinsonDurbin(int fOrder,          /* Filter order */
+					  int dataSize,		   /* Size of the data array */
+					  double* data,		   /* Data array */
+					  double* kArray)  	   /* Reflection coeff array */
+{
+	int order,i;
+	double signal;
+	double error, kTemp;				/* Prediction error */
+	double aArray1[TNS_MAX_ORDER+1];	/* Predictor coeff array */
+	double aArray2[TNS_MAX_ORDER+1];	/* Predictor coeff array 2 */
+	double rArray[TNS_MAX_ORDER+1];		/* Autocorrelation coeffs */
+	double* aPtr = aArray1;				/* Ptr to aArray1 */
+	double* aLastPtr = aArray2;			/* Ptr to aArray2 */
+	double* aTemp;
+
+	/* Compute autocorrelation coefficients */
+	Autocorrelation(fOrder,dataSize,data,rArray);
+	signal=rArray[0];	/* signal energy */
+
+	/* Set up pointers to current and last iteration */ 
+	/* predictor coefficients.						 */
+	aPtr = aArray1;
+	aLastPtr = aArray2;
+	/* If there is no signal energy, return */
+	if (!signal) {
+		kArray[0]=1.0;
+		for (order=1;order<=fOrder;order++) {
+			kArray[order]=0.0;
+		}
+		return 0;
+
+	} else {
+
+		/* Set up first iteration */
+		kArray[0]=1.0;
+		aPtr[0]=1.0;		/* Ptr to predictor coeffs, current iteration*/
+		aLastPtr[0]=1.0;	/* Ptr to predictor coeffs, last iteration */
+		error=rArray[0];
+
+		/* Now perform recursion */
+		for (order=1;order<=fOrder;order++) {
+			kTemp = aLastPtr[0]*rArray[order-0];
+			for (i=1;i<order;i++) {
+				kTemp += aLastPtr[i]*rArray[order-i];
+			}
+			kTemp = -kTemp/error;
+			kArray[order]=kTemp;
+			aPtr[order]=kTemp;
+			for (i=1;i<order;i++) {
+				aPtr[i] = aLastPtr[i] + kTemp*aLastPtr[order-i];
+			}
+			error = error * (1 - kTemp*kTemp);
+			
+			/* Now make current iteration the last one */
+			aTemp=aLastPtr;
+			aLastPtr=aPtr;		/* Current becomes last */
+			aPtr=aTemp;			/* Last becomes current */
+		}
+		return signal/error;	/* return the gain */
+	}
+}
+
+
+/*****************************************************/
+/* StepUp:                                           */
+/*   Convert reflection coefficients into            */
+/*   predictor coefficients.                         */
+/*****************************************************/
+static void StepUp(int fOrder,double* kArray,double* aArray)
+{
+	double aTemp[TNS_MAX_ORDER+2];
+	int i,order;
+
+	aArray[0]=1.0;
+	aTemp[0]=1.0;
+	for (order=1;order<=fOrder;order++) {
+		aArray[order]=0.0;
+		for (i=1;i<=order;i++) {
+			aTemp[i] = aArray[i] + kArray[order]*aArray[order-i];
+		}
+		for (i=1;i<=order;i++) {
+			aArray[i]=aTemp[i];
+		}
+	}
+}
--- /dev/null
+++ b/libfaac/tns.h
@@ -1,0 +1,61 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * $Id: tns.h,v 1.1 2001/02/28 18:39:34 menno Exp $
+ */
+
+#ifndef TNS_H
+#define TNS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*************************/
+/* Function prototypes   */
+/*************************/
+static void Autocorrelation(int maxOrder,        /* Maximum autocorr order */
+					 int dataSize,		  /* Size of the data array */
+					 double* data,		  /* Data array */
+					 double* rArray);	  /* Autocorrelation array */
+
+static double LevinsonDurbin(int maxOrder,        /* Maximum filter order */
+					  int dataSize,		   /* Size of the data array */
+					  double* data,		   /* Data array */
+					  double* kArray);	   /* Reflection coeff array */
+
+static void StepUp(int fOrder, double* kArray, double* aArray);
+
+static void QuantizeReflectionCoeffs(int fOrder,int coeffRes,double* rArray,int* indexArray);
+static int TruncateCoeffs(int fOrder,double threshold,double* kArray);
+static void TnsFilter(int length,double* spec,TnsFilterData* filter);
+static void TnsInvFilter(int length,double* spec,TnsFilterData* filter);
+void TnsInit(faacEncHandle hEncoder);
+void TnsEncode(TnsInfo* tnsInfo, int numberOfBands,int maxSfb,enum WINDOW_TYPE blockType,
+			   int* sfbOffsetTable,double* spec);
+void TnsEncodeFilterOnly(TnsInfo* tnsInfo, int numberOfBands, int maxSfb,
+						 enum WINDOW_TYPE blockType, int *sfbOffsetTable, double *spec);
+void TnsDecodeFilterOnly(TnsInfo* tnsInfo, int numberOfBands, int maxSfb,
+						 enum WINDOW_TYPE blockType, int *sfbOffsetTable, double *spec);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TNS_H */
--- a/libfaac/util.c
+++ b/libfaac/util.c
@@ -16,17 +16,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: util.c,v 1.5 2001/02/26 14:31:45 oxygene Exp $
+ * $Id: util.c,v 1.6 2001/02/28 18:39:34 menno Exp $
  */
 
 #include <math.h>
 
-#ifndef max
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-#endif
-#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif
+#include "util.h"
 
 /* Returns the sample rate index */
 int GetSRIndex(unsigned int sampleRate)
--- a/libfaac/util.h
+++ b/libfaac/util.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: util.h,v 1.3 2001/02/12 14:39:14 menno Exp $
+ * $Id: util.h,v 1.4 2001/02/28 18:39:34 menno Exp $
  */
 
 #ifndef UTIL_H
@@ -26,6 +26,17 @@
 extern "C" {
 #endif /* __cplusplus */
 
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef M_PI
+#define M_PI        3.14159265358979323846
+#endif
 
 
 int GetSRIndex(unsigned int sampleRate);