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

📄 aac_enc_quantization_int.c

📁 audio-video-codecs.rar语音编解码器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
//
//                  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) 2004-2006 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_int.h"
#include "aac_enc_search.h"

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

typedef struct
{
  Ipp32s x_min[N_LONG/2];
  Ipp32s x_min_pred[N_LONG/2];
  Ipp32s distortion[MAX_SECTION_NUMBER];
  Ipp16s saved_scale_factors[MAX_SECTION_NUMBER];
  Ipp32s saved_pred_used[MAX_SECTION_NUMBER];
  Ipp32s amplified[MAX_SECTION_NUMBER];
  Ipp32s max_dist;
  Ipp32s sum_dist;
  Ipp32s above_dist;
  Ipp32s above;
  Ipp32s max_win;
  Ipp32s max_sfb;
} sDistortionBlock;


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

static void aaciencMain_loop(sQuantizationBlock* pBlock,
                             sEnc_individual_channel_stream* pStream,
                             Ipp16s* mdct_line,
                             Ipp16s* mdct_scaled,
                             Ipp16s* mdct_line_pred,
                             Ipp16s* mdct_scaled_pred,
                             Ipp32s pow34_scaleFact);

static void aaciencCalcDist(sQuantizationBlock* pBlock,
                            sEnc_individual_channel_stream* pStream,
                            sDistortionBlock* pDist,
                            Ipp32s* mdct_line_int,
                            Ipp32s* mdct_line_pred_int,
                            Ipp32s  mdct_scaleFactor);

static Ipp32s aaciencAdjustSF(sQuantizationBlock* pBlock,
                           sEnc_individual_channel_stream* pStream,
                           sDistortionBlock* pDist,
                           Ipp16s* mdct_scaled,
                           Ipp32s* mdct_line_pred_int,
                           Ipp16s* mdct_scaled_pred,
                           Ipp32s*    pow34_scaleFact);

#define QUANT_ITER_NUM 8

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

Ipp16s scalefac_pow[] = {
  32767, 18658, 21247, 24196, 27554, 31379, 17867, 20347,
  23170, 26386, 30048, 17109, 19484, 22188, 25268, 28774
};

Ipp16s scalefac_pow_shift[] = {
  0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3
};

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

