⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aac_enc_thr.c

📁 audio-video-codecs.rar语音编解码器
💻 C
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//          Copyright(c) 2007 Intel Corporation. All Rights Reserved.
//
//     Intel Integrated Performance Primitives AAC Encode Sample for Windows*
//
//  By downloading and installing this sample, you hereby agree that the
//  accompanying Materials are being provided to you under the terms and
//  conditions of the End User License Agreement for the Intel Integrated
//  Performance Primitives product previously accepted by you. Please refer
//  to the file ippEULA.rtf or ippEULA.txt located in the root directory of your Intel IPP
//  product installation for more information.
//
//  MPEG-4 and AAC are international standards promoted by ISO, IEC, ITU, ETSI
//  and other organizations. Implementations of these standards, or the standard
//  enabled platforms may require licenses from various entities, including
//  Intel Corporation.
//
*/

#include <math.h>
#include <stdio.h>
#include "ippac.h"
#include "ipps.h"
#include "aac_enc_quantization_fp.h"
#include "aac_enc_search.h"

/* Loudness is defined as E^0.23 (see [Zwicker and Feldtkeller, 1967])   */
/* so POWER = 1/0.23. Because of dependence of quality of encoded signal */
/* from POWER is not very high one can change POWER to 4 in order to use */
/* sqrt instead of pow                                                   */
#define POWER 4.35
#define INV_POWER (1.0 / POWER)

/* SfbPE = w * log10(energy(sfb)/thr(sfb))                                       */
/* PE = SUM sfbPE                                                                */
/* NeededPE = BitToPeCoeff * bits_per_frame                                      */
/* Let thr(x) = (thr^(1/n) + x)^n                                                */
/* NeededPE = SUM w*log10(energy(sfb)) - SUM n*w*log10(thr(sfb)^(1/n) + x) =     */
/*                           logEnergy - SUM n*w*log10(thr(sfb)^(1/n) + x),      */
/* where logEnergy = SUM w*log10(energy(sfb))                                    */
/* How to find x?                                                                */
/* Iterations:                                                                   */
/* Approximation - all thresholds are the same (average),                        */
/* NeededPE = SUM w*log10(energy(sfb)) - (SUM n*w) * log10(avThr^(1/n) + x)      */
/* Steps of each iterations:                                                     */
/* 1) Calculate current currPE = logEnergy - SUM (n*w*log10(currThr(sfb)^(1/n))) */
/* 2) Calculate current CurAvThr^(1/n):                                          */
/*    currPE = logEnergy - (SUM n*w) * log10(CurAvThr^(1/n))                     */
/*    CurAvThr^(1/n) = pow(10, (logEnergy - currPE)/(SUM n*w))                   */
/* 3) Calculate x = pow(10, (logEnergy - NeededPE)/(SUM n*w)) - CurAvThr^(1/n)   */
/* 4) Calculate new currThr(sfb)^(1/n) += x                                      */


