• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6 
7  1.    INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18 
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28 
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33 
34 2.    COPYRIGHT LICENSE
35 
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39 
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42 
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48 
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51 
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54 
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60 
61 3.    NO PATENT LICENSE
62 
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67 
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70 
71 4.    DISCLAIMER
72 
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83 
84 5.    CONTACT INFORMATION
85 
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90 
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94 
95 /**************************** SBR encoder library ******************************
96 
97    Author(s):
98 
99    Description:
100 
101 *******************************************************************************/
102 
103 /*!
104   \file
105   \brief  frequency scale $Revision: 95225 $
106 */
107 
108 #include "sbrenc_freq_sca.h"
109 #include "sbr_misc.h"
110 
111 #include "genericStds.h"
112 
113 /*  StartFreq */
114 static INT getStartFreq(INT fsCore, const INT start_freq);
115 
116 /* StopFreq */
117 static INT getStopFreq(INT fsCore, const INT stop_freq);
118 
119 static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor);
120 static void CalcBands(INT *diff, INT start, INT stop, INT num_bands);
121 static INT modifyBands(INT max_band, INT *diff, INT length);
122 static void cumSum(INT start_value, INT *diff, INT length, UCHAR *start_adress);
123 
124 /*******************************************************************************
125  Functionname:  FDKsbrEnc_getSbrStartFreqRAW
126  *******************************************************************************
127  Description:
128 
129  Arguments:
130 
131  Return:
132  *******************************************************************************/
133 
FDKsbrEnc_getSbrStartFreqRAW(INT startFreq,INT fsCore)134 INT FDKsbrEnc_getSbrStartFreqRAW(INT startFreq, INT fsCore) {
135   INT result;
136 
137   if (startFreq < 0 || startFreq > 15) {
138     return -1;
139   }
140   /* Update startFreq struct */
141   result = getStartFreq(fsCore, startFreq);
142 
143   result =
144       (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */
145 
146   return (result);
147 
148 } /* End FDKsbrEnc_getSbrStartFreqRAW */
149 
150 /*******************************************************************************
151  Functionname:  getSbrStopFreq
152  *******************************************************************************
153  Description:
154 
155  Arguments:
156 
157  Return:
158  *******************************************************************************/
FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq,INT fsCore)159 INT FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq, INT fsCore) {
160   INT result;
161 
162   if (stopFreq < 0 || stopFreq > 13) return -1;
163 
164   /* Uppdate stopFreq struct */
165   result = getStopFreq(fsCore, stopFreq);
166   result =
167       (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */
168 
169   return (result);
170 } /* End getSbrStopFreq */
171 
172 /*******************************************************************************
173  Functionname:  getStartFreq
174  *******************************************************************************
175  Description:
176 
177  Arguments:  fsCore - core sampling rate
178 
179 
180  Return:
181  *******************************************************************************/
getStartFreq(INT fsCore,const INT start_freq)182 static INT getStartFreq(INT fsCore, const INT start_freq) {
183   INT k0_min;
184 
185   switch (fsCore) {
186     case 8000:
187       k0_min = 24; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */
188       break;
189     case 11025:
190       k0_min = 17; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */
191       break;
192     case 12000:
193       k0_min = 16; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */
194       break;
195     case 16000:
196       k0_min = 16; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */
197       break;
198     case 22050:
199       k0_min = 12; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */
200       break;
201     case 24000:
202       k0_min = 11; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */
203       break;
204     case 32000:
205       k0_min = 10; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */
206       break;
207     case 44100:
208       k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */
209       break;
210     case 48000:
211       k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */
212       break;
213     case 96000:
214       k0_min = 3; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */
215       break;
216     default:
217       k0_min = 11; /* illegal fs */
218   }
219 
220   switch (fsCore) {
221     case 8000: {
222       INT v_offset[] = {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
223       return (k0_min + v_offset[start_freq]);
224     }
225     case 11025: {
226       INT v_offset[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13};
227       return (k0_min + v_offset[start_freq]);
228     }
229     case 12000: {
230       INT v_offset[] = {-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16};
231       return (k0_min + v_offset[start_freq]);
232     }
233     case 16000: {
234       INT v_offset[] = {-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16};
235       return (k0_min + v_offset[start_freq]);
236     }
237     case 22050:
238     case 24000:
239     case 32000: {
240       INT v_offset[] = {-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20};
241       return (k0_min + v_offset[start_freq]);
242     }
243     case 44100:
244     case 48000:
245     case 96000: {
246       INT v_offset[] = {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24};
247       return (k0_min + v_offset[start_freq]);
248     }
249     default: {
250       INT v_offset[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33};
251       return (k0_min + v_offset[start_freq]);
252     }
253   }
254 } /* End getStartFreq */
255 
256 /*******************************************************************************
257  Functionname:  getStopFreq
258  *******************************************************************************
259  Description:
260 
261  Arguments:
262 
263  Return:
264  *******************************************************************************/
getStopFreq(INT fsCore,const INT stop_freq)265 static INT getStopFreq(INT fsCore, const INT stop_freq) {
266   INT result, i;
267   INT k1_min;
268   INT v_dstop[13];
269 
270   INT *v_stop_freq = NULL;
271   INT v_stop_freq_16[14] = {48, 49, 50, 51, 52, 54, 55,
272                             56, 57, 59, 60, 61, 63, 64};
273   INT v_stop_freq_22[14] = {35, 37, 38, 40, 42, 44, 46,
274                             48, 51, 53, 56, 58, 61, 64};
275   INT v_stop_freq_24[14] = {32, 34, 36, 38, 40, 42, 44,
276                             46, 49, 52, 55, 58, 61, 64};
277   INT v_stop_freq_32[14] = {32, 34, 36, 38, 40, 42, 44,
278                             46, 49, 52, 55, 58, 61, 64};
279   INT v_stop_freq_44[14] = {23, 25, 27, 29, 32, 34, 37,
280                             40, 43, 47, 51, 55, 59, 64};
281   INT v_stop_freq_48[14] = {21, 23, 25, 27, 30, 32, 35,
282                             38, 42, 45, 49, 54, 59, 64};
283   INT v_stop_freq_64[14] = {20, 22, 24, 26, 29, 31, 34,
284                             37, 41, 45, 49, 54, 59, 64};
285   INT v_stop_freq_88[14] = {15, 17, 19, 21, 23, 26, 29,
286                             33, 37, 41, 46, 51, 57, 64};
287   INT v_stop_freq_96[14] = {13, 15, 17, 19, 21, 24, 27,
288                             31, 35, 39, 44, 50, 57, 64};
289   INT v_stop_freq_192[14] = {7,  8,  10, 12, 14, 16, 19,
290                              23, 27, 32, 38, 46, 54, 64};
291 
292   switch (fsCore) {
293     case 8000:
294       k1_min = 48;
295       v_stop_freq = v_stop_freq_16;
296       break;
297     case 11025:
298       k1_min = 35;
299       v_stop_freq = v_stop_freq_22;
300       break;
301     case 12000:
302       k1_min = 32;
303       v_stop_freq = v_stop_freq_24;
304       break;
305     case 16000:
306       k1_min = 32;
307       v_stop_freq = v_stop_freq_32;
308       break;
309     case 22050:
310       k1_min = 23;
311       v_stop_freq = v_stop_freq_44;
312       break;
313     case 24000:
314       k1_min = 21;
315       v_stop_freq = v_stop_freq_48;
316       break;
317     case 32000:
318       k1_min = 20;
319       v_stop_freq = v_stop_freq_64;
320       break;
321     case 44100:
322       k1_min = 15;
323       v_stop_freq = v_stop_freq_88;
324       break;
325     case 48000:
326       k1_min = 13;
327       v_stop_freq = v_stop_freq_96;
328       break;
329     case 96000:
330       k1_min = 7;
331       v_stop_freq = v_stop_freq_192;
332       break;
333     default:
334       k1_min = 21; /* illegal fs  */
335   }
336 
337   /* Ensure increasing bandwidth */
338   for (i = 0; i <= 12; i++) {
339     v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i];
340   }
341 
342   FDKsbrEnc_Shellsort_int(v_dstop, 13); /* Sort bandwidth changes */
343 
344   result = k1_min;
345   for (i = 0; i < stop_freq; i++) {
346     result = result + v_dstop[i];
347   }
348 
349   return (result);
350 
351 } /* End getStopFreq */
352 
353 /*******************************************************************************
354  Functionname:  FDKsbrEnc_FindStartAndStopBand
355  *******************************************************************************
356  Description:
357 
358  Arguments:     srSbr            SBR sampling freqency
359                 srCore           AAC core sampling freqency
360                 noChannels       Number of QMF channels
361                 startFreq        SBR start frequency in QMF bands
362                 stopFreq         SBR start frequency in QMF bands
363 
364                *k0               Output parameter
365                *k2               Output parameter
366 
367  Return:       Error code (0 is OK)
368  *******************************************************************************/
FDKsbrEnc_FindStartAndStopBand(const INT srSbr,const INT srCore,const INT noChannels,const INT startFreq,const INT stopFreq,INT * k0,INT * k2)369 INT FDKsbrEnc_FindStartAndStopBand(const INT srSbr, const INT srCore,
370                                    const INT noChannels, const INT startFreq,
371                                    const INT stopFreq, INT *k0, INT *k2) {
372   /* Update startFreq struct */
373   *k0 = getStartFreq(srCore, startFreq);
374 
375   /* Test if start freq is outside corecoder range */
376   if (srSbr * noChannels < *k0 * srCore) {
377     return (
378         1); /* raise the cross-over frequency and/or lower the number
379                of target bands per octave (or lower the sampling frequency) */
380   }
381 
382   /*Update stopFreq struct */
383   if (stopFreq < 14) {
384     *k2 = getStopFreq(srCore, stopFreq);
385   } else if (stopFreq == 14) {
386     *k2 = 2 * *k0;
387   } else {
388     *k2 = 3 * *k0;
389   }
390 
391   /* limit to Nyqvist */
392   if (*k2 > noChannels) {
393     *k2 = noChannels;
394   }
395 
396   /* Test for invalid  k0 k2 combinations */
397   if ((srCore == 22050) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS44100))
398     return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for
399                    fs=44.1kHz */
400 
401   if ((srCore >= 24000) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS48000))
402     return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for
403                    fs>=48kHz */
404 
405   if ((*k2 - *k0) > MAX_FREQ_COEFFS)
406     return (1); /*Number of bands exceeds valid range of MAX_FREQ_COEFFS */
407 
408   if ((*k2 - *k0) < 0) return (1); /* Number of bands is negative */
409 
410   return (0);
411 }
412 
413 /*******************************************************************************
414  Functionname:  FDKsbrEnc_UpdateFreqScale
415  *******************************************************************************
416  Description:
417 
418  Arguments:
419 
420  Return:
421  *******************************************************************************/
FDKsbrEnc_UpdateFreqScale(UCHAR * v_k_master,INT * h_num_bands,const INT k0,const INT k2,const INT freqScale,const INT alterScale)422 INT FDKsbrEnc_UpdateFreqScale(UCHAR *v_k_master, INT *h_num_bands, const INT k0,
423                               const INT k2, const INT freqScale,
424                               const INT alterScale)
425 
426 {
427   INT b_p_o = 0; /* bands_per_octave */
428   FIXP_DBL warp = FL2FXCONST_DBL(0.0f);
429   INT dk = 0;
430 
431   /* Internal variables */
432   INT k1 = 0, i;
433   INT num_bands0;
434   INT num_bands1;
435   INT diff_tot[MAX_OCTAVE + MAX_SECOND_REGION];
436   INT *diff0 = diff_tot;
437   INT *diff1 = diff_tot + MAX_OCTAVE;
438   INT k2_achived;
439   INT k2_diff;
440   INT incr = 0;
441 
442   /* Init */
443   if (freqScale == 1) b_p_o = 12;
444   if (freqScale == 2) b_p_o = 10;
445   if (freqScale == 3) b_p_o = 8;
446 
447   if (freqScale > 0) /*Bark*/
448   {
449     if (alterScale == 0)
450       warp = FL2FXCONST_DBL(0.5f); /* 1.0/(1.0*2.0) */
451     else
452       warp = FL2FXCONST_DBL(1.0f / 2.6f); /* 1.0/(1.3*2.0); */
453 
454     if (4 * k2 >= 9 * k0) /*two or more regions (how many times the basis band
455                              is copied)*/
456     {
457       k1 = 2 * k0;
458 
459       num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f));
460       num_bands1 = numberOfBands(b_p_o, k1, k2, warp);
461 
462       CalcBands(diff0, k0, k1, num_bands0);       /*CalcBands1 => diff0 */
463       FDKsbrEnc_Shellsort_int(diff0, num_bands0); /*SortBands sort diff0 */
464 
465       if (diff0[0] == 0) /* too wide FB bands for target tuning */
466       {
467         return (1); /* raise the cross-over frequency and/or lower the number
468                        of target bands per octave (or lower the sampling
469                        frequency */
470       }
471 
472       cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */
473 
474       CalcBands(diff1, k1, k2, num_bands1);       /* CalcBands2 => diff1 */
475       FDKsbrEnc_Shellsort_int(diff1, num_bands1); /* SortBands sort diff1 */
476       if (diff0[num_bands0 - 1] > diff1[0])       /* max(1) > min(2) */
477       {
478         if (modifyBands(diff0[num_bands0 - 1], diff1, num_bands1)) return (1);
479       }
480 
481       /* Add 2'nd region */
482       cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]);
483       *h_num_bands = num_bands0 + num_bands1; /* Output nr of bands */
484 
485     } else /* one region */
486     {
487       k1 = k2;
488 
489       num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f));
490       CalcBands(diff0, k0, k1, num_bands0);       /* CalcBands1 => diff0 */
491       FDKsbrEnc_Shellsort_int(diff0, num_bands0); /* SortBands sort diff0 */
492 
493       if (diff0[0] == 0) /* too wide FB bands for target tuning */
494       {
495         return (1); /* raise the cross-over frequency and/or lower the number
496                        of target bands per octave (or lower the sampling
497                        frequency */
498       }
499 
500       cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */
501       *h_num_bands = num_bands0;                 /* Output nr of bands */
502     }
503   } else /* Linear mode */
504   {
505     if (alterScale == 0) {
506       dk = 1;
507       num_bands0 = 2 * ((k2 - k0) / 2); /* FLOOR to get to few number of bands*/
508     } else {
509       dk = 2;
510       num_bands0 =
511           2 * (((k2 - k0) / dk + 1) / 2); /* ROUND to get closest fit */
512     }
513 
514     k2_achived = k0 + num_bands0 * dk;
515     k2_diff = k2 - k2_achived;
516 
517     for (i = 0; i < num_bands0; i++) diff_tot[i] = dk;
518 
519     /* If linear scale wasn't achived */
520     /* and we got wide SBR are */
521     if (k2_diff < 0) {
522       incr = 1;
523       i = 0;
524     }
525 
526     /* If linear scale wasn't achived */
527     /* and we got small SBR are */
528     if (k2_diff > 0) {
529       incr = -1;
530       i = num_bands0 - 1;
531     }
532 
533     /* Adjust diff vector to get sepc. SBR range */
534     while (k2_diff != 0) {
535       diff_tot[i] = diff_tot[i] - incr;
536       i = i + incr;
537       k2_diff = k2_diff + incr;
538     }
539 
540     cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */
541     *h_num_bands = num_bands0;                    /* Output nr of bands */
542   }
543 
544   if (*h_num_bands < 1) return (1); /*To small sbr area */
545 
546   return (0);
547 } /* End FDKsbrEnc_UpdateFreqScale */
548 
numberOfBands(INT b_p_o,INT start,INT stop,FIXP_DBL warp_factor)549 static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor) {
550   INT result = 0;
551   /* result = 2* (INT) ( (double)b_p_o *
552    * (double)(FDKlog((double)stop/(double)start)/FDKlog((double)2)) *
553    * (double)FX_DBL2FL(warp_factor) + 0.5); */
554   result = ((b_p_o * fMult((CalcLdInt(stop) - CalcLdInt(start)), warp_factor) +
555              (FL2FX_DBL(0.5f) >> LD_DATA_SHIFT)) >>
556             ((DFRACT_BITS - 1) - LD_DATA_SHIFT))
557            << 1; /* do not optimize anymore (rounding!!) */
558 
559   return (result);
560 }
561 
CalcBands(INT * diff,INT start,INT stop,INT num_bands)562 static void CalcBands(INT *diff, INT start, INT stop, INT num_bands) {
563   INT i, qb, qe, qtmp;
564   INT previous;
565   INT current;
566   FIXP_DBL base, exp, tmp;
567 
568   previous = start;
569   for (i = 1; i <= num_bands; i++) {
570     base = fDivNorm((FIXP_DBL)stop, (FIXP_DBL)start, &qb);
571     exp = fDivNorm((FIXP_DBL)i, (FIXP_DBL)num_bands, &qe);
572     tmp = fPow(base, qb, exp, qe, &qtmp);
573     tmp = fMult(tmp, (FIXP_DBL)(start << 24));
574     current = (INT)scaleValue(tmp, qtmp - 23);
575     current = (current + 1) >> 1; /* rounding*/
576     diff[i - 1] = current - previous;
577     previous = current;
578   }
579 
580 } /* End CalcBands */
581 
cumSum(INT start_value,INT * diff,INT length,UCHAR * start_adress)582 static void cumSum(INT start_value, INT *diff, INT length,
583                    UCHAR *start_adress) {
584   INT i;
585   start_adress[0] = start_value;
586   for (i = 1; i <= length; i++)
587     start_adress[i] = start_adress[i - 1] + diff[i - 1];
588 } /* End cumSum */
589 
modifyBands(INT max_band_previous,INT * diff,INT length)590 static INT modifyBands(INT max_band_previous, INT *diff, INT length) {
591   INT change = max_band_previous - diff[0];
592 
593   /* Limit the change so that the last band cannot get narrower than the first
594    * one */
595   if (change > (diff[length - 1] - diff[0]) / 2)
596     change = (diff[length - 1] - diff[0]) / 2;
597 
598   diff[0] += change;
599   diff[length - 1] -= change;
600   FDKsbrEnc_Shellsort_int(diff, length);
601 
602   return (0);
603 } /* End modifyBands */
604 
605 /*******************************************************************************
606  Functionname:  FDKsbrEnc_UpdateHiRes
607  *******************************************************************************
608  Description:
609 
610 
611  Arguments:
612 
613  Return:
614  *******************************************************************************/
FDKsbrEnc_UpdateHiRes(UCHAR * h_hires,INT * num_hires,UCHAR * v_k_master,INT num_master,INT * xover_band)615 INT FDKsbrEnc_UpdateHiRes(UCHAR *h_hires, INT *num_hires, UCHAR *v_k_master,
616                           INT num_master, INT *xover_band) {
617   INT i;
618   INT max1, max2;
619 
620   if ((v_k_master[*xover_band] >
621        32) || /* v_k_master[*xover_band] > noQMFChannels(dualRate)/divider */
622       (*xover_band > num_master)) {
623     /* xover_band error, too big for this startFreq. Will be clipped */
624 
625     /* Calculate maximum value for xover_band */
626     max1 = 0;
627     max2 = num_master;
628     while ((v_k_master[max1 + 1] < 32) && /* noQMFChannels(dualRate)/divider */
629            ((max1 + 1) < max2)) {
630       max1++;
631     }
632 
633     *xover_band = max1;
634   }
635 
636   *num_hires = num_master - *xover_band;
637   for (i = *xover_band; i <= num_master; i++) {
638     h_hires[i - *xover_band] = v_k_master[i];
639   }
640 
641   return (0);
642 } /* End FDKsbrEnc_UpdateHiRes */
643 
644 /*******************************************************************************
645  Functionname:  FDKsbrEnc_UpdateLoRes
646  *******************************************************************************
647  Description:
648 
649  Arguments:
650 
651  Return:
652  *******************************************************************************/
FDKsbrEnc_UpdateLoRes(UCHAR * h_lores,INT * num_lores,UCHAR * h_hires,INT num_hires)653 void FDKsbrEnc_UpdateLoRes(UCHAR *h_lores, INT *num_lores, UCHAR *h_hires,
654                            INT num_hires) {
655   INT i;
656 
657   if (num_hires % 2 == 0) /* if even number of hires bands */
658   {
659     *num_lores = num_hires / 2;
660     /* Use every second lores=hires[0,2,4...] */
661     for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2];
662 
663   } else /* odd number of hires which means xover is odd */
664   {
665     *num_lores = (num_hires + 1) / 2;
666 
667     /* Use lores=hires[0,1,3,5 ...] */
668     h_lores[0] = h_hires[0];
669     for (i = 1; i <= *num_lores; i++) {
670       h_lores[i] = h_hires[i * 2 - 1];
671     }
672   }
673 
674 } /* End FDKsbrEnc_UpdateLoRes */
675