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);