void aac_UpdateThr(
  sEnc_individual_channel_stream* pStream,
  sQuantizationData*              qData,
  Ipp32f                          NeededPE,
  Ipp32s*                         msMask,
  Ipp32s                          ms_mask_present,
  Ipp32s                          numCh)
{
  Ipp32f powNoiseThr[2][MAX_SECTION_NUMBER];
  Ipp32f minPowNoiseThr[2][MAX_SECTION_NUMBER];
  Ipp32f minNoiseThr[2][MAX_SECTION_NUMBER];
  Ipp32s isBounded[2][MAX_SECTION_NUMBER];
  Ipp32f *sfbPE[2];
  Ipp32f *energy[2];
  Ipp32f *logEnergy[2];
  Ipp32f *minSNR[2];
  Ipp32f *noiseThr[2];
  Ipp32s *sfb_width[2];
  Ipp32s savedSfb[2];
  Ipp32s numSfb[2];
  Ipp32f PEBoundedTotal, currPE, x;
  Ipp32s max_sfb[2];
  Ipp32s i, sfb, numLines, iter;
  Ipp32f sumLogEnergy;
  Ipp32s totalBounded, found;

  for (i = 0; i < numCh; i++) {
    max_sfb[i] = pStream[i].max_sfb;
    numSfb[i] = pStream[i].num_window_groups * pStream[i].max_sfb;
    sfb_width[i] = pStream[i].sfb_width;
    sfbPE[i] = qData[i].sfbPE;
    energy[i] = qData[i].energy;
    logEnergy[i] = qData[i].logEnergy;
    minSNR[i] = qData[i].minSNR;
    noiseThr[i] = qData[i].noiseThr;

    for (sfb = 0; sfb < numSfb[i]; sfb++) {
      isBounded[i][sfb] = 0;
    }

    if (qData[i].predAttackWindow >= 0) {
      for (sfb = 0; sfb < max_sfb[i]; sfb++) {
        isBounded[i][qData[i].predAttackWindow * pStream[i].max_sfb + sfb] = 2;
      }
    }
  }

  if ((numCh == 2) && (ms_mask_present != 0)) {
    for (sfb = 0; sfb < numSfb[0]; sfb++) {
      if (msMask[sfb] == 1) {
        if (energy[0][sfb] > energy[1][sfb] && energy[1][sfb] != 0) {
          minSNR[1][sfb] *= (energy[0][sfb] / energy[1][sfb]);
          if (minSNR[1][sfb] >= 1) {
            isBounded[1][sfb] = 2;
          }
        } else if (energy[1][sfb] > energy[0][sfb] && energy[0][sfb] != 0){
          minSNR[0][sfb] *= (energy[1][sfb] / energy[0][sfb]);
          if (minSNR[0][sfb] >= 1) {
            isBounded[0][sfb] = 2;
          }
        }
      }
    }
  }

  totalBounded = 0;
  PEBoundedTotal = 0;
  currPE = 0;
  sumLogEnergy = 0;
  numLines = 0;

  for (i = 0; i < numCh; i++) {
    for (sfb = 0; sfb < numSfb[i]; sfb++) {
      minNoiseThr[i][sfb] = minSNR[i][sfb] * energy[i][sfb];
      minPowNoiseThr[i][sfb] = (Ipp32f)pow(minSNR[i][sfb] * energy[i][sfb], INV_POWER);
      powNoiseThr[i][sfb] = (Ipp32f)pow(noiseThr[i][sfb], INV_POWER);

      if (isBounded[i][sfb] != 2) {
        if (powNoiseThr[i][sfb] > minPowNoiseThr[i][sfb]) {
          isBounded[i][sfb] = 1;
          totalBounded++;
        }
      }

      /* Step 1 */
      if (sfbPE[i][sfb] > 0) {
        if (isBounded[i][sfb] != 1) {
          sumLogEnergy += sfb_width[i][sfb] * logEnergy[i][sfb];
          currPE += sfbPE[i][sfb];
          numLines += sfb_width[i][sfb];
        } else {
          PEBoundedTotal += sfbPE[i][sfb];
        }
      }
    }
  }

  if (currPE < NeededPE - PEBoundedTotal)
    return;

  iter = 0;
  while ((abs(NeededPE - currPE - PEBoundedTotal) > 0.02 * NeededPE) && (numLines > 0) && (iter < 3)) {
    /* Step 2, 3 */
    x = (Ipp32f)(pow(10, (sumLogEnergy - (NeededPE - PEBoundedTotal)) / (POWER*numLines)) -
      pow(10, (sumLogEnergy - currPE) / (POWER*numLines)));

    if (x < 0) x = 0;

    /* Step 4, 1 */
    iter++;
    currPE = 0;
    sumLogEnergy = 0;
    numLines = 0;

    for (i = 0; i < numCh; i++) {
      for (sfb = 0; sfb < numSfb[i]; sfb++) {
        Ipp32f tmp;

        if (isBounded[i][sfb] != 1) {
          tmp = powNoiseThr[i][sfb];
          powNoiseThr[i][sfb] += x;

          if (isBounded[i][sfb] != 2) {
            if (powNoiseThr[i][sfb] > minPowNoiseThr[i][sfb]) {
              powNoiseThr[i][sfb] = minPowNoiseThr[i][sfb];
              isBounded[i][sfb] = 1;
              totalBounded++;
            }
          }

          if (powNoiseThr[i][sfb] < 0)
            powNoiseThr[i][sfb] = 0;

          if (powNoiseThr[i][sfb] > 0) {
            tmp = (Ipp32f)(POWER * log10(powNoiseThr[i][sfb]));
          } else {
            tmp = -100000000;
          }

          if (logEnergy[i][sfb] > tmp) {
            sfbPE[i][sfb] = sfb_width[i][sfb] * (logEnergy[i][sfb] - tmp);
            if (isBounded[i][sfb] != 1) {
              sumLogEnergy += sfb_width[i][sfb] * logEnergy[i][sfb];
              currPE += sfbPE[i][sfb];
              numLines += sfb_width[i][sfb];
            } else {
              PEBoundedTotal += sfbPE[i][sfb];
            }
          } else {
            sfbPE[i][sfb] = -1;
          }
        }
      }
    }
  }

  for (i = 0; i < numCh; i++) {
    for (sfb = 0; sfb < numSfb[i]; sfb++) {
      noiseThr[i][sfb] = (Ipp32f)pow(powNoiseThr[i][sfb], POWER);
    }
  }

  currPE += PEBoundedTotal;

  NeededPE *= 1.4f;

  /* If currPE is very big - allow some frequency holes */
  if (currPE > NeededPE) {
    Ipp32f minEnergy, avEnergy;
    Ipp32f boundEn[4];
    Ipp32s totNumSfb, j;

    minEnergy = avEnergy = energy[0][0];
    totNumSfb = 0;

    for (i = 0; i < numCh; i++) {
      for (sfb = 0; sfb < numSfb[i]; sfb++) {
        if (minEnergy > energy[i][sfb])
          minEnergy = energy[i][sfb];

        avEnergy += energy[i][sfb];
      }
      totNumSfb += numSfb[i];
    }

    avEnergy /= totNumSfb;

    if (minEnergy < 1) minEnergy = 1;
    if (avEnergy  < 1) avEnergy = 1;

    /* log scale between minEnergy and avEnergy */
    for (i = 0; i < 4; i++) {
      boundEn[i] = (Ipp32f)(minEnergy * pow(avEnergy/minEnergy, (i+1)/4.0));
    }

    j = 0;

    for (;;) {
      for (i = 0; i < numCh; i++) {
        savedSfb[i] = numSfb[i] - 1;
      }

      found = 1;
      while ((currPE > NeededPE) && (found == 1)) {
        found = 0;
        for (i = 0; i < numCh; i++) {
          sfb = savedSfb[i];
          if (sfb == -max_sfb[i]) continue;
          while ((energy[i][sfb] > boundEn[j]) || (sfbPE[i][sfb] < 0)) {
            sfb -= max_sfb[i];
            if (sfb == -max_sfb[i]) break;
            if (sfb < 0) sfb += numSfb[i] - 1;
          }
          savedSfb[i] = sfb;
          if (sfb == -max_sfb[i]) continue;
          /* should be more than energy. Coeff doesn't matter */
          /* Here will be hole                                */
          noiseThr[i][sfb] = 10*energy[i][sfb];
          currPE -= sfbPE[i][sfb];
          sfbPE[i][sfb] = -1;
          found = 1;
        }
      }

      if (currPE <= NeededPE) break;
      j++;
      if (j >= 4) break;
    }
  }
}

/****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -