ref: 11abc06aeeabb8b3f6d1669d9641b231cc5dc4e3
dir: /libfaac/quantize.c/
/**************************************************************************** Quantizer core functions quality setting, error distribution, etc. Copyright (C) 2017 Krzysztof Nikiel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ****************************************************************************/ #include <math.h> #include "util.h" // band sound masking static void bmask(CoderInfo *coderInfo, double *xr, double *bandqual, double quality) { int sfb, start, end, cnt; int last = coderInfo->lastx; int lastsb = 0; int *cb_offset = coderInfo->sfb_offset; int num_cb = coderInfo->nr_of_sfb; double avgenrg = coderInfo->avgenrg; double powm = 0.25; enum {MIDF=34}; for (sfb = 0; sfb < num_cb; sfb++) { if (last > cb_offset[sfb]) lastsb = sfb; } for (sfb = 0; sfb < num_cb; sfb++) { double avge, maxe; double target; start = cb_offset[sfb]; end = cb_offset[sfb + 1]; if (sfb > lastsb) { bandqual[sfb] = 0; continue; } avge = 0.0; maxe = 0.0; for (cnt = start; cnt < end; cnt++) { double e = xr[cnt]*xr[cnt]; avge += e; if (maxe < e) maxe = e; } avge /= (end - start); #define NOISETONE 0.2 if (coderInfo->block_type == ONLY_SHORT_WINDOW) { target = NOISETONE * pow(avge/avgenrg, powm); target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powm); target *= 0.9 + (40.0 / (fabs(start + end - MIDF) + 32)); } else { target = NOISETONE * pow(avge/avgenrg, powm); target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powm); target *= 0.9 + (40.0 / (0.125 * fabs(start + end - (8*MIDF)) + 32)); target *= 0.45; } bandqual[sfb] = 3.5 * target * quality; } } // use band quality levels to quantize a block static void qlevel(CoderInfo *coderInfo, const double *xr, int *xi, const double *bandqual) { int sb, cnt; int start, end; // 1.5dB step static const double sfstep = 20.0 / 1.5 / log(10); static const double sfstep_1 = 1.0 / sfstep; for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) { double sfacfix; int sfac; double maxx; double rmsx; start = coderInfo->sfb_offset[sb]; end = coderInfo->sfb_offset[sb+1]; maxx = 0.0; rmsx = 0.0; for (cnt = start; cnt < end; cnt++) { double e = xr[cnt] * xr[cnt]; if (maxx < e) maxx = e; rmsx += e; } rmsx /= (end - start); rmsx = sqrt(rmsx); maxx = sqrt(maxx); if (maxx < 10.0) { for (cnt = start; cnt < end; cnt++) xi[cnt] = 0; coderInfo->scale_factor[sb] = 10; continue; } sfac = (int)(log(bandqual[sb] / rmsx) * sfstep - 0.5); sfacfix = exp(sfac * sfstep_1); coderInfo->scale_factor[sb] = sfac; for (cnt = start; cnt < end; cnt++) { int x0, x1; double err0, err1; double tmp = fabs(xr[cnt]) * sfacfix; tmp = sqrt(tmp * sqrt(tmp)); x0 = tmp; x1 = x0 + 1; err0 = fabs(tmp * tmp - x0 * x0); err1 = fabs(tmp * tmp - x1 * x1); if (err0 < err1) xi[cnt] = x0; else xi[cnt] = x1; } } } int BlocQuant(CoderInfo *coderInfo, double *xr, int *xi, double quality) { double bandlvl[MAX_SCFAC_BANDS]; int cnt; int nonzero = 0; for (cnt = 0; cnt < FRAME_LEN; cnt++) nonzero += (fabs(xr[cnt]) > 1E-20); SetMemory(xi, 0, FRAME_LEN*sizeof(xi[0])); if (nonzero) { bmask(coderInfo, xr, bandlvl, quality); qlevel(coderInfo, xr, xi, bandlvl); return 1; } return 0; }