Sigrid Solveig HaflínudóttirPlan 9 portf19cd855 years agoHistory
605 lines · 21.5 KB · C
RawDownload
/********************************************************************** This software module was originally developed by Texas Instrumentsand edited by         in the course ofdevelopment of the MPEG-2 NBC/MPEG-4 Audio standardISO/IEC 13818-7, 14496-1,2 and 3. This software module is animplementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio toolsas specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC givesusers of the MPEG-2 NBC/MPEG-4 Audio standards free license to thissoftware module or modifications thereof for use in hardware orsoftware products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audiostandards. Those intending to use this software module in hardware orsoftware products are advised that this use may infringe existingpatents. The original developer of this software module and his/hercompany, the subsequent editors and their companies, and ISO/IEC haveno liability for use of this software module or modifications thereofin an implementation. Copyright is not released for non MPEG-2NBC/MPEG-4 Audio conforming products. The original developer retainsfull right to use the code for his/her own purpose, assign or donatethe code to a third party and to inhibit third party from using thecode for non MPEG-2 NBC/MPEG-4 Audio conforming products. Thiscopyright notice must be included in all copies or derivative works. Copyright (c) 1997.**********************************************************************//* * $Id: tns.c,v 1.11 2012/03/01 18:34:17 knik Exp $ */ #include "util.h"#include "frame.h"#include "coder.h"#include "bitstream.h"#include "tns.h" /***********************************************//* TNS Profile/Frequency Dependent Parameters  *//***********************************************//* 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;  /*************************//* 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);  /*****************************************************//* InitTns:                                          *//*****************************************************/void TnsInit(faacEncStruct* hEncoder){    unsigned int channel;    int fsIndex = hEncoder->sampleRateIdx;    int profile = hEncoder->config.aacObjectType;     for (channel = 0; channel < hEncoder->numChannels; channel++) {        TnsInfo *tnsInfo = &hEncoder->coderInfo[channel].tnsInfo;         switch( profile ) {        case MAIN:        case LTP:            tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];            tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];            if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */                tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongMain;            } else { /* MPEG4 */                if (fsIndex <= 5) /* fs > 32000Hz */                    tnsInfo->tnsMaxOrderLong = 12;                else                    tnsInfo->tnsMaxOrderLong = 20;            }            tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;            break;        case LOW :            tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];            tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];            if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */                tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongLow;            } else { /* MPEG4 */                if (fsIndex <= 5) /* fs > 32000Hz */                    tnsInfo->tnsMaxOrderLong = 12;                else                    tnsInfo->tnsMaxOrderLong = 20;            }            tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;            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 *)AllocMemory(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) FreeMemory(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] = (kArray[i]>=0)?(int)(0.5+(asin(kArray[i])*iqfac)):(int)(-0.5+(asin(kArray[i])*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 */

Lines 1–500 of 605.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t