aboutsummaryrefslogtreecommitdiffstats
path: root/libAACenc/src/ms_stereo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACenc/src/ms_stereo.cpp')
-rw-r--r--libAACenc/src/ms_stereo.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/libAACenc/src/ms_stereo.cpp b/libAACenc/src/ms_stereo.cpp
new file mode 100644
index 0000000..ab0cb1c
--- /dev/null
+++ b/libAACenc/src/ms_stereo.cpp
@@ -0,0 +1,251 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2012 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.
+
+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:
+
+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
+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.
+
+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."
+
+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.
+
+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.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------------------------------------- */
+
+/******************************** MPEG Audio Encoder **************************
+
+ Initial author: M.Werner
+ contents/description: MS stereo processing
+
+******************************************************************************/
+#include "ms_stereo.h"
+
+#include "psy_const.h"
+
+/* static const float scaleMinThres = 1.0f; */ /* 0.75f for 3db boost */
+
+void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)],
+ PSY_OUT_CHANNEL* psyOutChannel[2],
+ const INT *isBook,
+ INT *msDigest, /* output */
+ INT *msMask, /* output */
+ const INT sfbCnt,
+ const INT sfbPerGroup,
+ const INT maxSfbPerGroup,
+ const INT *sfbOffset)
+{
+ FIXP_DBL *sfbEnergyLeft = psyData[0]->sfbEnergy.Long; /* modified where msMask==1 */
+ FIXP_DBL *sfbEnergyRight = psyData[1]->sfbEnergy.Long; /* modified where msMask==1 */
+ const FIXP_DBL *sfbEnergyMid = psyData[0]->sfbEnergyMS.Long;
+ const FIXP_DBL *sfbEnergySide = psyData[1]->sfbEnergyMS.Long;
+ FIXP_DBL *sfbThresholdLeft = psyData[0]->sfbThreshold.Long; /* modified where msMask==1 */
+ FIXP_DBL *sfbThresholdRight = psyData[1]->sfbThreshold.Long; /* modified where msMask==1 */
+
+ FIXP_DBL *sfbSpreadEnLeft = psyData[0]->sfbSpreadEnergy.Long;
+ FIXP_DBL *sfbSpreadEnRight = psyData[1]->sfbSpreadEnergy.Long;
+
+ FIXP_DBL *sfbEnergyLeftLdData = psyOutChannel[0]->sfbEnergyLdData; /* modified where msMask==1 */
+ FIXP_DBL *sfbEnergyRightLdData = psyOutChannel[1]->sfbEnergyLdData; /* modified where msMask==1 */
+ FIXP_DBL *sfbEnergyMidLdData = psyData[0]->sfbEnergyMSLdData;
+ FIXP_DBL *sfbEnergySideLdData = psyData[1]->sfbEnergyMSLdData;
+ FIXP_DBL *sfbThresholdLeftLdData = psyOutChannel[0]->sfbThresholdLdData; /* modified where msMask==1 */
+ FIXP_DBL *sfbThresholdRightLdData = psyOutChannel[1]->sfbThresholdLdData; /* modified where msMask==1 */
+
+ FIXP_DBL *mdctSpectrumLeft = psyData[0]->mdctSpectrum; /* modified where msMask==1 */
+ FIXP_DBL *mdctSpectrumRight = psyData[1]->mdctSpectrum; /* modified where msMask==1 */
+
+ INT sfb,sfboffs, j; /* loop counters */
+ FIXP_DBL pnlrLdData, pnmsLdData;
+ FIXP_DBL minThresholdLdData;
+ FIXP_DBL minThreshold;
+ INT useMS;
+
+ INT msMaskTrueSomewhere = 0; /* to determine msDigest */
+ INT numMsMaskFalse = 0; /* number of non-intensity bands where L/R coding is used */
+
+ for(sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
+ for(sfboffs=0;sfboffs<maxSfbPerGroup;sfboffs++) {
+
+ if ( (isBook==NULL) ? 1 : (isBook[sfb+sfboffs] == 0) ) {
+ FIXP_DBL tmp;
+
+/*
+ minThreshold=min(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs])*scaleMinThres;
+ pnlr = (sfbThresholdLeft[sfb+sfboffs]/
+ max(sfbEnergyLeft[sfb+sfboffs],sfbThresholdLeft[sfb+sfboffs]))*
+ (sfbThresholdRight[sfb+sfboffs]/
+ max(sfbEnergyRight[sfb+sfboffs],sfbThresholdRight[sfb+sfboffs]));
+ pnms = (minThreshold/max(sfbEnergyMid[sfb+sfboffs],minThreshold))*
+ (minThreshold/max(sfbEnergySide[sfb+sfboffs],minThreshold));
+ useMS = (pnms > pnlr);
+*/
+
+ /* we assume that scaleMinThres == 1.0f and we can drop it */
+ minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
+
+ /* pnlrLdData = sfbThresholdLeftLdData[sfb+sfboffs] -
+ max(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]) +
+ sfbThresholdRightLdData[sfb+sfboffs] -
+ max(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); */
+ tmp = fixMax(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]);
+ pnlrLdData = (sfbThresholdLeftLdData[sfb+sfboffs]>>1) - (tmp>>1);
+ pnlrLdData = pnlrLdData + (sfbThresholdRightLdData[sfb+sfboffs]>>1);
+ tmp = fixMax(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
+ pnlrLdData = pnlrLdData - (tmp>>1);
+
+ /* pnmsLdData = minThresholdLdData - max(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData) +
+ minThresholdLdData - max(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData); */
+ tmp = fixMax(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData);
+ pnmsLdData = minThresholdLdData - (tmp>>1);
+ tmp = fixMax(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData);
+ pnmsLdData = pnmsLdData - (tmp>>1);
+ useMS = (pnmsLdData > (pnlrLdData));
+
+
+ if (useMS) {
+ msMask[sfb+sfboffs] = 1;
+ msMaskTrueSomewhere = 1;
+ for(j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
+ FIXP_DBL specL, specR;
+ specL = mdctSpectrumLeft[j]>>1;
+ specR = mdctSpectrumRight[j]>>1;
+ mdctSpectrumLeft[j] = specL + specR;
+ mdctSpectrumRight[j] = specL - specR;
+ }
+ minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]);
+ sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold;
+ sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData;
+ sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs];
+ sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs];
+ sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs];
+ sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs];
+
+ sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] =
+ fixMin( sfbSpreadEnLeft[sfb+sfboffs],
+ sfbSpreadEnRight[sfb+sfboffs] ) >> 1;
+
+ }
+ else {
+ msMask[sfb+sfboffs] = 0;
+ numMsMaskFalse++;
+ } /* useMS */
+ } /* isBook */
+ else {
+ /* keep mDigest from IS module */
+ if (msMask[sfb+sfboffs]) {
+ msMaskTrueSomewhere = 1;
+ }
+ /* prohibit MS_MASK_ALL in combination with IS */
+ numMsMaskFalse = 9;
+ } /* isBook */
+ } /* sfboffs */
+ } /* sfb */
+
+
+ if(msMaskTrueSomewhere == 1) {
+ if ((numMsMaskFalse == 0) || ((numMsMaskFalse < maxSfbPerGroup) && (numMsMaskFalse < 9))) {
+ *msDigest = SI_MS_MASK_ALL;
+ /* loop through M/S bands; if msMask==0, set it to 1 and apply M/S */
+ for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) {
+ for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) {
+ if (( (isBook == NULL) ? 1 : (isBook[sfb+sfboffs] == 0) ) && (msMask[sfb+sfboffs] == 0)) {
+ msMask[sfb+sfboffs] = 1;
+ /* apply M/S coding */
+ for(j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
+ FIXP_DBL specL, specR;
+ specL = mdctSpectrumLeft[j]>>1;
+ specR = mdctSpectrumRight[j]>>1;
+ mdctSpectrumLeft[j] = specL + specR;
+ mdctSpectrumRight[j] = specL - specR;
+ }
+ minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]);
+ sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold;
+ minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
+ sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData;
+ sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs];
+ sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs];
+ sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs];
+ sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs];
+
+ sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] =
+ fixMin( sfbSpreadEnLeft[sfb+sfboffs],
+ sfbSpreadEnRight[sfb+sfboffs] ) >> 1;
+ }
+ }
+ }
+ } else {
+ *msDigest = SI_MS_MASK_SOME;
+ }
+ } else {
+ *msDigest = SI_MS_MASK_NONE;
+ }
+}