diff options
Diffstat (limited to 'libSBRdec/src/sbrdec_freq_sca.cpp')
-rw-r--r-- | libSBRdec/src/sbrdec_freq_sca.cpp | 723 |
1 files changed, 373 insertions, 350 deletions
diff --git a/libSBRdec/src/sbrdec_freq_sca.cpp b/libSBRdec/src/sbrdec_freq_sca.cpp index 8adfbb1..165f94b 100644 --- a/libSBRdec/src/sbrdec_freq_sca.cpp +++ b/libSBRdec/src/sbrdec_freq_sca.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. 1. INTRODUCTION -The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements -the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. -This FDK AAC Codec software is intended to be used on a wide variety of Android devices. - -AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual -audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by -independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part -of the MPEG specifications. - -Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) -may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners -individually for the purpose of encoding or decoding bit streams in products that are compliant with -the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license -these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec -software may already be covered under those patent licenses when it is used for those licensed purposes only. - -Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, -are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional -applications information and documentation. +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. 2. COPYRIGHT LICENSE -Redistribution and use in source and binary forms, with or without modification, are permitted without -payment of copyright license fees provided that you satisfy the following conditions: +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: -You must retain the complete text of this software license in redistributions of the FDK AAC Codec or -your modifications thereto in source code form. +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. -You must retain the complete text of this software license in the documentation and/or other materials -provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. -You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your modifications thereto to recipients of copies in binary form. -The name of Fraunhofer may not be used to endorse or promote products derived from this library without -prior written permission. +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. -You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec -software or your modifications thereto. +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. -Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software -and the date of any change. For modified versions of the FDK AAC Codec, the term -"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term -"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." 3. NO PATENT LICENSE -NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, -ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with -respect to this software. +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. -You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized -by appropriate patent licenses. +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. 4. DISCLAIMER -This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors -"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties -of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, -including but not limited to procurement of substitute goods or services; loss of use, data, or profits, -or business interruption, however caused and on any theory of liability, whether in contract, strict -liability, or tort (including negligence), arising in any way out of the use of this software, even if -advised of the possibility of such damage. +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. 5. CONTACT INFORMATION @@ -79,11 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Frequency scale calculation + \brief Frequency scale calculation */ #include "sbrdec_freq_sca.h" @@ -92,18 +111,16 @@ amm-info@iis.fraunhofer.de #include "sbr_rom.h" #include "env_extr.h" -#include "genericStds.h" /* need log() for debug-code only */ - -#define MAX_OCTAVE 29 -#define MAX_SECOND_REGION 50 - - -static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); -static void CalcBands(UCHAR * diff, UCHAR start, UCHAR stop, UCHAR num_bands); -static SBR_ERROR modifyBands(UCHAR max_band, UCHAR * diff, UCHAR length); -static void cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress); +#include "genericStds.h" /* need log() for debug-code only */ +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 +static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); +static void CalcBands(UCHAR *diff, UCHAR start, UCHAR stop, UCHAR num_bands); +static SBR_ERROR modifyBands(UCHAR max_band, UCHAR *diff, UCHAR length); +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress); /*! \brief Retrieve QMF-band where the SBR range starts @@ -113,41 +130,61 @@ static void cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_ad \return Number of start band */ -static UCHAR -getStartBand(UINT fs, /*!< Output sampling frequency */ - UCHAR startFreq, /*!< Index to table of possible start bands */ - UINT headerDataFlags) /*!< Info to SBR mode */ +static UCHAR getStartBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR startFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags) /*!< Info to SBR mode */ { - INT band; - UINT fsMapped; + INT band; + UINT fsMapped = fs; + SBR_RATE rate = DUAL; + + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + rate = QUAD; + } + fsMapped = sbrdec_mapToStdSampleRate(fs, 1); + } - fsMapped = fs; + FDK_ASSERT(2 * (rate + 1) <= (4)); switch (fsMapped) { + case 192000: + band = FDK_sbrDecoder_sbr_start_freq_192[startFreq]; + break; + case 176400: + band = FDK_sbrDecoder_sbr_start_freq_176[startFreq]; + break; + case 128000: + band = FDK_sbrDecoder_sbr_start_freq_128[startFreq]; + break; case 96000: case 88200: - band = FDK_sbrDecoder_sbr_start_freq_88[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_88[rate][startFreq]; break; case 64000: - band = FDK_sbrDecoder_sbr_start_freq_64[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_64[rate][startFreq]; break; case 48000: - band = FDK_sbrDecoder_sbr_start_freq_48[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_48[rate][startFreq]; break; case 44100: - band = FDK_sbrDecoder_sbr_start_freq_44[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_44[rate][startFreq]; + break; + case 40000: + band = FDK_sbrDecoder_sbr_start_freq_40[rate][startFreq]; break; case 32000: - band = FDK_sbrDecoder_sbr_start_freq_32[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_32[rate][startFreq]; break; case 24000: - band = FDK_sbrDecoder_sbr_start_freq_24[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_24[rate][startFreq]; break; case 22050: - band = FDK_sbrDecoder_sbr_start_freq_22[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_22[rate][startFreq]; break; case 16000: - band = FDK_sbrDecoder_sbr_start_freq_16[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_16[rate][startFreq]; break; default: band = 255; @@ -156,7 +193,6 @@ getStartBand(UINT fs, /*!< Output sampling frequency */ return band; } - /*! \brief Retrieve QMF-band where the SBR range starts @@ -165,29 +201,32 @@ getStartBand(UINT fs, /*!< Output sampling frequency */ \return Number of start band */ -static UCHAR -getStopBand(UINT fs, /*!< Output sampling frequency */ - UCHAR stopFreq, /*!< Index to table of possible start bands */ - UINT headerDataFlags, /*!< Info to SBR mode */ - UCHAR k0) /*!< Start freq index */ +static UCHAR getStopBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR stopFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags, /*!< Info to SBR mode */ + UCHAR k0) /*!< Start freq index */ { UCHAR k2; if (stopFreq < 14) { - INT stopMin; - UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + INT stopMin; + INT num = 2 * (64); + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; UCHAR *diff0 = diff_tot; - UCHAR *diff1 = diff_tot+MAX_OCTAVE; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; - if (fs < 32000) { - stopMin = (((2*6000*2*(64)) / fs) + 1) >> 1; + if (headerDataFlags & SBRDEC_QUAD_RATE) { + num >>= 1; } - else { + + if (fs < 32000) { + stopMin = (((2 * 6000 * num) / fs) + 1) >> 1; + } else { if (fs < 64000) { - stopMin = (((2*8000*2*(64)) / fs) + 1) >> 1; - } - else { - stopMin = (((2*10000*2*(64)) / fs) + 1) >> 1; + stopMin = (((2 * 8000 * num) / fs) + 1) >> 1; + } else { + stopMin = (((2 * 10000 * num) / fs) + 1) >> 1; } } @@ -196,44 +235,49 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ based on a logarithmic scale. The vectors diff0 and diff1 are used temporarily here. */ - CalcBands( diff0, stopMin, 64, 13); - shellsort( diff0, 13); + CalcBands(diff0, stopMin, 64, 13); + shellsort(diff0, 13); cumSum(stopMin, diff0, 13, diff1); k2 = diff1[stopFreq]; - } - else if (stopFreq==14) - k2 = 2*k0; + } else if (stopFreq == 14) + k2 = 2 * k0; else - k2 = 3*k0; + k2 = 3 * k0; /* Limit to Nyquist */ - if (k2 > (64)) - k2 = (64); - + if (k2 > (64)) k2 = (64); /* Range checks */ /* 1 <= difference <= 48; 1 <= fs <= 96000 */ - if ( ((k2 - k0) > MAX_FREQ_COEFFS) || (k2 <= k0) ) { - return 255; + { + UCHAR max_freq_coeffs = (headerDataFlags & SBRDEC_QUAD_RATE) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS; + if (((k2 - k0) > max_freq_coeffs) || (k2 <= k0)) { + return 255; + } } - if (headerDataFlags & (SBRDEC_SYNTAX_USAC|SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + return k2; /* skip other checks: (k2 - k0) must be <= + MAX_FREQ_COEFFS_QUAD_RATE for all fs */ + } + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { /* 1 <= difference <= 35; 42000 <= fs <= 96000 */ - if ( (fs >= 42000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + if ((fs >= 42000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { return 255; } /* 1 <= difference <= 32; 46009 <= fs <= 96000 */ - if ( (fs >= 46009) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + if ((fs >= 46009) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { return 255; } - } - else { + } else { /* 1 <= difference <= 35; fs == 44100 */ - if ( (fs == 44100) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + if ((fs == 44100) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { return 255; } /* 1 <= difference <= 32; 48000 <= fs <= 96000 */ - if ( (fs >= 48000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + if ((fs >= 48000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { return 255; } } @@ -241,7 +285,6 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ return k2; } - /*! \brief Generates master frequency tables @@ -252,29 +295,33 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ \return errorCode, 0 if successful */ SBR_ERROR -sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ - UCHAR *numMaster, /*!< Number of entries in master table */ - UINT fs, /*!< SBR working sampling rate */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ - UINT flags) -{ - FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ - INT dk=0; +sbrdecUpdateFreqScale( + UCHAR *v_k_master, /*!< Master table to be created */ + UCHAR *numMaster, /*!< Number of entries in master table */ + UINT fs, /*!< SBR working sampling rate */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ + UINT flags) { + FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ + INT dk = 0; /* Internal variables */ - UCHAR k0, k2, i; - UCHAR num_bands0 = 0; - UCHAR num_bands1 = 0; - UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR k0, k2, i; + UCHAR num_bands0 = 0; + UCHAR num_bands1 = 0; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; UCHAR *diff0 = diff_tot; - UCHAR *diff1 = diff_tot+MAX_OCTAVE; - INT k2_achived; - INT k2_diff; - INT incr=0; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; /* Determine start band */ + if (flags & SBRDEC_QUAD_RATE) { + fs >>= 1; + } + k0 = getStartBand(fs, hHeaderData->bs_data.startFreq, flags); if (k0 == 255) { return SBRDEC_UNSUPPORTED_CONFIG; @@ -288,127 +335,134 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ return SBRDEC_UNSUPPORTED_CONFIG; } - if(hHeaderData->bs_data.freqScale>0) { /* Bark */ + if (hHeaderData->bs_data.freqScale > 0) { /* Bark */ INT k1; - if(hHeaderData->bs_data.freqScale==1) { - bpo_div16 = FL2FXCONST_SGL(12.0f/16.0f); - } - else if(hHeaderData->bs_data.freqScale==2) { - bpo_div16 = FL2FXCONST_SGL(10.0f/16.0f); - } - else { - bpo_div16 = FL2FXCONST_SGL(8.0f/16.0f); + if (hHeaderData->bs_data.freqScale == 1) { + bpo_div16 = FL2FXCONST_SGL(12.0f / 16.0f); + } else if (hHeaderData->bs_data.freqScale == 2) { + bpo_div16 = FL2FXCONST_SGL(10.0f / 16.0f); + } else { + bpo_div16 = FL2FXCONST_SGL(8.0f / 16.0f); } + /* Ref: ISO/IEC 23003-3, Figure 12 - Flowchart calculation of fMaster for + * 4:1 system when bs_freq_scale > 0 */ + if (flags & SBRDEC_QUAD_RATE) { + if ((SHORT)k0 < (SHORT)(bpo_div16 >> ((FRACT_BITS - 1) - 4))) { + bpo_div16 = (FIXP_SGL)(k0 & (UCHAR)0xfe) + << ((FRACT_BITS - 1) - 4); /* bpo_div16 = floor(k0/2)*2 */ + } + } - if( 1000 * k2 > 2245 * k0 ) { /* Two or more regions */ - k1 = 2*k0; + if (1000 * k2 > 2245 * k0) { /* Two or more regions */ + k1 = 2 * k0; num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); - num_bands1 = numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale ); - if ( num_bands0 < 1) { + num_bands1 = + numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale); + if (num_bands0 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } - if ( num_bands1 < 1 ) { + if (num_bands1 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } CalcBands(diff0, k0, k1, num_bands0); - shellsort( diff0, num_bands0); + shellsort(diff0, num_bands0); if (diff0[0] == 0) { -#ifdef DEBUG_TOOLS -#endif return SBRDEC_UNSUPPORTED_CONFIG; } cumSum(k0, diff0, num_bands0, v_k_master); CalcBands(diff1, k1, k2, num_bands1); - shellsort( diff1, num_bands1); - if(diff0[num_bands0-1] > diff1[0]) { + shellsort(diff1, num_bands1); + if (diff0[num_bands0 - 1] > diff1[0]) { SBR_ERROR err; - err = modifyBands(diff0[num_bands0-1],diff1, num_bands1); - if (err) - return SBRDEC_UNSUPPORTED_CONFIG; + err = modifyBands(diff0[num_bands0 - 1], diff1, num_bands1); + if (err) return SBRDEC_UNSUPPORTED_CONFIG; } /* Add 2nd region */ cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); - *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ + *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ - } - else { /* Only one region */ - k1=k2; + } else { /* Only one region */ + k1 = k2; num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); - if ( num_bands0 < 1) { + if (num_bands0 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } CalcBands(diff0, k0, k1, num_bands0); shellsort(diff0, num_bands0); if (diff0[0] == 0) { -#ifdef DEBUG_TOOLS -#endif return SBRDEC_UNSUPPORTED_CONFIG; } cumSum(k0, diff0, num_bands0, v_k_master); - *numMaster = num_bands0; /* Output nr of bands */ - + *numMaster = num_bands0; /* Output nr of bands */ + } + } else { /* Linear mode */ + if (hHeaderData->bs_data.alterScale == 0) { + dk = 1; + /* FLOOR to get to few number of bands (next lower even number) */ + num_bands0 = (k2 - k0) & 254; + } else { + dk = 2; + num_bands0 = (((k2 - k0) >> 1) + 1) & 254; /* ROUND to the closest fit */ } - } - else { /* Linear mode */ - if (hHeaderData->bs_data.alterScale==0) { - dk = 1; - /* FLOOR to get to few number of bands (next lower even number) */ - num_bands0 = (k2 - k0) & 254; - } else { - dk = 2; - num_bands0 = ( ((k2 - k0) >> 1) + 1 ) & 254; /* ROUND to the closest fit */ - } - if (num_bands0 < 1) { - return SBRDEC_UNSUPPORTED_CONFIG; - /* We must return already here because 'i' can become negative below. */ - } + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + /* We must return already here because 'i' can become negative below. */ + } - k2_achived = k0 + num_bands0*dk; - k2_diff = k2 - k2_achived; + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; - for(i=0;i<num_bands0;i++) - diff_tot[i] = dk; + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; - /* If linear scale wasn't achieved */ - /* and we got too wide SBR area */ - if (k2_diff < 0) { - incr = 1; - i = 0; - } + /* If linear scale wasn't achieved */ + /* and we got too wide SBR area */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } - /* If linear scale wasn't achieved */ - /* and we got too small SBR area */ - if (k2_diff > 0) { - incr = -1; - i = num_bands0-1; - } + /* If linear scale wasn't achieved */ + /* and we got too small SBR area */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } - /* Adjust diff vector to get sepc. SBR range */ - while (k2_diff != 0) { - diff_tot[i] = diff_tot[i] - incr; - i = i + incr; - k2_diff = k2_diff + incr; - } + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } - cumSum(k0, diff_tot, num_bands0, v_k_master);/* cumsum */ - *numMaster = num_bands0; /* Output nr of bands */ + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *numMaster = num_bands0; /* Output nr of bands */ } if (*numMaster < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } + /* Ref: ISO/IEC 23003-3 Cor.3, "In 7.5.5.2, add to the requirements:"*/ + if (flags & SBRDEC_QUAD_RATE) { + int k; + for (k = 1; k < *numMaster; k++) { + if (!(v_k_master[k] - v_k_master[k - 1] <= k0 - 2)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + } /* Print out the calculated table @@ -417,7 +471,6 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ return SBRDEC_OK; } - /*! \brief Calculate frequency ratio of one SBR band @@ -427,56 +480,52 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ \return num_band-th root of k_start/k_stop */ -static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) -{ -/* Scaled bandfactor and step 1 bit right to avoid overflow - * use double data type */ +static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) { + /* Scaled bandfactor and step 1 bit right to avoid overflow + * use double data type */ FIXP_DBL bandfactor = FL2FXCONST_DBL(0.25f); /* Start value */ - FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ + FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ - int direction = 1; + int direction = 1; -/* Because saturation can't be done in INT IIS, - * changed start and stop data type from FIXP_SGL to FIXP_DBL */ - FIXP_DBL start = k_start << (DFRACT_BITS-8); - FIXP_DBL stop = k_stop << (DFRACT_BITS-8); + /* Because saturation can't be done in INT IIS, + * changed start and stop data type from FIXP_SGL to FIXP_DBL */ + FIXP_DBL start = k_start << (DFRACT_BITS - 8); + FIXP_DBL stop = k_stop << (DFRACT_BITS - 8); FIXP_DBL temp; - int j, i=0; + int j, i = 0; - while ( step > FL2FXCONST_DBL(0.0f)) { + while (step > FL2FXCONST_DBL(0.0f)) { i++; temp = stop; /* Calculate temp^num_bands: */ - for (j=0; j<num_bands; j++) - //temp = fMult(temp,bandfactor); - temp = fMultDiv2(temp,bandfactor)<<2; + for (j = 0; j < num_bands; j++) + // temp = fMult(temp,bandfactor); + temp = fMultDiv2(temp, bandfactor) << 2; - if (temp<start) { /* Factor too strong, make it weaker */ + if (temp < start) { /* Factor too strong, make it weaker */ if (direction == 0) /* Halfen step. Right shift is not done as fract because otherwise the lowest bit cannot be cleared due to rounding */ step = (FIXP_DBL)((LONG)step >> 1); direction = 1; bandfactor = bandfactor + step; - } - else { /* Factor is too weak: make it stronger */ - if (direction == 1) - step = (FIXP_DBL)((LONG)step >> 1); + } else { /* Factor is too weak: make it stronger */ + if (direction == 1) step = (FIXP_DBL)((LONG)step >> 1); direction = 0; bandfactor = bandfactor - step; } - if (i>100) { + if (i > 100) { step = FL2FXCONST_DBL(0.0f); } } - return FX_DBL2FX_SGL(bandfactor<<1); + return FX_DBL2FX_SGL(bandfactor << 1); } - /*! \brief Calculate number of SBR bands between start and stop band @@ -487,34 +536,35 @@ static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) \return number of bands */ -static int -numberOfBands(FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ - int start, /*!< First QMF band of SBR frequency range */ - int stop, /*!< Last QMF band of SBR frequency range + 1 */ - int warpFlag) /*!< Stretching flag */ +static int numberOfBands( + FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ + int start, /*!< First QMF band of SBR frequency range */ + int stop, /*!< Last QMF band of SBR frequency range + 1 */ + int warpFlag) /*!< Stretching flag */ { FIXP_SGL num_bands_div128; - int num_bands; + int num_bands; - num_bands_div128 = FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start,stop),bpo_div16)); + num_bands_div128 = + FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start, stop), bpo_div16)); if (warpFlag) { /* Apply the warp factor of 1.3 to get wider bands. We use a value of 32768/25200 instead of the exact value to avoid critical cases of rounding. */ - num_bands_div128 = FX_DBL2FX_SGL(fMult(num_bands_div128, FL2FXCONST_SGL(25200.0/32768.0))); + num_bands_div128 = FX_DBL2FX_SGL( + fMult(num_bands_div128, FL2FXCONST_SGL(25200.0 / 32768.0))); } /* add scaled 1 for rounding to even numbers: */ - num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL( 1.0f/128.0f ); + num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL(1.0f / 128.0f); /* scale back to right aligned integer and double the value: */ num_bands = 2 * ((LONG)num_bands_div128 >> (FRACT_BITS - 7)); - return(num_bands); + return (num_bands); } - /*! \brief Calculate width of SBR bands @@ -522,11 +572,10 @@ numberOfBands(FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided this function calculates the width of each SBR band in QMF channels. The bands get wider from start to stop (bark scale). */ -static void -CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ - UCHAR start, /*!< Lower end of subband range */ - UCHAR stop, /*!< Upper end of subband range */ - UCHAR num_bands) /*!< Desired number of bands */ +static void CalcBands(UCHAR *diff, /*!< Vector of widths to be calculated */ + UCHAR start, /*!< Lower end of subband range */ + UCHAR stop, /*!< Upper end of subband range */ + UCHAR num_bands) /*!< Desired number of bands */ { int i; int previous; @@ -535,18 +584,20 @@ CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ FIXP_SGL bandfactor = calcFactorPerBand(start, stop, num_bands); previous = stop; /* Start with highest QMF channel */ - exact = (FIXP_SGL)(stop << (FRACT_BITS-8)); /* Shift left to gain some accuracy */ + exact = (FIXP_SGL)( + stop << (FRACT_BITS - 8)); /* Shift left to gain some accuracy */ - for(i=num_bands-1; i>=0; i--) { + for (i = num_bands - 1; i >= 0; i--) { /* Calculate border of next lower sbr band */ - exact = FX_DBL2FX_SGL(fMult(exact,bandfactor)); + exact = FX_DBL2FX_SGL(fMult(exact, bandfactor)); /* Add scaled 0.5 for rounding: - We use a value 128/256 instead of 0.5 to avoid some critical cases of rounding. */ - temp = exact + FL2FXCONST_SGL(128.0/32768.0); + We use a value 128/256 instead of 0.5 to avoid some critical cases of + rounding. */ + temp = exact + FL2FXCONST_SGL(128.0 / 32768.0); /* scale back to right alinged integer: */ - current = (LONG)temp >> (FRACT_BITS-8); + current = (LONG)temp >> (FRACT_BITS - 8); /* Save width of band i */ diff[i] = previous - current; @@ -554,20 +605,17 @@ CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ } } - /*! \brief Calculate cumulated sum vector from delta vector */ -static void -cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress) -{ +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress) { int i; - start_adress[0]=start_value; - for(i=1; i<=length; i++) - start_adress[i] = start_adress[i-1] + diff[i-1]; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; } - /*! \brief Adapt width of frequency bands in the second region @@ -575,116 +623,96 @@ cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress) is calculated separately. This function tries to avoid that the second region starts with a band smaller than the highest band of the first region. */ -static SBR_ERROR -modifyBands(UCHAR max_band_previous, UCHAR * diff, UCHAR length) -{ +static SBR_ERROR modifyBands(UCHAR max_band_previous, UCHAR *diff, + UCHAR length) { int change = max_band_previous - diff[0]; - /* Limit the change so that the last band cannot get narrower than the first one */ - if ( change > (diff[length-1]-diff[0])>>1 ) - change = (diff[length-1]-diff[0])>>1; + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) >> 1) + change = (diff[length - 1] - diff[0]) >> 1; diff[0] += change; - diff[length-1] -= change; + diff[length - 1] -= change; shellsort(diff, length); return SBRDEC_OK; } - /*! \brief Update high resolution frequency band table */ -static void -sbrdecUpdateHiRes(UCHAR * h_hires, - UCHAR * num_hires, - UCHAR * v_k_master, - UCHAR num_bands, - UCHAR xover_band) -{ +static void sbrdecUpdateHiRes(UCHAR *h_hires, UCHAR *num_hires, + UCHAR *v_k_master, UCHAR num_bands, + UCHAR xover_band) { UCHAR i; - *num_hires = num_bands-xover_band; + *num_hires = num_bands - xover_band; - for(i=xover_band; i<=num_bands; i++) { - h_hires[i-xover_band] = v_k_master[i]; + for (i = xover_band; i <= num_bands; i++) { + h_hires[i - xover_band] = v_k_master[i]; } } - /*! \brief Build low resolution table out of high resolution table */ -static void -sbrdecUpdateLoRes(UCHAR * h_lores, - UCHAR * num_lores, - UCHAR * h_hires, - UCHAR num_hires) -{ +static void sbrdecUpdateLoRes(UCHAR *h_lores, UCHAR *num_lores, UCHAR *h_hires, + UCHAR num_hires) { UCHAR i; - if( (num_hires & 1) == 0) { + if ((num_hires & 1) == 0) { /* If even number of hires bands */ *num_lores = num_hires >> 1; /* Use every second lores=hires[0,2,4...] */ - for(i=0; i<=*num_lores; i++) - h_lores[i] = h_hires[i*2]; - } - else { + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + } else { /* Odd number of hires, which means xover is odd */ - *num_lores = (num_hires+1) >> 1; + *num_lores = (num_hires + 1) >> 1; /* Use lores=hires[0,1,3,5 ...] */ h_lores[0] = h_hires[0]; - for(i=1; i<=*num_lores; i++) { - h_lores[i] = h_hires[i*2-1]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; } } } - /*! - \brief Derive a low-resolution frequency-table from the master frequency table + \brief Derive a low-resolution frequency-table from the master frequency + table */ -void -sbrdecDownSampleLoRes(UCHAR *v_result, - UCHAR num_result, - UCHAR *freqBandTableRef, - UCHAR num_Ref) -{ +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref) { int step; - int i,j; - int org_length,result_length; - int v_index[MAX_FREQ_COEFFS>>1]; + int i, j; + int org_length, result_length; + int v_index[MAX_FREQ_COEFFS >> 1]; /* init */ org_length = num_Ref; result_length = num_result; - v_index[0] = 0; /* Always use left border */ - i=0; - while(org_length > 0) { + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) { /* Create downsample vector */ i++; step = org_length / result_length; org_length = org_length - step; result_length--; - v_index[i] = v_index[i-1] + step; + v_index[i] = v_index[i - 1] + step; } - for(j=0;j<=i;j++) { + for (j = 0; j <= i; j++) { /* Use downsample vector to index LoResolution vector */ - v_result[j]=freqBandTableRef[v_index[j]]; + v_result[j] = freqBandTableRef[v_index[j]]; } - } - /*! \brief Sorting routine */ -void shellsort(UCHAR *in, UCHAR n) -{ - +void shellsort(UCHAR *in, UCHAR n) { int i, j, v, w; int inc = 1; @@ -697,115 +725,110 @@ void shellsort(UCHAR *in, UCHAR n) for (i = inc; i < n; i++) { v = in[i]; j = i; - while ((w=in[j-inc]) > v) { + while ((w = in[j - inc]) > v) { in[j] = w; j -= inc; - if (j < inc) - break; + if (j < inc) break; } in[j] = v; } } while (inc > 1); - } - - /*! \brief Reset frequency band tables \return errorCode, 0 if successful */ SBR_ERROR -resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) -{ +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) { SBR_ERROR err = SBRDEC_OK; - int k2,kx, lsb, usb; - int intTemp; - UCHAR nBandsLo, nBandsHi; + int k2, kx, lsb, usb; + int intTemp; + UCHAR nBandsLo, nBandsHi; HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; /* Calculate master frequency function */ - err = sbrdecUpdateFreqScale(hFreq->v_k_master, - &hFreq->numMaster, - hHeaderData->sbrProcSmplRate, - hHeaderData, - flags); + err = sbrdecUpdateFreqScale(hFreq->v_k_master, &hFreq->numMaster, + hHeaderData->sbrProcSmplRate, hHeaderData, flags); - if ( err || (hHeaderData->bs_info.xover_band > hFreq->numMaster) ) { + if (err || (hHeaderData->bs_info.xover_band > hFreq->numMaster)) { return SBRDEC_UNSUPPORTED_CONFIG; } /* Derive Hiresolution from master frequency function */ - sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, hFreq->numMaster, hHeaderData->bs_info.xover_band ); + sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, + hFreq->numMaster, hHeaderData->bs_info.xover_band); /* Derive Loresolution from Hiresolution */ - sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], nBandsHi); - + sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], + nBandsHi); hFreq->nSfb[0] = nBandsLo; hFreq->nSfb[1] = nBandsHi; /* Check index to freqBandTable[0] */ - if ( !(nBandsLo > 0) || (nBandsLo > (MAX_FREQ_COEFFS>>1)) ) { + if (!(nBandsLo > 0) || + (nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS_DUAL_RATE) >> + 1))) { return SBRDEC_UNSUPPORTED_CONFIG; } lsb = hFreq->freqBandTable[0][0]; usb = hFreq->freqBandTable[0][nBandsLo]; - /* Additional check for lsb */ - if ( (lsb > (32)) || (lsb >= usb) ) { + /* Check for start frequency border k_x: + - ISO/IEC 14496-3 4.6.18.3.6 Requirements + - ISO/IEC 23003-3 7.5.5.2 Modifications and additions to the MPEG-4 SBR + tool + */ + /* Note that lsb > as hHeaderData->numberOfAnalysisBands is a valid SBR config + * for 24 band QMF analysis. */ + if ((lsb > ((flags & SBRDEC_QUAD_RATE) ? 16 : (32))) || (lsb >= usb)) { return SBRDEC_UNSUPPORTED_CONFIG; } - /* Calculate number of noise bands */ k2 = hFreq->freqBandTable[1][nBandsHi]; kx = hFreq->freqBandTable[1][0]; - if (hHeaderData->bs_data.noise_bands == 0) - { + if (hHeaderData->bs_data.noise_bands == 0) { hFreq->nNfb = 1; - } - else /* Calculate no of noise bands 1,2 or 3 bands/octave */ + } else /* Calculate no of noise bands 1,2 or 3 bands/octave */ { /* Fetch number of octaves divided by 32 */ - intTemp = (LONG)FDK_getNumOctavesDiv8(kx,k2) >> 2; + intTemp = (LONG)FDK_getNumOctavesDiv8(kx, k2) >> 2; /* Integer-Multiplication with number of bands: */ intTemp = intTemp * hHeaderData->bs_data.noise_bands; /* Add scaled 0.5 for rounding: */ - intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f/32.0f); + intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f / 32.0f); /* Convert to right-aligned integer: */ intTemp = intTemp >> (FRACT_BITS - 1 /*sign*/ - 5 /* rescale */); - /* Compare with float calculation */ - FDK_ASSERT( intTemp == (int)((hHeaderData->bs_data.noise_bands * FDKlog( (float)k2/kx) / (float)(FDKlog(2.0)))+0.5) ); - - if( intTemp==0) - intTemp=1; + if (intTemp == 0) intTemp = 1; hFreq->nNfb = intTemp; } hFreq->nInvfBands = hFreq->nNfb; - if( hFreq->nNfb > MAX_NOISE_COEFFS ) { + if (hFreq->nNfb > MAX_NOISE_COEFFS) { return SBRDEC_UNSUPPORTED_CONFIG; } /* Get noise bands */ - sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, - hFreq->nNfb, - hFreq->freqBandTable[0], - nBandsLo); - - + sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb, + hFreq->freqBandTable[0], nBandsLo); + /* save old highband; required for overlap in usac + when headerchange occurs at XVAR and VARX frame; */ + hFreq->ov_highSubband = hFreq->highSubband; - hFreq->lowSubband = lsb; + hFreq->lowSubband = lsb; hFreq->highSubband = usb; return SBRDEC_OK; |