"Fossies" - the Fresh Open Source Software Archive

Member "faac-1_30/libfaac/blockswitch.c" (16 Oct 2019, 12454 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 "blockswitch.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * FAAC - Freeware Advanced Audio Coder
    3  * Copyright (C) 2002 Krzysztof Nikiel
    4  *
    5  * This library is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Lesser General Public
    7  * License as published by the Free Software Foundation; either
    8  * version 2.1 of the License, or (at your option) any later version.
    9  *
   10  * This library is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  * Lesser General Public License for more details.
   14 
   15  * You should have received a copy of the GNU Lesser General Public
   16  * License along with this library; if not, write to the Free Software
   17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   18  *
   19  * $Id: psychkni.c,v 1.19 2012/03/01 18:34:17 knik Exp $
   20  */
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <math.h>
   24 
   25 #include "blockswitch.h"
   26 #include "coder.h"
   27 #include "fft.h"
   28 #include "util.h"
   29 #include <faac.h>
   30 
   31 typedef float psyfloat;
   32 
   33 typedef struct
   34 {
   35   /* bandwidth */
   36   int bandS;
   37   int lastband;
   38 
   39   /* band volumes */
   40   psyfloat *engPrev[8];
   41   psyfloat *eng[8];
   42   psyfloat *engNext[8];
   43   psyfloat *engNext2[8];
   44 }
   45 psydata_t;
   46 
   47 
   48 static void Hann(GlobalPsyInfo * gpsyInfo, double *inSamples, int size)
   49 {
   50   int i;
   51 
   52   /* Applying Hann window */
   53   if (size == BLOCK_LEN_LONG * 2)
   54   {
   55     for (i = 0; i < size; i++)
   56       inSamples[i] *= gpsyInfo->hannWindow[i];
   57   }
   58   else
   59   {
   60     for (i = 0; i < size; i++)
   61       inSamples[i] *= gpsyInfo->hannWindowS[i];
   62   }
   63 }
   64 
   65 #define PRINTSTAT 0
   66 #if PRINTSTAT
   67 static struct {
   68     int tot;
   69     int s;
   70 } frames;
   71 #endif
   72 
   73 static void PsyCheckShort(PsyInfo * psyInfo, double quality)
   74 {
   75   enum {PREVS = 2, NEXTS = 2};
   76   psydata_t *psydata = psyInfo->data;
   77   int lastband = psydata->lastband;
   78   int firstband = 2;
   79   int sfb, win;
   80   psyfloat *lasteng;
   81 
   82   psyInfo->block_type = ONLY_LONG_WINDOW;
   83 
   84   lasteng = NULL;
   85   for (win = 0; win < PREVS + 8 + NEXTS; win++)
   86   {
   87       psyfloat *eng;
   88 
   89       if (win < PREVS)
   90           eng = psydata->engPrev[win + 8 - PREVS];
   91       else if (win < (PREVS + 8))
   92           eng = psydata->eng[win - PREVS];
   93       else
   94           eng = psydata->engNext[win - PREVS - 8];
   95 
   96       if (lasteng)
   97       {
   98           double toteng = 0.0;
   99           double volchg = 0.0;
  100 
  101           for (sfb = firstband; sfb < lastband; sfb++)
  102           {
  103               toteng += (eng[sfb] < lasteng[sfb]) ? eng[sfb] : lasteng[sfb];
  104               volchg += fabs(eng[sfb] - lasteng[sfb]);
  105           }
  106 
  107           if ((volchg / toteng * quality) > 3.0)
  108           {
  109               psyInfo->block_type = ONLY_SHORT_WINDOW;
  110               break;
  111           }
  112       }
  113       lasteng = eng;
  114   }
  115 
  116 #if PRINTSTAT
  117   frames.tot++;
  118   if (psyInfo->block_type == ONLY_SHORT_WINDOW)
  119       frames.s++;
  120 #endif
  121 }
  122 
  123 static void PsyInit(GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, unsigned int numChannels,
  124             unsigned int sampleRate, int *cb_width_long, int num_cb_long,
  125             int *cb_width_short, int num_cb_short)
  126 {
  127   unsigned int channel;
  128   int i, j, size;
  129 
  130   gpsyInfo->hannWindow =
  131     (double *) AllocMemory(2 * BLOCK_LEN_LONG * sizeof(double));
  132   gpsyInfo->hannWindowS =
  133     (double *) AllocMemory(2 * BLOCK_LEN_SHORT * sizeof(double));
  134 
  135   for (i = 0; i < BLOCK_LEN_LONG * 2; i++)
  136     gpsyInfo->hannWindow[i] = 0.5 * (1 - cos(2.0 * M_PI * (i + 0.5) /
  137                          (BLOCK_LEN_LONG * 2)));
  138   for (i = 0; i < BLOCK_LEN_SHORT * 2; i++)
  139     gpsyInfo->hannWindowS[i] = 0.5 * (1 - cos(2.0 * M_PI * (i + 0.5) /
  140                           (BLOCK_LEN_SHORT * 2)));
  141   gpsyInfo->sampleRate = (double) sampleRate;
  142 
  143   for (channel = 0; channel < numChannels; channel++)
  144   {
  145     psydata_t *psydata = AllocMemory(sizeof(psydata_t));
  146     psyInfo[channel].data = psydata;
  147   }
  148 
  149   size = BLOCK_LEN_LONG;
  150   for (channel = 0; channel < numChannels; channel++)
  151   {
  152     psyInfo[channel].size = size;
  153 
  154     psyInfo[channel].prevSamples =
  155       (double *) AllocMemory(size * sizeof(double));
  156     memset(psyInfo[channel].prevSamples, 0, size * sizeof(double));
  157   }
  158 
  159   size = BLOCK_LEN_SHORT;
  160   for (channel = 0; channel < numChannels; channel++)
  161   {
  162     psydata_t *psydata = psyInfo[channel].data;
  163 
  164     psyInfo[channel].sizeS = size;
  165 
  166     for (j = 0; j < 8; j++)
  167     {
  168       psydata->engPrev[j] =
  169             (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat));
  170       memset(psydata->engPrev[j], 0, NSFB_SHORT * sizeof(psyfloat));
  171       psydata->eng[j] =
  172           (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat));
  173       memset(psydata->eng[j], 0, NSFB_SHORT * sizeof(psyfloat));
  174       psydata->engNext[j] =
  175           (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat));
  176       memset(psydata->engNext[j], 0, NSFB_SHORT * sizeof(psyfloat));
  177       psydata->engNext2[j] =
  178           (psyfloat *) AllocMemory(NSFB_SHORT * sizeof(psyfloat));
  179       memset(psydata->engNext2[j], 0, NSFB_SHORT * sizeof(psyfloat));
  180     }
  181   }
  182 }
  183 
  184 static void PsyEnd(GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo, unsigned int numChannels)
  185 {
  186   unsigned int channel;
  187   int j;
  188 
  189   if (gpsyInfo->hannWindow)
  190     FreeMemory(gpsyInfo->hannWindow);
  191   if (gpsyInfo->hannWindowS)
  192     FreeMemory(gpsyInfo->hannWindowS);
  193 
  194   for (channel = 0; channel < numChannels; channel++)
  195   {
  196     if (psyInfo[channel].prevSamples)
  197       FreeMemory(psyInfo[channel].prevSamples);
  198   }
  199 
  200   for (channel = 0; channel < numChannels; channel++)
  201   {
  202     psydata_t *psydata = psyInfo[channel].data;
  203 
  204     for (j = 0; j < 8; j++)
  205     {
  206         if (psydata->engPrev[j])
  207             FreeMemory(psydata->engPrev[j]);
  208         if (psydata->eng[j])
  209             FreeMemory(psydata->eng[j]);
  210         if (psydata->engNext[j])
  211             FreeMemory(psydata->engNext[j]);
  212         if (psydata->engNext2[j])
  213             FreeMemory(psydata->engNext2[j]);
  214     }
  215   }
  216 
  217   for (channel = 0; channel < numChannels; channel++)
  218   {
  219     if (psyInfo[channel].data)
  220       FreeMemory(psyInfo[channel].data);
  221   }
  222 
  223 #if PRINTSTAT
  224   printf("short frames: %d/%d (%.2f %%)\n", frames.s, frames.tot, 100.0*frames.s/frames.tot);
  225 #endif
  226 }
  227 
  228 /* Do psychoacoustical analysis */
  229 static void PsyCalculate(ChannelInfo * channelInfo, GlobalPsyInfo * gpsyInfo,
  230              PsyInfo * psyInfo, int *cb_width_long, int
  231              num_cb_long, int *cb_width_short,
  232              int num_cb_short, unsigned int numChannels,
  233              double quality
  234             )
  235 {
  236   unsigned int channel;
  237 
  238   // limit switching threshold
  239   if (quality < 0.4)
  240       quality = 0.4;
  241 
  242   for (channel = 0; channel < numChannels; channel++)
  243   {
  244     if (channelInfo[channel].present)
  245     {
  246 
  247       if (channelInfo[channel].cpe &&
  248       channelInfo[channel].ch_is_left)
  249       {             /* CPE */
  250 
  251     int leftChan = channel;
  252     int rightChan = channelInfo[channel].paired_ch;
  253 
  254     PsyCheckShort(&psyInfo[leftChan], quality);
  255     PsyCheckShort(&psyInfo[rightChan], quality);
  256       }
  257       else if (!channelInfo[channel].cpe &&
  258            channelInfo[channel].lfe)
  259       {             /* LFE */
  260         // Only set block type and it should be OK
  261     psyInfo[channel].block_type = ONLY_LONG_WINDOW;
  262       }
  263       else if (!channelInfo[channel].cpe)
  264       {             /* SCE */
  265     PsyCheckShort(&psyInfo[channel], quality);
  266       }
  267     }
  268   }
  269 }
  270 
  271 // imported from filtbank.c
  272 static void mdct( FFT_Tables *fft_tables, double *data, int N )
  273 {
  274     double tempr, tempi, c, s, cold, cfreq, sfreq; /* temps for pre and post twiddle */
  275     double freq = 2.0 * M_PI / N;
  276     double cosfreq8, sinfreq8;
  277     int i, n;
  278 
  279     double xi[BLOCK_LEN_LONG / 2];
  280     double xr[BLOCK_LEN_LONG / 2];
  281 
  282     /* prepare for recurrence relation in pre-twiddle */
  283     cfreq = cos (freq);
  284     sfreq = sin (freq);
  285     cosfreq8 = cos (freq * 0.125);
  286     sinfreq8 = sin (freq * 0.125);
  287     c = cosfreq8;
  288     s = sinfreq8;
  289 
  290     for (i = 0; i < (N >> 2); i++) {
  291         /* calculate real and imaginary parts of g(n) or G(p) */
  292         n = 2 * i;
  293 
  294         if (n < (N >> 2))
  295             tempr = data [(N>>2) + (N>>1) - 1 - n] + data [N - (N>>2) + n];
  296         else
  297             tempr = data [(N>>2) + (N>>1) - 1 - n] - data [-(N>>2) + n];
  298 
  299         if (n < (N >> 2))
  300             tempi = data [(N>>2) + n] - data [(N>>2) - 1 - n];
  301         else
  302             tempi = data [(N>>2) + n] + data [N + (N>>2) - 1 - n];
  303 
  304         /* calculate pre-twiddled FFT input */
  305         xr[i] = tempr * c + tempi * s;
  306         xi[i] = tempi * c - tempr * s;
  307 
  308         /* use recurrence to prepare cosine and sine for next value of i */
  309         cold = c;
  310         c = c * cfreq - s * sfreq;
  311         s = s * cfreq + cold * sfreq;
  312     }
  313 
  314     /* Perform in-place complex FFT of length N/4 */
  315     switch (N) {
  316     case BLOCK_LEN_SHORT * 2:
  317         fft( fft_tables, xr, xi, 6);
  318         break;
  319     case BLOCK_LEN_LONG * 2:
  320         fft( fft_tables, xr, xi, 9);
  321     }
  322 
  323     /* prepare for recurrence relations in post-twiddle */
  324     c = cosfreq8;
  325     s = sinfreq8;
  326 
  327     /* post-twiddle FFT output and then get output data */
  328     for (i = 0; i < (N >> 2); i++) {
  329         /* get post-twiddled FFT output  */
  330         tempr = 2. * (xr[i] * c + xi[i] * s);
  331         tempi = 2. * (xi[i] * c - xr[i] * s);
  332 
  333         /* fill in output values */
  334         data [2 * i] = -tempr;   /* first half even */
  335         data [(N >> 1) - 1 - 2 * i] = tempi;  /* first half odd */
  336         data [(N >> 1) + 2 * i] = -tempi;  /* second half even */
  337         data [N - 1 - 2 * i] = tempr;  /* second half odd */
  338 
  339         /* use recurrence to prepare cosine and sine for next value of i */
  340         cold = c;
  341         c = c * cfreq - s * sfreq;
  342         s = s * cfreq + cold * sfreq;
  343     }
  344 }
  345 
  346 
  347 static void PsyBufferUpdate( FFT_Tables *fft_tables, GlobalPsyInfo * gpsyInfo, PsyInfo * psyInfo,
  348                 double *newSamples, unsigned int bandwidth,
  349                 int *cb_width_short, int num_cb_short)
  350 {
  351   int win;
  352   double transBuff[2 * BLOCK_LEN_LONG];
  353   double transBuffS[2 * BLOCK_LEN_SHORT];
  354   psydata_t *psydata = psyInfo->data;
  355   psyfloat *tmp;
  356   int sfb;
  357 
  358   psydata->bandS = psyInfo->sizeS * bandwidth * 2 / gpsyInfo->sampleRate;
  359 
  360   memcpy(transBuff, psyInfo->prevSamples, psyInfo->size * sizeof(double));
  361   memcpy(transBuff + psyInfo->size, newSamples, psyInfo->size * sizeof(double));
  362 
  363   for (win = 0; win < 8; win++)
  364   {
  365     int first = 0;
  366     int last = 0;
  367 
  368     memcpy(transBuffS, transBuff + (win * BLOCK_LEN_SHORT) + (BLOCK_LEN_LONG - BLOCK_LEN_SHORT) / 2,
  369        2 * psyInfo->sizeS * sizeof(double));
  370 
  371     Hann(gpsyInfo, transBuffS, 2 * psyInfo->sizeS);
  372     mdct( fft_tables, transBuffS, 2 * psyInfo->sizeS);
  373 
  374     // shift bufs
  375     tmp = psydata->engPrev[win];
  376     psydata->engPrev[win] = psydata->eng[win];
  377     psydata->eng[win] = psydata->engNext[win];
  378     psydata->engNext[win] = psydata->engNext2[win];
  379     psydata->engNext2[win] = tmp;
  380 
  381     for (sfb = 0; sfb < num_cb_short; sfb++)
  382     {
  383       double e;
  384       int l;
  385 
  386       first = last;
  387       last = first + cb_width_short[sfb];
  388 
  389       if (first < 1)
  390           first = 1;
  391 
  392       if (first >= psydata->bandS) // band out of range
  393           break;
  394 
  395       e = 0.0;
  396       for (l = first; l < last; l++)
  397           e += transBuffS[l] * transBuffS[l];
  398 
  399       psydata->engNext2[win][sfb] = e;
  400     }
  401     psydata->lastband = sfb;
  402     for (; sfb < num_cb_short; sfb++)
  403     {
  404         psydata->engNext2[win][sfb] = 0;
  405     }
  406   }
  407 
  408   memcpy(psyInfo->prevSamples, newSamples, psyInfo->size * sizeof(double));
  409 }
  410 
  411 static void BlockSwitch(CoderInfo * coderInfo, PsyInfo * psyInfo, unsigned int numChannels)
  412 {
  413   unsigned int channel;
  414   int desire = ONLY_LONG_WINDOW;
  415 
  416   /* Use the same block type for all channels
  417      If there is 1 channel that wants a short block,
  418      use a short block on all channels.
  419    */
  420   for (channel = 0; channel < numChannels; channel++)
  421   {
  422     if (psyInfo[channel].block_type == ONLY_SHORT_WINDOW)
  423       desire = ONLY_SHORT_WINDOW;
  424   }
  425 
  426   for (channel = 0; channel < numChannels; channel++)
  427   {
  428     int lasttype = coderInfo[channel].block_type;
  429 
  430     if (desire == ONLY_SHORT_WINDOW
  431     || coderInfo[channel].desired_block_type == ONLY_SHORT_WINDOW)
  432     {
  433       if (lasttype == ONLY_LONG_WINDOW || lasttype == SHORT_LONG_WINDOW)
  434     coderInfo[channel].block_type = LONG_SHORT_WINDOW;
  435       else
  436     coderInfo[channel].block_type = ONLY_SHORT_WINDOW;
  437     }
  438     else
  439     {
  440       if (lasttype == ONLY_SHORT_WINDOW || lasttype == LONG_SHORT_WINDOW)
  441     coderInfo[channel].block_type = SHORT_LONG_WINDOW;
  442       else
  443     coderInfo[channel].block_type = ONLY_LONG_WINDOW;
  444     }
  445     coderInfo[channel].desired_block_type = desire;
  446   }
  447 }
  448 
  449 psymodel_t psymodel2 =
  450 {
  451   PsyInit,
  452   PsyEnd,
  453   PsyCalculate,
  454   PsyBufferUpdate,
  455   BlockSwitch
  456 };