void aaciencQuantization(sQuantizationBlock* pBlock,
                         sEnc_individual_channel_stream* pStream,
                         Ipp16s* mdct_line,
                         Ipp16s* mdct_line_pred,
                         Ipp32s mdct_scaleFactor,
                         Ipp32s *p_smr)
{
  Ipp32s mdct_line_int[N_LONG/2];
  Ipp32s mdct_line_pred_int[N_LONG/2];
  Ipp32s ltp_long_used[MAX_SFB];
  Ipp16s mdct_line_abs[N_LONG/2];
  Ipp16s mdct_scaled[N_LONG/2];
  Ipp16s mdct_scaled_pred[N_LONG/2];
  Ipp16s x_quant[N_LONG/2];
  Ipp16s scale_factors[MAX_SECTION_NUMBER];
  Ipp16s sfb_cb[MAX_SECTION_NUMBER];
  sDistortionBlock Dist;
  Ipp32s *smr, *px_min, *p_mdct_line_pred_int;
  Ipp32s *sfb_offset;
  Ipp32s sum_dist = 0;         /* stupid MS warning */
  Ipp32s above_dist = 0;       /* stupid MS warning */
  Ipp32s above = 0;            /* stupid MS warning */
  Ipp32s iter = 0;             /* stupid MS warning */
  Ipp32s ltp_data_present = 0; /* stupid MS warning */
  Ipp32s pow34_scaleFact;
  Ipp32s win, sfb, i;
  Ipp32s first, itest;
  Ipp16s max_mdct_line, max_mdct_line_pred;

  ippsAbs_16s(mdct_line, mdct_line_abs, pStream->max_line);
  ippsMax_16s(mdct_line_abs, pStream->max_line, &max_mdct_line);

  if (mdct_line_pred) {
    ippsAbs_16s(mdct_line_pred, mdct_line_abs, pStream->max_line);
    ippsMax_16s(mdct_line_abs, pStream->max_line, &max_mdct_line_pred);

    if (max_mdct_line_pred > max_mdct_line) {
      max_mdct_line = max_mdct_line_pred;
    }
  }

  pow34_scaleFact = 3 * (mdct_scaleFactor >> 2) - 1;

  if (max_mdct_line != 0) {
    Ipp16s tmp_mdct_scaled;
    Ipp32s i_tmp_mdct_scaled;

    ippsPow34_16s_Sfs(&max_mdct_line, mdct_scaleFactor,
                      &tmp_mdct_scaled, pow34_scaleFact, 1);

    i_tmp_mdct_scaled = tmp_mdct_scaled;
    while (i_tmp_mdct_scaled < 16384) {
      i_tmp_mdct_scaled = i_tmp_mdct_scaled << 1;
      pow34_scaleFact--;
    }
  }

  ippsPow34_16s_Sfs(mdct_line, mdct_scaleFactor,
                    mdct_scaled, pow34_scaleFact, pStream->max_line);

  if (pBlock->ns_mode) {
    if (mdct_scaleFactor > 0) {
      for (i = 0; i < pStream->max_line; i++) {
        mdct_line_int[i] = ((Ipp32s)mdct_line[i] << mdct_scaleFactor);
      }
    } else {
      for (i = 0; i < pStream->max_line; i++) {
        mdct_line_int[i] = ((Ipp32s)mdct_line[i] >> -mdct_scaleFactor);
      }
    }

    smr = p_smr;
    sfb_offset = pStream->sfb_offset;
    px_min = Dist.x_min;
    for (win = 0; win < pStream->num_window_groups; win++) {
      for (sfb = 0; sfb < pStream->max_sfb; sfb++) {
        ippsDotProd_16s32s_Sfs(mdct_line + sfb_offset[sfb],
                               mdct_line + sfb_offset[sfb],
                               sfb_offset[sfb+1] - sfb_offset[sfb],
                               px_min + sfb, pBlock->sfb_width_scale - 1);
      }

      ippsMul_32s_ISfs(smr, px_min, pStream->max_sfb, 21);

      sfb_offset += pStream->max_sfb;
      smr += pStream->max_sfb;
      px_min += pStream->max_sfb;
    }
  }

  p_mdct_line_pred_int = 0;

  if (mdct_line_pred) {
    ippsPow34_16s_Sfs(mdct_line_pred, mdct_scaleFactor,
                      mdct_scaled_pred, pow34_scaleFact, pStream->max_line);

    if (pBlock->ns_mode) {
      if (mdct_scaleFactor > 0) {
        for (i = 0; i < pStream->max_line; i++) {
          mdct_line_pred_int[i] = ((Ipp32s)mdct_line_pred[i] << mdct_scaleFactor);
        }
      } else {
        for (i = 0; i < pStream->max_line; i++) {
          mdct_line_pred_int[i] = ((Ipp32s)mdct_line_pred[i] >> mdct_scaleFactor);
        }
      }
      p_mdct_line_pred_int = mdct_line_pred_int;
      smr = p_smr;
      sfb_offset = pStream->sfb_offset;
      px_min = Dist.x_min_pred;
      for (win = 0; win < pStream->num_window_groups; win++) {
        for (sfb = 0; sfb < pStream->max_sfb; sfb++) {
          ippsDotProd_16s32s_Sfs(mdct_line_pred + sfb_offset[sfb],
                                 mdct_line_pred + sfb_offset[sfb],
                                 sfb_offset[sfb+1] - sfb_offset[sfb],
                                 px_min + sfb, pBlock->sfb_width_scale - 1);
        }

        ippsMul_32s_ISfs(smr, px_min, pStream->max_sfb, 21);

        sfb_offset += pStream->max_sfb;
        smr += pStream->max_sfb;
        px_min += pStream->max_sfb;
      }
    }
  }

  if (pBlock->ns_mode) {
    ippsSet_32s(0, Dist.distortion,
      pStream->num_window_groups * pStream->max_sfb);
    ippsSet_16s(0, pBlock->ns_scale_factors,
      pStream->num_window_groups * pStream->max_sfb);
    ippsSet_32s(1, Dist.amplified,
      pStream->num_window_groups * pStream->max_sfb);
  }

  first = 1;
  for (;;) {
    pBlock->start_common_scalefac = -SF_OFFSET;
    pBlock->finish_common_scalefac = -SF_OFFSET;
    max_mdct_line = 0;

    ippsMax_16s(mdct_scaled, pStream->max_line, &max_mdct_line);

    if (mdct_line_pred) {
      ippsMax_16s(mdct_scaled_pred, pStream->max_line, &max_mdct_line_pred);

      if (max_mdct_line_pred > max_mdct_line) {
        max_mdct_line = max_mdct_line_pred;
      }
    }

    if (max_mdct_line > 0) {
      Ipp32s quot = pow34_scaleFact / 3;
      Ipp32s rem = pow34_scaleFact - quot * 3;
      Ipp32s shift, max_quant, j, tmp_quot, tmp;
      Ipp32s delta, add_shift;
      Ipp16s tmp_buf[16];

      if (rem > 0) {
        rem -= 3;
        quot += 1;
      }

      tmp_quot = quot;

      ippsMulC_16s_Sfs(scalefac_pow, max_mdct_line, tmp_buf, 16, 15);

      shift = 0;
      max_quant = (MAX_QUANT << (-rem));

      if (max_quant < (Ipp32s)tmp_buf[0]) {
        max_quant <<= 3;
        tmp_quot++;
      }

      for (j = 15; j >= 0; j--) {
        tmp = (Ipp32s)tmp_buf[j];
        if ((tmp << scalefac_pow_shift[j]) <= max_quant) {
          shift = j;
          break;
        }
      }

      pBlock->start_common_scalefac = tmp_quot * 16 - shift;

      shift = 16;
      delta = (65536 - MAGIC_NUMBER_I) << (2-rem);

      tmp = ((Ipp32s)tmp_buf[15] << scalefac_pow_shift[15]);
      add_shift = 0;

      while (delta > tmp) {
        tmp <<= 3;
        add_shift+=3;
        quot--;
      }

      for (j = 15; j >= 0; j--) {
        tmp = (Ipp32s)tmp_buf[j];
        if ((tmp << (scalefac_pow_shift[j] + add_shift)) < delta) {
          shift = j;
          break;
        }
      }

      if (shift == 16) {
        shift = 15;
        quot++;
      }

      pBlock->finish_common_scalefac = (quot + 6) * 16 - shift + 1;

      if (pBlock->start_common_scalefac > 255 - SF_OFFSET) {
        pBlock->start_common_scalefac = 255 - SF_OFFSET;
      } else if (pBlock->start_common_scalefac < -SF_OFFSET) {
        pBlock->start_common_scalefac = -SF_OFFSET;
      }

      if (pBlock->finish_common_scalefac > 255 - SF_OFFSET) {
        pBlock->finish_common_scalefac = 255 - SF_OFFSET;
      } else if (pBlock->finish_common_scalefac < -SF_OFFSET) {
        pBlock->finish_common_scalefac = -SF_OFFSET;
      }
    }

    aaciencMain_loop(pBlock, pStream, mdct_line, mdct_scaled,
                     mdct_line_pred, mdct_scaled_pred, pow34_scaleFact);

    if (pBlock->ns_mode == 0)
      break;

    aaciencCalcDist(pBlock, pStream, &Dist, mdct_line_int,
                    p_mdct_line_pred_int, mdct_scaleFactor);

    if (first) {
      itest = 1;
      first = 0;
    } else {
      itest = 0;
      if (above > 0) {
        if (Dist.above == 0) itest = 1;
        else if (Dist.above_dist < above_dist) itest = 1;
      } else if ((Dist.sum_dist < sum_dist) && (Dist.above == 0)) itest = 1;
    }

    if (itest) {
      iter = 0;
      sum_dist = Dist.sum_dist;
      above_dist = Dist.above_dist;
      above = Dist.above;
      ippsCopy_16s(pStream->scale_factors, scale_factors,
        pStream->num_window_groups * pStream->max_sfb);
      ippsCopy_16s(pStream->x_quant, x_quant, pStream->max_line);
      ippsCopy_16s(pStream->sfb_cb, sfb_cb, MAX_SECTION_NUMBER);

      if (mdct_line_pred) {
        if (pStream->audioObjectType == AOT_AAC_LTP) {
          ltp_data_present = pStream->ltp_data_present;
          if (pStream->ltp_data_present) {
            ippsCopy_32s(pStream->ltp_long_used, ltp_long_used, MAX_SFB);
          }
        }
      }
    } else iter++;

    if (Dist.max_dist <= 0) break;
    if (Dist.above == 0) break;

    if ((iter > 5) && (above == 0)) {
      break;
    }

    itest = aaciencAdjustSF(pBlock, pStream, &Dist, mdct_scaled,
                            p_mdct_line_pred_int, mdct_scaled_pred,
                            &pow34_scaleFact);

    if (!itest) {
      break;
    }
  }

  if (pBlock->ns_mode) {
    ippsCopy_16s(scale_factors, pStream->scale_factors,
      pStream->num_window_groups * pStream->max_sfb);
    ippsCopy_16s(x_quant, pStream->x_quant, pStream->max_line);
    ippsCopy_16s(sfb_cb, pStream->sfb_cb, MAX_SECTION_NUMBER);

    if (mdct_line_pred) {
      if (pStream->audioObjectType == AOT_AAC_LTP) {
        pStream->ltp_data_present = ltp_data_present;
        if (pStream->ltp_data_present) {
          ippsCopy_32s(ltp_long_used, pStream->ltp_long_used, MAX_SFB);
        }
      }
    }
  }
}

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

static void aaciencMain_loop(sQuantizationBlock* pBlock,
                             sEnc_individual_channel_stream* pStream,
                             Ipp16s* mdct_line,
                             Ipp16s* mdct_scaled,
                             Ipp16s* mdct_line_pred,
                             Ipp16s* mdct_scaled_pred,
                             Ipp32s pow34_scaleFact)
{
  Ipp16s tmp_x_quant[N_LONG/2];
  Ipp16s mdct_sign[N_LONG/2];
  Ipp16s mdct_sign_pred[N_LONG/2];
  Ipp16s x_quant_unsigned[N_LONG/2];
  Ipp16s quant_unsigned_pred[N_LONG/2];

⌨️ 快捷键说明

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