"Fossies" - the Fresh Open Source Software Archive

Member "faac-1_30/libfaac/tns.c" (16 Oct 2019, 22084 Bytes) of package /linux/misc/faac-1_30.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tns.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.28_vs_1.29.9.2.

    1 /**********************************************************************
    2 
    3 This software module was originally developed by Texas Instruments
    4 and edited by         in the course of
    5 development of the MPEG-2 NBC/MPEG-4 Audio standard
    6 ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
    7 implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
    8 as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
    9 users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
   10 software module or modifications thereof for use in hardware or
   11 software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
   12 standards. Those intending to use this software module in hardware or
   13 software products are advised that this use may infringe existing
   14 patents. The original developer of this software module and his/her
   15 company, the subsequent editors and their companies, and ISO/IEC have
   16 no liability for use of this software module or modifications thereof
   17 in an implementation. Copyright is not released for non MPEG-2
   18 NBC/MPEG-4 Audio conforming products. The original developer retains
   19 full right to use the code for his/her own purpose, assign or donate
   20 the code to a third party and to inhibit third party from using the
   21 code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
   22 copyright notice must be included in all copies or derivative works.
   23 
   24 Copyright (c) 1997.
   25 **********************************************************************/
   26 /*
   27  * $Id: tns.c,v 1.11 2012/03/01 18:34:17 knik Exp $
   28  */
   29 
   30 #include <math.h>
   31 #include "frame.h"
   32 #include "coder.h"
   33 #include "bitstream.h"
   34 #include "tns.h"
   35 #include "util.h"
   36 
   37 /***********************************************/
   38 /* TNS Profile/Frequency Dependent Parameters  */
   39 /***********************************************/
   40 /* Limit bands to > 2.0 kHz */
   41 static unsigned short tnsMinBandNumberLong[12] =
   42 { 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
   43 static unsigned short tnsMinBandNumberShort[12] =
   44 { 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
   45 
   46 /**************************************/
   47 /* Main/Low Profile TNS Parameters    */
   48 /**************************************/
   49 static unsigned short tnsMaxBandsLongMainLow[12] =
   50 { 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
   51 
   52 static unsigned short tnsMaxBandsShortMainLow[12] =
   53 { 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
   54 
   55 static unsigned short tnsMaxOrderLongMain = 20;
   56 static unsigned short tnsMaxOrderLongLow = 12;
   57 static unsigned short tnsMaxOrderShortMainLow = 7;
   58 
   59 
   60 /*************************/
   61 /* Function prototypes   */
   62 /*************************/
   63 static void Autocorrelation(int maxOrder,        /* Maximum autocorr order */
   64                      int dataSize,        /* Size of the data array */
   65                      double* data,        /* Data array */
   66                      double* rArray);     /* Autocorrelation array */
   67 
   68 static double LevinsonDurbin(int maxOrder,        /* Maximum filter order */
   69                       int dataSize,        /* Size of the data array */
   70                       double* data,        /* Data array */
   71                       double* kArray);     /* Reflection coeff array */
   72 
   73 static void StepUp(int fOrder, double* kArray, double* aArray);
   74 
   75 static void QuantizeReflectionCoeffs(int fOrder,int coeffRes,double* rArray,int* indexArray);
   76 static int TruncateCoeffs(int fOrder,double threshold,double* kArray);
   77 static void TnsFilter(int length,double* spec,TnsFilterData* filter);
   78 static void TnsInvFilter(int length,double* spec,TnsFilterData* filter);
   79 
   80 
   81 /*****************************************************/
   82 /* InitTns:                                          */
   83 /*****************************************************/
   84 void TnsInit(faacEncStruct* hEncoder)
   85 {
   86     unsigned int channel;
   87     int fsIndex = hEncoder->sampleRateIdx;
   88     int profile = hEncoder->config.aacObjectType;
   89 
   90     for (channel = 0; channel < hEncoder->numChannels; channel++) {
   91         TnsInfo *tnsInfo = &hEncoder->coderInfo[channel].tnsInfo;
   92 
   93         switch( profile ) {
   94         case MAIN:
   95         case LTP:
   96             tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
   97             tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
   98             if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */
   99                 tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongMain;
  100             } else { /* MPEG4 */
  101                 if (fsIndex <= 5) /* fs > 32000Hz */
  102                     tnsInfo->tnsMaxOrderLong = 12;
  103                 else
  104                     tnsInfo->tnsMaxOrderLong = 20;
  105             }
  106             tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
  107             break;
  108         case LOW :
  109             tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
  110             tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
  111             if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */
  112                 tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongLow;
  113             } else { /* MPEG4 */
  114                 if (fsIndex <= 5) /* fs > 32000Hz */
  115                     tnsInfo->tnsMaxOrderLong = 12;
  116                 else
  117                     tnsInfo->tnsMaxOrderLong = 20;
  118             }
  119             tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
  120             break;
  121         }
  122         tnsInfo->tnsMinBandNumberLong = tnsMinBandNumberLong[fsIndex];
  123         tnsInfo->tnsMinBandNumberShort = tnsMinBandNumberShort[fsIndex];
  124     }
  125 }
  126 
  127 
  128 /*****************************************************/
  129 /* TnsEncode:                                        */
  130 /*****************************************************/
  131 void TnsEncode(TnsInfo* tnsInfo,       /* TNS info */
  132                int numberOfBands,       /* Number of bands per window */
  133                int maxSfb,              /* max_sfb */
  134                enum WINDOW_TYPE blockType,   /* block type */
  135                int* sfbOffsetTable,     /* Scalefactor band offset table */
  136                double* spec)            /* Spectral data array */
  137 {
  138     int numberOfWindows,windowSize;
  139     int startBand,stopBand,order;    /* Bands over which to apply TNS */
  140     int lengthInBands;               /* Length to filter, in bands */
  141     int w;
  142     int startIndex,length;
  143     double gain;
  144 
  145     switch( blockType ) {
  146     case ONLY_SHORT_WINDOW :
  147 
  148         /* TNS not used for short blocks currently */
  149         tnsInfo->tnsDataPresent = 0;
  150         return;
  151 
  152         numberOfWindows = MAX_SHORT_WINDOWS;
  153         windowSize = BLOCK_LEN_SHORT;
  154         startBand = tnsInfo->tnsMinBandNumberShort;
  155         stopBand = numberOfBands;
  156         lengthInBands = stopBand-startBand;
  157         order = tnsInfo->tnsMaxOrderShort;
  158         startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
  159         stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
  160         break;
  161 
  162     default:
  163         numberOfWindows = 1;
  164         windowSize = BLOCK_LEN_SHORT;
  165         startBand = tnsInfo->tnsMinBandNumberLong;
  166         stopBand = numberOfBands;
  167         lengthInBands = stopBand - startBand;
  168         order = tnsInfo->tnsMaxOrderLong;
  169         startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
  170         stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
  171         break;
  172     }
  173 
  174     /* Make sure that start and stop bands < maxSfb */
  175     /* Make sure that start and stop bands >= 0 */
  176     startBand = min(startBand,maxSfb);
  177     stopBand = min(stopBand,maxSfb);
  178     startBand = max(startBand,0);
  179     stopBand = max(stopBand,0);
  180 
  181     tnsInfo->tnsDataPresent = 0;     /* default TNS not used */
  182 
  183     /* Perform analysis and filtering for each window */
  184     for (w=0;w<numberOfWindows;w++) {
  185 
  186         TnsWindowData* windowData = &tnsInfo->windowData[w];
  187         TnsFilterData* tnsFilter = windowData->tnsFilter;
  188         double* k = tnsFilter->kCoeffs;    /* reflection coeffs */
  189         double* a = tnsFilter->aCoeffs;    /* prediction coeffs */
  190 
  191         windowData->numFilters=0;
  192         windowData->coefResolution = DEF_TNS_COEFF_RES;
  193         startIndex = w * windowSize + sfbOffsetTable[startBand];
  194         length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
  195         gain = LevinsonDurbin(order,length,&spec[startIndex],k);
  196 
  197         if (gain>DEF_TNS_GAIN_THRESH) {  /* Use TNS */
  198             int truncatedOrder;
  199             windowData->numFilters++;
  200             tnsInfo->tnsDataPresent=1;
  201             tnsFilter->direction = 0;
  202             tnsFilter->coefCompress = 0;
  203             tnsFilter->length = lengthInBands;
  204             QuantizeReflectionCoeffs(order,DEF_TNS_COEFF_RES,k,tnsFilter->index);
  205             truncatedOrder = TruncateCoeffs(order,DEF_TNS_COEFF_THRESH,k);
  206             tnsFilter->order = truncatedOrder;
  207             StepUp(truncatedOrder,k,a);    /* Compute predictor coefficients */
  208             TnsInvFilter(length,&spec[startIndex],tnsFilter);      /* Filter */
  209         }
  210     }
  211 }
  212 
  213 
  214 /*****************************************************/
  215 /* TnsEncodeFilterOnly:                              */
  216 /* This is a stripped-down version of TnsEncode()    */
  217 /* which performs TNS analysis filtering only        */
  218 /*****************************************************/
  219 void TnsEncodeFilterOnly(TnsInfo* tnsInfo,           /* TNS info */
  220                          int numberOfBands,          /* Number of bands per window */
  221                          int maxSfb,                 /* max_sfb */
  222                          enum WINDOW_TYPE blockType, /* block type */
  223                          int* sfbOffsetTable,        /* Scalefactor band offset table */
  224                          double* spec)               /* Spectral data array */
  225 {
  226     int numberOfWindows,windowSize;
  227     int startBand,stopBand;    /* Bands over which to apply TNS */
  228     int w;
  229     int startIndex,length;
  230 
  231     switch( blockType ) {
  232     case ONLY_SHORT_WINDOW :
  233         numberOfWindows = MAX_SHORT_WINDOWS;
  234         windowSize = BLOCK_LEN_SHORT;
  235         startBand = tnsInfo->tnsMinBandNumberShort;
  236         stopBand = numberOfBands;
  237         startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
  238         stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
  239         break;
  240 
  241     default:
  242         numberOfWindows = 1;
  243         windowSize = BLOCK_LEN_LONG;
  244         startBand = tnsInfo->tnsMinBandNumberLong;
  245         stopBand = numberOfBands;
  246         startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
  247         stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
  248         break;
  249     }
  250 
  251     /* Make sure that start and stop bands < maxSfb */
  252     /* Make sure that start and stop bands >= 0 */
  253     startBand = min(startBand,maxSfb);
  254     stopBand = min(stopBand,maxSfb);
  255     startBand = max(startBand,0);
  256     stopBand = max(stopBand,0);
  257 
  258 
  259     /* Perform filtering for each window */
  260     for(w=0;w<numberOfWindows;w++)
  261     {
  262         TnsWindowData* windowData = &tnsInfo->windowData[w];
  263         TnsFilterData* tnsFilter = windowData->tnsFilter;
  264 
  265         startIndex = w * windowSize + sfbOffsetTable[startBand];
  266         length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
  267 
  268         if (tnsInfo->tnsDataPresent  &&  windowData->numFilters) {  /* Use TNS */
  269             TnsInvFilter(length,&spec[startIndex],tnsFilter);
  270         }
  271     }
  272 }
  273 
  274 
  275 /*****************************************************/
  276 /* TnsDecodeFilterOnly:                              */
  277 /* This is a stripped-down version of TnsEncode()    */
  278 /* which performs TNS synthesis filtering only       */
  279 /*****************************************************/
  280 void TnsDecodeFilterOnly(TnsInfo* tnsInfo,           /* TNS info */
  281                          int numberOfBands,          /* Number of bands per window */
  282                          int maxSfb,                 /* max_sfb */
  283                          enum WINDOW_TYPE blockType, /* block type */
  284                          int* sfbOffsetTable,        /* Scalefactor band offset table */
  285                          double* spec)               /* Spectral data array */
  286 {
  287     int numberOfWindows,windowSize;
  288     int startBand,stopBand;    /* Bands over which to apply TNS */
  289     int w;
  290     int startIndex,length;
  291 
  292     switch( blockType ) {
  293     case ONLY_SHORT_WINDOW :
  294         numberOfWindows = MAX_SHORT_WINDOWS;
  295         windowSize = BLOCK_LEN_SHORT;
  296         startBand = tnsInfo->tnsMinBandNumberShort;
  297         stopBand = numberOfBands;
  298         startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
  299         stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
  300         break;
  301 
  302     default:
  303         numberOfWindows = 1;
  304         windowSize = BLOCK_LEN_LONG;
  305         startBand = tnsInfo->tnsMinBandNumberLong;
  306         stopBand = numberOfBands;
  307         startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
  308         stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
  309         break;
  310     }
  311 
  312     /* Make sure that start and stop bands < maxSfb */
  313     /* Make sure that start and stop bands >= 0 */
  314     startBand = min(startBand,maxSfb);
  315     stopBand = min(stopBand,maxSfb);
  316     startBand = max(startBand,0);
  317     stopBand = max(stopBand,0);
  318 
  319 
  320     /* Perform filtering for each window */
  321     for(w=0;w<numberOfWindows;w++)
  322     {
  323         TnsWindowData* windowData = &tnsInfo->windowData[w];
  324         TnsFilterData* tnsFilter = windowData->tnsFilter;
  325 
  326         startIndex = w * windowSize + sfbOffsetTable[startBand];
  327         length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
  328 
  329         if (tnsInfo->tnsDataPresent  &&  windowData->numFilters) {  /* Use TNS */
  330             TnsFilter(length,&spec[startIndex],tnsFilter);
  331         }
  332     }
  333 }
  334 
  335 
  336 /*****************************************************/
  337 /* TnsFilter:                                        */
  338 /*   Filter the given spec with specified length     */
  339 /*   using the coefficients specified in filter.     */
  340 /*   Not that the order and direction are specified  */
  341 /*   withing the TNS_FILTER_DATA structure.          */
  342 /*****************************************************/
  343 static void TnsFilter(int length,double* spec,TnsFilterData* filter)
  344 {
  345     int i,j,k=0;
  346     int order=filter->order;
  347     double* a=filter->aCoeffs;
  348 
  349     /* Determine loop parameters for given direction */
  350     if (filter->direction) {
  351 
  352         /* Startup, initial state is zero */
  353         for (i=length-2;i>(length-1-order);i--) {
  354             k++;
  355             for (j=1;j<=k;j++) {
  356                 spec[i]-=spec[i+j]*a[j];
  357             }
  358         }
  359 
  360         /* Now filter completely inplace */
  361         for (i=length-1-order;i>=0;i--) {
  362             for (j=1;j<=order;j++) {
  363                 spec[i]-=spec[i+j]*a[j];
  364             }
  365         }
  366 
  367 
  368     } else {
  369 
  370         /* Startup, initial state is zero */
  371         for (i=1;i<order;i++) {
  372             for (j=1;j<=i;j++) {
  373                 spec[i]-=spec[i-j]*a[j];
  374             }
  375         }
  376 
  377         /* Now filter completely inplace */
  378         for (i=order;i<length;i++) {
  379             for (j=1;j<=order;j++) {
  380                 spec[i]-=spec[i-j]*a[j];
  381             }
  382         }
  383     }
  384 }
  385 
  386 
  387 /********************************************************/
  388 /* TnsInvFilter:                                        */
  389 /*   Inverse filter the given spec with specified       */
  390 /*   length using the coefficients specified in filter. */
  391 /*   Not that the order and direction are specified     */
  392 /*   withing the TNS_FILTER_DATA structure.             */
  393 /********************************************************/
  394 static void TnsInvFilter(int length,double* spec,TnsFilterData* filter)
  395 {
  396     int i,j,k=0;
  397     int order=filter->order;
  398     double* a=filter->aCoeffs;
  399     double* temp;
  400 
  401     temp = (double *)AllocMemory(length * sizeof (double));
  402 
  403     /* Determine loop parameters for given direction */
  404     if (filter->direction) {
  405 
  406         /* Startup, initial state is zero */
  407         temp[length-1]=spec[length-1];
  408         for (i=length-2;i>(length-1-order);i--) {
  409             temp[i]=spec[i];
  410             k++;
  411             for (j=1;j<=k;j++) {
  412                 spec[i]+=temp[i+j]*a[j];
  413             }
  414         }
  415 
  416         /* Now filter the rest */
  417         for (i=length-1-order;i>=0;i--) {
  418             temp[i]=spec[i];
  419             for (j=1;j<=order;j++) {
  420                 spec[i]+=temp[i+j]*a[j];
  421             }
  422         }
  423 
  424 
  425     } else {
  426 
  427         /* Startup, initial state is zero */
  428         temp[0]=spec[0];
  429         for (i=1;i<order;i++) {
  430             temp[i]=spec[i];
  431             for (j=1;j<=i;j++) {
  432                 spec[i]+=temp[i-j]*a[j];
  433             }
  434         }
  435 
  436         /* Now filter the rest */
  437         for (i=order;i<length;i++) {
  438             temp[i]=spec[i];
  439             for (j=1;j<=order;j++) {
  440                 spec[i]+=temp[i-j]*a[j];
  441             }
  442         }
  443     }
  444     if (temp) FreeMemory(temp);
  445 }
  446 
  447 
  448 
  449 
  450 
  451 /*****************************************************/
  452 /* TruncateCoeffs:                                   */
  453 /*   Truncate the given reflection coeffs by zeroing */
  454 /*   coefficients in the tail with absolute value    */
  455 /*   less than the specified threshold.  Return the  */
  456 /*   truncated filter order.                         */
  457 /*****************************************************/
  458 static int TruncateCoeffs(int fOrder,double threshold,double* kArray)
  459 {
  460     int i;
  461 
  462     for (i = fOrder; i >= 0; i--) {
  463         kArray[i] = (fabs(kArray[i])>threshold) ? kArray[i] : 0.0;
  464         if (kArray[i]!=0.0) return i;
  465     }
  466 
  467     return 0;
  468 }
  469 
  470 /*****************************************************/
  471 /* QuantizeReflectionCoeffs:                         */
  472 /*   Quantize the given array of reflection coeffs   */
  473 /*   to the specified resolution in bits.            */
  474 /*****************************************************/
  475 static void QuantizeReflectionCoeffs(int fOrder,
  476                               int coeffRes,
  477                               double* kArray,
  478                               int* indexArray)
  479 {
  480     double iqfac,iqfac_m;
  481     int i;
  482 
  483     iqfac = ((1<<(coeffRes-1))-0.5)/(M_PI/2);
  484     iqfac_m = ((1<<(coeffRes-1))+0.5)/(M_PI/2);
  485 
  486     /* Quantize and inverse quantize */
  487     for (i=1;i<=fOrder;i++) {
  488         indexArray[i] = (kArray[i]>=0)?(int)(0.5+(asin(kArray[i])*iqfac)):(int)(-0.5+(asin(kArray[i])*iqfac_m));
  489         kArray[i] = sin((double)indexArray[i]/((indexArray[i]>=0)?iqfac:iqfac_m));
  490     }
  491 }
  492 
  493 /*****************************************************/
  494 /* Autocorrelation,                                  */
  495 /*   Compute the autocorrelation function            */
  496 /*   estimate for the given data.                    */
  497 /*****************************************************/
  498 static void Autocorrelation(int maxOrder,        /* Maximum autocorr order */
  499                      int dataSize,        /* Size of the data array */
  500                      double* data,        /* Data array */
  501                      double* rArray)      /* Autocorrelation array */
  502 {
  503     int order,index;
  504 
  505     for (order=0;order<=maxOrder;order++) {
  506         rArray[order]=0.0;
  507         for (index=0;index<dataSize;index++) {
  508             rArray[order]+=data[index]*data[index+order];
  509         }
  510         dataSize--;
  511     }
  512 }
  513 
  514 
  515 
  516 /*****************************************************/
  517 /* LevinsonDurbin:                                   */
  518 /*   Compute the reflection coefficients for the     */
  519 /*   given data using LevinsonDurbin recursion.      */
  520 /*   Return the prediction gain.                     */
  521 /*****************************************************/
  522 static double LevinsonDurbin(int fOrder,          /* Filter order */
  523                       int dataSize,        /* Size of the data array */
  524                       double* data,        /* Data array */
  525                       double* kArray)      /* Reflection coeff array */
  526 {
  527     int order,i;
  528     double signal;
  529     double error, kTemp;                /* Prediction error */
  530     double aArray1[TNS_MAX_ORDER+1];    /* Predictor coeff array */
  531     double aArray2[TNS_MAX_ORDER+1];    /* Predictor coeff array 2 */
  532     double rArray[TNS_MAX_ORDER+1];     /* Autocorrelation coeffs */
  533     double* aPtr = aArray1;             /* Ptr to aArray1 */
  534     double* aLastPtr = aArray2;         /* Ptr to aArray2 */
  535     double* aTemp;
  536 
  537     /* Compute autocorrelation coefficients */
  538     Autocorrelation(fOrder,dataSize,data,rArray);
  539     signal=rArray[0];   /* signal energy */
  540 
  541     /* Set up pointers to current and last iteration */
  542     /* predictor coefficients.                       */
  543     aPtr = aArray1;
  544     aLastPtr = aArray2;
  545     /* If there is no signal energy, return */
  546     if (!signal) {
  547         kArray[0]=1.0;
  548         for (order=1;order<=fOrder;order++) {
  549             kArray[order]=0.0;
  550         }
  551         return 0;
  552 
  553     } else {
  554 
  555         /* Set up first iteration */
  556         kArray[0]=1.0;
  557         aPtr[0]=1.0;        /* Ptr to predictor coeffs, current iteration*/
  558         aLastPtr[0]=1.0;    /* Ptr to predictor coeffs, last iteration */
  559         error=rArray[0];
  560 
  561         /* Now perform recursion */
  562         for (order=1;order<=fOrder;order++) {
  563             kTemp = aLastPtr[0]*rArray[order-0];
  564             for (i=1;i<order;i++) {
  565                 kTemp += aLastPtr[i]*rArray[order-i];
  566             }
  567             kTemp = -kTemp/error;
  568             kArray[order]=kTemp;
  569             aPtr[order]=kTemp;
  570             for (i=1;i<order;i++) {
  571                 aPtr[i] = aLastPtr[i] + kTemp*aLastPtr[order-i];
  572             }
  573             error = error * (1 - kTemp*kTemp);
  574 
  575             /* Now make current iteration the last one */
  576             aTemp=aLastPtr;
  577             aLastPtr=aPtr;      /* Current becomes last */
  578             aPtr=aTemp;         /* Last becomes current */
  579         }
  580         return signal/error;    /* return the gain */
  581     }
  582 }
  583 
  584 
  585 /*****************************************************/
  586 /* StepUp:                                           */
  587 /*   Convert reflection coefficients into            */
  588 /*   predictor coefficients.                         */
  589 /*****************************************************/
  590 static void StepUp(int fOrder,double* kArray,double* aArray)
  591 {
  592     double aTemp[TNS_MAX_ORDER+2];
  593     int i,order;
  594 
  595     aArray[0]=1.0;
  596     aTemp[0]=1.0;
  597     for (order=1;order<=fOrder;order++) {
  598         aArray[order]=0.0;
  599         for (i=1;i<=order;i++) {
  600             aTemp[i] = aArray[i] + kArray[order]*aArray[order-i];
  601         }
  602         for (i=1;i<=order;i++) {
  603             aArray[i]=aTemp[i];
  604         }
  605     }
  606 }