1 /*
2  *  TwoLAME: an optimized MPEG Audio Layer Two encoder
3  *
4  *  Copyright (C) 2001-2004 Michael Cheng
5  *  Copyright (C) 2004-2018 The TwoLAME Project
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2.1 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include <string.h>
27 
28 #include "twolame.h"
29 #include "common.h"
30 #include "mem.h"
31 #include "fft.h"
32 #include "ath.h"
33 #include "psycho_3.h"
34 
35 /* This is a reimplementation of psy model 1 using the ISO11172 standard.
36    I found the original dist10 code (which is full of pointers) to be
37    a horrible thing to try and understand and debug.
38    This implementation is not built for speed, but is rather meant to
39    clearly outline the steps specified by the standard (still, it's only
40    a tiny fraction slower than the dist10 code, and nothing has been optimized)
41    MFC Feb 2003 */
42 
psycho_3_add_db(psycho_3_mem * mem,FLOAT a,FLOAT b)43 static inline FLOAT psycho_3_add_db(psycho_3_mem * mem, FLOAT a, FLOAT b)
44 {
45     /* MFC - if the difference between a and b is large (>99), then just return the largest one.
46        (about 10% of the time) - For differences between 0 and 99, return the largest value, but
47        add in a pre-calculated difference value. - the value 99 was chosen arbitarily. - maximum
48        (a-b) i've seen is 572 */
49     FLOAT fdiff;
50     int idiff;
51     fdiff = (10.0 * (a - b));
52 
53     if (fdiff > 990.0) {
54         return a;
55     }
56     if (fdiff < -990.0) {
57         return (b);
58     }
59 
60     idiff = (int) fdiff;
61     if (idiff >= 0) {
62         return (a + mem->dbtable[idiff]);
63     }
64 
65     return (b + mem->dbtable[-idiff]);
66 }
67 
68 
69 
70 /* ISO11172 Sec D.1 Step 1 - Window with HANN and then perform the FFT */
psycho_3_fft(FLOAT sample[BLKSIZE],FLOAT energy[BLKSIZE])71 static void psycho_3_fft(FLOAT sample[BLKSIZE], FLOAT energy[BLKSIZE])
72 {
73     FLOAT x_real[BLKSIZE];
74     int i;
75     static int init = 0;
76     static FLOAT window[FFT_SIZE];
77 
78     if (!init) {                /* calculate window function for the Fourier transform */
79         FLOAT sqrt_8_over_3 = pow(8.0 / 3.0, 0.5);
80         for (i = 0; i < BLKSIZE; i++) {
81             window[i] = sqrt_8_over_3 * 0.5 * (1 - cos(2.0 * PI * i / (BLKSIZE))) / BLKSIZE;
82         }
83         init=1;
84     }
85 
86     /* convolve the samples with the hann window */
87     for (i = 0; i < BLKSIZE; i++)
88         x_real[i] = (FLOAT) (sample[i] * window[i]);
89     /* do the FFT */
90     twolame_psycho_1_fft(x_real, energy, BLKSIZE);
91 }
92 
93 
94 /* Sect D.1 Step 1 - convert the energies into dB */
psycho_3_powerdensityspectrum(FLOAT energy[BLKSIZE],FLOAT power[HBLKSIZE])95 static void psycho_3_powerdensityspectrum(FLOAT energy[BLKSIZE], FLOAT power[HBLKSIZE])
96 {
97     int i;
98     for (i = 1; i < HBLKSIZE; i++) {
99         if (energy[i] < 1E-20)
100             power[i] = -200.0 + POWERNORM;
101         else
102             power[i] = 10 * log10(energy[i]) + POWERNORM;
103     }
104 }
105 
106 
107 /* Sect D.1 Step 2 - Determine the sound pressure level in each subband */
psycho_3_spl(FLOAT * Lsb,FLOAT * power,FLOAT * scale)108 static void psycho_3_spl(FLOAT * Lsb, FLOAT * power, FLOAT * scale)
109 {
110     int i;
111     FLOAT Xmax[SBLIMIT];
112 
113     for (i = 0; i < SBLIMIT; i++) {
114         Xmax[i] = DBMIN;
115     }
116     /* Find the maximum SPL in the power spectrum */
117     for (i = 1; i < HBLKSIZE; i++) {
118         int index = (i - 1) >> 4;
119         if (Xmax[index] < power[i])
120             Xmax[index] = power[i];
121     }
122 
123     /* Compare it to the sound pressure based upon the scale for this subband and pick the maximum
124        one */
125     for (i = 0; i < SBLIMIT; i++) {
126         FLOAT val = 20 * log10(scale[i] * 32768) - 10;
127         Lsb[i] = MAX(Xmax[i], val);
128     }
129 }
130 
131 
132 /* Sect D.1 Step4b
133    A tone within the range (start -> end), must be 7.0 dB greater than
134    all it's neighbours within +/- srange. Don't count its immediate neighbours. */
psycho_3_tonal_label_range(psycho_3_mem * mem,FLOAT * power,int * tonelabel,int * maxima,FLOAT * Xtm,int start,int end,int srange)135 static void psycho_3_tonal_label_range(psycho_3_mem * mem, FLOAT * power, int *tonelabel,
136                                        int *maxima, FLOAT * Xtm, int start, int end, int srange)
137 {
138     int j, k;
139 
140     for (k = start; k < end; k++)   /* Search for all the maxima in this range */
141         if (maxima[k] == 1) {
142             tonelabel[k] = TONE;    /* assume it's a TONE and then prove otherwise */
143             for (j = -srange; j <= +srange; j++)    /* Check the neighbours within +/- srange */
144                 if (abs(j) > 1) /* Don't count the immediate neighbours, or itself */
145                     if ((power[k] - power[k + j]) < 7.0)
146                         tonelabel[k] = 0;   /* Not greater by 7dB, therefore not a tone */
147             if (tonelabel[k] == TONE) {
148                 /* Calculate the sound pressure level for this tone by summing the adjacent
149                    spectral lines Xtm[k] = 10 * log10( pow(10.0, 0.1*power[k-1]) + pow(10.0,
150                    0.1*power[k]) + pow(10.0, 0.1*power[k+1]) ); */
151                 FLOAT temp = psycho_3_add_db(mem, power[k - 1], power[k]);
152                 Xtm[k] = psycho_3_add_db(mem, temp, power[k + 1]);
153 
154                 /* *ALL* spectral lines within +/- srange are set to -inf dB So that when we do the
155                    noise calculate, they are not counted */
156                 for (j = -srange; j <= +srange; j++)
157                     power[k + j] = DBMIN;
158             }
159         }
160 }
161 
162 
163 /* Sect D.1 Step 4 Label the Tonal Components */
psycho_3_tonal_label(psycho_3_mem * mem,FLOAT power[HBLKSIZE],int * tonelabel,FLOAT Xtm[HBLKSIZE])164 static void psycho_3_tonal_label(psycho_3_mem * mem, FLOAT power[HBLKSIZE], int *tonelabel,
165                                  FLOAT Xtm[HBLKSIZE])
166 {
167     int i;
168     int maxima[HBLKSIZE];
169 
170     /* Find the maxima as per ISO11172 D.1.4.a */
171     maxima[0] = maxima[HBLKSIZE - 1] = 0;
172     tonelabel[0] = tonelabel[HBLKSIZE - 1] = 0;
173     Xtm[0] = Xtm[HBLKSIZE - 1] = DBMIN;
174     for (i = 1; i < HBLKSIZE - 1; i++) {
175         tonelabel[i] = 0;
176         Xtm[i] = DBMIN;
177         if (power[i] > power[i - 1] && power[i] > power[i + 1]) /* The first criteria for a maximum
178                                                                  */
179             maxima[i] = 1;
180         else
181             maxima[i] = 0;
182     }
183 
184     {
185         /* Now find the tones as per ISO11172 D.1 Step4.b */
186         /* The standard is a bit vague (surprise surprise). So I'm going to assume that - a tone
187            must be 7dB greater than *all* the relevant neighbours - once a tone is found, the
188            neighbours are immediately set to -inf dB */
189 
190         psycho_3_tonal_label_range(mem, power, tonelabel, maxima, Xtm, 2, 63, 2);
191         psycho_3_tonal_label_range(mem, power, tonelabel, maxima, Xtm, 63, 127, 3);
192         psycho_3_tonal_label_range(mem, power, tonelabel, maxima, Xtm, 127, 255, 6);
193         psycho_3_tonal_label_range(mem, power, tonelabel, maxima, Xtm, 255, 500, 12);
194 
195     }
196 }
197 
198 
199 
psycho_3_init_add_db(psycho_3_mem * mem)200 static void psycho_3_init_add_db(psycho_3_mem * mem)
201 {
202     int i;
203     FLOAT x;
204     for (i = 0; i < DBTAB; i++) {
205         x = (FLOAT) i / 10.0;
206         mem->dbtable[i] = 10 * log10(1 + pow(10.0, x / 10.0)) - x;
207     }
208 }
209 
210 
211 /* D.1 Step 4.c Labelling non-tonal (noise) components
212    Sum the energies in each critical band (the tone energies have been removed
213    during the tone labelling).
214    Find the "geometric mean" of these energies - i.e. find the best spot to put the
215    sum of energies within this critical band. */
psycho_3_noise_label(psycho_3_mem * mem,FLOAT power[HBLKSIZE],FLOAT energy[BLKSIZE],int * tonelabel,int * noiselabel,FLOAT Xnm[HBLKSIZE])216 static void psycho_3_noise_label(psycho_3_mem * mem, FLOAT power[HBLKSIZE], FLOAT energy[BLKSIZE],
217                                  int *tonelabel, int *noiselabel, FLOAT Xnm[HBLKSIZE])
218 {
219     int i, j;
220     int cbands = mem->cbands;
221     int *cbandindex = mem->cbandindex;
222 
223     Xnm[0] = DBMIN;
224     for (i = 0; i < cbands; i++) {
225         /* for each critical band */
226         FLOAT sum = DBMIN;
227         FLOAT esum = 0;
228         FLOAT centreweight = 0;
229         int centre;
230         for (j = cbandindex[i]; j < cbandindex[i + 1]; j++) {
231             Xnm[j] = DBMIN;
232             /* go through all the spectral lines within the critical band, adding the energies. The
233                tone energies have already been removed */
234             if (power[j] != DBMIN) {
235                 /* Found a noise energy, add it to the sum */
236                 sum = psycho_3_add_db(mem, power[j], sum);
237 
238                 /* calculations for the geometric mean FIXME MFC Feb 2003: Would it just be easier
239                    to do the *whole* of psycho_1 in the energy domain rather than in the dB domain?
240                    FIXME: This is just a lazy arsed arithmetic mean. Don't know if it's really going
241                    to make that much difference */
242                 esum += energy[j];  /* Calculate the sum of energies */
243                 centreweight += (j - cbandindex[i]) * energy[j];    /* And the energy moment */
244             }
245         }
246 
247         /* MEANX, crash on AMD64 without this hack. See
248            https://sourceforge.net/tracker/?func=detail&atid=735435&aid=1453400&group_id=136040
249            Probably a better way to do this */
250         if (sum <= DBMIN || esum < 0.00001)
251             /* If the energy sum is really small, just pretend the noise occurs in the centre
252                frequency line */
253             centre = (cbandindex[i] + cbandindex[i + 1]) / 2;
254         else {
255             /* Otherwise, work out the mean position of the noise, and put it there. */
256             centre = cbandindex[i] + (int) (centreweight / esum);
257         }
258         // /MEANX
259         Xnm[centre] = sum;
260         noiselabel[centre] = NOISE;
261     }
262 }
263 
264 
265 /* ISO11172 D.1 Step 5
266    Get rid of noise/tones that aren't greater than the ATH
267    If two tones are within 0.5bark, then delete the tone with the lower energy */
psycho_3_decimation(FLOAT * ath,int * tonelabel,FLOAT * Xtm,int * noiselabel,FLOAT * Xnm,FLOAT * bark)268 static void psycho_3_decimation(FLOAT * ath, int *tonelabel, FLOAT * Xtm, int *noiselabel,
269                                 FLOAT * Xnm, FLOAT * bark)
270 {
271     int i;
272 
273     /* Delete components which aren't above the ATH */
274     for (i = 1; i < HBLKSIZE; i++) {
275         if (noiselabel[i] == NOISE) {
276             if (Xnm[i] < ath[i]) {
277                 /* this masker isn't above the ATH : delete it */
278                 Xnm[i] = DBMIN;
279                 noiselabel[i] = 0;
280             }
281         }
282         if (tonelabel[i] == TONE) {
283             if (Xtm[i] < ath[i]) {
284                 Xtm[i] = DBMIN;
285                 tonelabel[i] = 0;
286             }
287         }
288     }
289     /* Search for tones that are within 0.5 bark */
290     /* MFC FIXME Feb 2003: haven't done this yet */
291 
292 }
293 
294 
295 /* ISO11172 Sect D.1 Step 6
296    Calculation of individual masking thresholds
297    Work out how each of the tones&noises maskes other frequencies
298    NOTE: Only a subset of other frequencies is checked. According to the
299    standard different subbands are subsampled to different amounts.
300    See psycho_3_init and freq_subset */
psycho_3_threshold(psycho_3_mem * mem,FLOAT * LTg,int * tonelabel,FLOAT * Xtm,int * noiselabel,FLOAT * Xnm,FLOAT * bark,FLOAT * ath,int bit_rate,int * freq_subset)301 static void psycho_3_threshold(psycho_3_mem * mem, FLOAT * LTg, int *tonelabel, FLOAT * Xtm,
302                                int *noiselabel, FLOAT * Xnm, FLOAT * bark, FLOAT * ath,
303                                int bit_rate, int *freq_subset)
304 {
305     int i, j, k;
306     FLOAT LTtm[SUBSIZE];
307     FLOAT LTnm[SUBSIZE];
308 
309     for (i = 0; i < SUBSIZE; i++) {
310         LTtm[i] = DBMIN;
311         LTnm[i] = DBMIN;
312     }
313     /* Loop over the entire spectrum and find every noise and tone And then with each noise/tone
314        work out how it masks the spectral lines around it */
315     for (k = 1; k < HBLKSIZE; k++) {
316         /* Find every tone */
317         if (tonelabel[k] == TONE) {
318             for (j = 0; j < SUBSIZE; j++) {
319                 /* figure out how it masks the levels around it */
320                 FLOAT dz = bark[freq_subset[j]] - bark[k];
321                 if (dz >= -3.0 && dz < 8.0) {
322                     FLOAT vf;
323                     FLOAT av = -1.525 - 0.275 * bark[k] - 4.5 + Xtm[k];
324                     /* masking function for lower & upper slopes */
325                     if (dz < -1)
326                         vf = 17 * (dz + 1) - (0.4 * Xtm[k] + 6);
327                     else if (dz < 0)
328                         vf = (0.4 * Xtm[k] + 6) * dz;
329                     else if (dz < 1)
330                         vf = (-17 * dz);
331                     else
332                         vf = -(dz - 1) * (17 - 0.15 * Xtm[k]) - 17;
333                     LTtm[j] = psycho_3_add_db(mem, LTtm[j], av + vf);
334                 }
335             }
336         }
337 
338         /* find every noise label */
339         if (noiselabel[k] == NOISE) {
340             for (j = 0; j < SUBSIZE; j++) {
341                 /* figure out how it masks the levels around it */
342                 FLOAT dz = bark[freq_subset[j]] - bark[k];
343                 if (dz >= -3.0 && dz < 8.0) {
344                     FLOAT vf;
345                     FLOAT av = -1.525 - 0.175 * bark[k] - 0.5 + Xnm[k];
346                     /* masking function for lower & upper slopes */
347                     if (dz < -1)
348                         vf = 17 * (dz + 1) - (0.4 * Xnm[k] + 6);
349                     else if (dz < 0)
350                         vf = (0.4 * Xnm[k] + 6) * dz;
351                     else if (dz < 1)
352                         vf = (-17 * dz);
353                     else
354                         vf = -(dz - 1) * (17 - 0.15 * Xnm[k]) - 17;
355                     LTnm[j] = psycho_3_add_db(mem, LTnm[j], av + vf);
356                 }
357             }
358         }
359     }
360 
361     /* ISO11172 D.1 Step 7 Calculate the global masking threhold */
362     for (i = 0; i < SUBSIZE; i++) {
363         LTg[i] = psycho_3_add_db(mem, LTnm[i], LTtm[i]);
364         if (bit_rate < 96)
365             LTg[i] = psycho_3_add_db(mem, ath[freq_subset[i]], LTg[i]);
366         else
367             LTg[i] = psycho_3_add_db(mem, ath[freq_subset[i]] - 12.0, LTg[i]);
368     }
369 }
370 
371 
372 /* Find the minimum LTg for each subband. ISO11172 Sec D.1 Step 8 */
psycho_3_minimummasking(FLOAT * LTg,FLOAT * LTmin,int * freq_subset)373 static void psycho_3_minimummasking(FLOAT * LTg, FLOAT * LTmin, int *freq_subset)
374 {
375     int i;
376 
377     for (i = 0; i < SBLIMIT; i++)
378         LTmin[i] = 999999.9;
379 
380     for (i = 0; i < SUBSIZE; i++) {
381         int index = freq_subset[i] >> 4;
382         if (LTmin[index] > LTg[i]) {
383             LTmin[index] = LTg[i];
384         }
385     }
386 }
387 
388 
389 /* ISO11172 Sect D.1 Step 9
390    Calculate the signal-to-mask ratio
391    MFC FIXME Feb 2003 for better calling from
392    twolame, add a "float SMR[]" array and return it */
psycho_3_smr(FLOAT * LTmin,FLOAT * Lsb)393 static void psycho_3_smr(FLOAT * LTmin, FLOAT * Lsb)
394 {
395     int i;
396     for (i = 0; i < SBLIMIT; i++) {
397         LTmin[i] = Lsb[i] - LTmin[i];
398     }
399 }
400 
401 
twolame_psycho_3_init(twolame_options * glopts)402 static psycho_3_mem *twolame_psycho_3_init(twolame_options * glopts)
403 {
404     int i;
405     int cbase = 0;              /* current base index for the bark range calculation */
406     FLOAT sfreq;
407     psycho_3_mem *mem;
408     int numlines[HBLKSIZE];
409     FLOAT cbval[HBLKSIZE];
410     int partition[HBLKSIZE];
411     int *freq_subset;
412     FLOAT *bark, *ath;
413     int cbands = 0;
414     int *cbandindex;
415 
416     mem = (psycho_3_mem *) TWOLAME_MALLOC(sizeof(psycho_3_mem));
417     mem->off[0] = mem->off[1] = 256;
418     freq_subset = mem->freq_subset;
419     bark = mem->bark;
420     ath = mem->ath;
421     cbandindex = mem->cbandindex;
422 
423     /* Initialise the tables for the adding dB */
424     psycho_3_init_add_db(mem);
425 
426     /* For each spectral line calculate the bark and the ATH (in dB) */
427     sfreq = (FLOAT) glopts->samplerate_out;
428     for (i = 1; i < HBLKSIZE; i++) {
429         FLOAT freq = i * sfreq / BLKSIZE;
430         bark[i] = twolame_ath_freq2bark(freq);
431         ath[i] = twolame_ath_db(freq, glopts->athlevel);
432     }
433 
434     {   /* Work out the critical bands Starting from line 0, all lines
435            within 1 bark of the starting bark are added to the same
436            critical band. When a line is greater by 1.0 of a bark, start a
437            new critical band.  */
438 
439         cbandindex[0] = 1;
440         for (i = 1; i < HBLKSIZE; i++) {
441             if ((bark[i] - bark[cbase]) > 1.0) {    /* 1 critical band? 1 bark? */
442                 /* this frequency line is too different from the starting line, (in terms of the
443                    bark distance) so make this spectral line the first member of the next critical
444                    band */
445                 cbase = i;      /* Start the new critical band from this frequency line */
446                 cbands++;
447                 cbandindex[cbands] = cbase;
448             }
449             /* partition[i] tells us which critical band the i'th frequency line is in */
450             partition[i] = cbands;
451             /* keep a count of how many frequency lines are in each partition */
452             numlines[cbands]++;
453         }
454 
455         cbands++;
456         cbandindex[cbands] = 513;   /* Set the top of the last critical band */
457         mem->cbands = cbands;   // make a not of the number of cbands
458 
459         /* For each crtical band calculate the average bark value cbval [central bark value] */
460         for (i = 1; i < HBLKSIZE; i++)
461             cbval[partition[i]] += bark[i]; /* sum up all the bark values */
462         for (i = 1; i < CBANDS; i++) {
463             if (numlines[i] != 0)
464                 cbval[i] /= numlines[i];    /* divide by the number of values */
465             else {
466                 cbval[i] = 0;   /* this isn't a partition */
467             }
468         }
469     }
470 
471     {
472         /* For Step6 - For the calculation of individual masking thresholds the spectral lines are
473            subsampled i.e. no need to work out the masking for every single spectral line.
474            Depending upon which subband the calculation is for, you can skip a number of lines
475            There are 16 lines per subband -> 32 * 16 = 512 Subband 0-2 : Every line (3 * 16 = 48
476            lines) Subband 3-5 : Every Second line (3 * 16/2 = 24 lines) Subband 6-11 : Every 4th
477            line (6 * 16/4 = 24 lines) Subband 12-31 : Every 12th line (20 * 16/8 = 40 lines)
478 
479            create this subset of frequencies (freq_subset) */
480         int freq_index = 0;
481         for (i = 1; i < (3 * 16) + 1; i++)
482             freq_subset[freq_index++] = i;
483         for (; i < (6 * 16) + 1; i += 2)
484             freq_subset[freq_index++] = i;
485         for (; i < (12 * 16) + 1; i += 4)
486             freq_subset[freq_index++] = i;
487         for (; i < (32 * 16) + 1; i += 8)
488             freq_subset[freq_index++] = i;
489     }
490 
491     if (glopts->verbosity > 4) {
492         fprintf(stderr, "%i critical bands\n", cbands);
493         for (i = 0; i < cbands; i++)
494             fprintf(stderr, "cband %i spectral line index %i\n", i, cbandindex[i]);
495         fprintf(stderr, "%i Subsampled spectral lines\n", SUBSIZE);
496         for (i = 0; i < SUBSIZE; i++)
497             fprintf(stderr, "%i Spectral line %i Bark %.2f\n", i, freq_subset[i],
498                     bark[freq_subset[i]]);
499     }
500 
501     return (mem);
502 }
503 
504 
psycho_3_dump(int * tonelabel,FLOAT * Xtm,int * noiselabel,FLOAT * Xnm)505 static void psycho_3_dump(int *tonelabel, FLOAT * Xtm, int *noiselabel, FLOAT * Xnm)
506 {
507     int i;
508     fprintf(stderr, "3 Ton:");
509     for (i = 1; i < HAN_SIZE; i++) {
510         if (tonelabel[i] == TONE)
511             fprintf(stderr, "[%i] %3.0f ", i, Xtm[i]);
512     }
513     fprintf(stderr, "\n");
514 
515     fprintf(stderr, "3 Nos:");
516     for (i = 1; i < HAN_SIZE; i++) {
517         if (noiselabel[i] == NOISE)
518             fprintf(stderr, "[%i] %3.0f ", i, Xnm[i]);
519     }
520     fprintf(stderr, "\n");
521 }
522 
523 
twolame_psycho_3(twolame_options * glopts,short int buffer[2][1152],FLOAT scale[2][32],FLOAT ltmin[2][32])524 void twolame_psycho_3(twolame_options * glopts, short int buffer[2][1152], FLOAT scale[2][32],
525                       FLOAT ltmin[2][32])
526 {
527     psycho_3_mem *mem;
528     int nch = glopts->num_channels_out;
529     int k, i;
530     FLOAT sample[BLKSIZE];
531 
532     FLOAT energy[BLKSIZE];
533     FLOAT power[HBLKSIZE] = {0};
534     FLOAT Xtm[HBLKSIZE], Xnm[HBLKSIZE];
535     int tonelabel[HBLKSIZE], noiselabel[HBLKSIZE] = {0};
536     FLOAT LTg[HBLKSIZE];
537     FLOAT Lsb[SBLIMIT];
538 
539     if (!glopts->p3mem) {
540         glopts->p3mem = twolame_psycho_3_init(glopts);
541     }
542     mem = glopts->p3mem;
543 
544     for (k = 0; k < nch; k++) {
545         int ok = mem->off[k] % 1408;
546         for (i = 0; i < 1152; i++) {
547             mem->fft_buf[k][ok++] = (FLOAT) buffer[k][i] / SCALE;
548             if (ok >= 1408)
549                 ok = 0;
550         }
551         ok = (mem->off[k] + 1216) % 1408;
552         for (i = 0; i < BLKSIZE; i++) {
553             sample[i] = mem->fft_buf[k][ok++];
554             if (ok >= 1408)
555                 ok = 0;
556         }
557 
558         mem->off[k] += 1152;
559         mem->off[k] %= 1408;
560 
561         psycho_3_fft(sample, energy);
562         psycho_3_powerdensityspectrum(energy, power);
563         psycho_3_spl(Lsb, power, &scale[k][0]);
564         psycho_3_tonal_label(mem, power, tonelabel, Xtm);
565         psycho_3_noise_label(mem, power, energy, tonelabel, noiselabel, Xnm);
566         if (glopts->verbosity > 8)
567             psycho_3_dump(tonelabel, Xtm, noiselabel, Xnm);
568         psycho_3_decimation(mem->ath, tonelabel, Xtm, noiselabel, Xnm, mem->bark);
569         psycho_3_threshold(mem, LTg, tonelabel, Xtm, noiselabel, Xnm, mem->bark, mem->ath,
570                            glopts->bitrate / nch, mem->freq_subset);
571         psycho_3_minimummasking(LTg, &ltmin[k][0], mem->freq_subset);
572         psycho_3_smr(&ltmin[k][0], Lsb);
573     }
574 }
575 
576 
twolame_psycho_3_deinit(psycho_3_mem ** mem)577 void twolame_psycho_3_deinit(psycho_3_mem ** mem)
578 {
579 
580     if (mem == NULL || *mem == NULL)
581         return;
582 
583     TWOLAME_FREE(*mem);
584 }
585 
586 
587 // vim:ts=4:sw=4:nowrap:
588