📄 aac_enc_quantization_int.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) 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 + -