ref: ae01d6dfb986b6bbcc725ebb8f898f818773addc
dir: /libfaac/aacquant.c/
/*
* FAAC - Freeware Advanced Audio Coder
* Copyright (C) 2001 Menno Bakker
* Copyright (C) 2002, 2003 Krzysztof Nikiel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <math.h>
#include <stdlib.h>
#include <faac.h>
#include "aacquant.h"
#include "coder.h"
#include "huffman.h"
#include "util.h"
#include "quantize.c"
void AACQuantizeInit(CoderInfo *coderInfo, unsigned int numChannels,
AACQuantCfg *aacquantCfg)
{
unsigned int channel, i;
aacquantCfg->pow43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double));
aacquantCfg->pow43[0] = 0.0;
for(i=1;i<PRECALC_SIZE;i++)
aacquantCfg->pow43[i] = pow((double)i, 4.0/3.0);
for (channel = 0; channel < numChannels; channel++) {
coderInfo[channel].requantFreq = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double));
}
}
void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels,
AACQuantCfg *aacquantCfg)
{
unsigned int channel;
if (aacquantCfg->pow43)
{
FreeMemory(aacquantCfg->pow43);
aacquantCfg->pow43 = NULL;
}
for (channel = 0; channel < numChannels; channel++) {
if (coderInfo[channel].requantFreq) FreeMemory(coderInfo[channel].requantFreq);
}
}
static void UpdateRequant(CoderInfo *coderInfo, int *xi,
double *pow43)
{
double *requant_xr = coderInfo->requantFreq;
int sb;
int i;
for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
{
double invQuantFac =
pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
int start = coderInfo->sfb_offset[sb];
int end = coderInfo->sfb_offset[sb + 1];
for (i = start; i < end; i++)
requant_xr[i] = pow43[xi[i]] * invQuantFac;
}
}
int AACQuantize(CoderInfo *coderInfo,
int *cb_width,
int num_cb,
double *xr,
AACQuantCfg *aacquantCfg)
{
int sb, i;
int bits = 0, sign;
int xi[FRAME_LEN];
/* Use local copy's */
int *scale_factor = coderInfo->scale_factor;
/* Set all scalefactors to 0 */
coderInfo->global_gain = 0;
for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
scale_factor[sb] = 0;
if (BlocQuant(coderInfo, xr, xi, (double)aacquantCfg->quality/DEFQUAL, aacquantCfg->pow43))
{
UpdateRequant(coderInfo, xi, aacquantCfg->pow43);
for ( i = 0; i < FRAME_LEN; i++ ) {
sign = (xr[i] < 0) ? -1 : 1;
xi[i] *= sign;
coderInfo->requantFreq[i] *= sign;
}
}
BitSearch(coderInfo, xi);
/* offset the difference of common_scalefac and scalefactors by SF_OFFSET */
for (i = 0; i < coderInfo->nr_of_sfb; i++) {
if ((coderInfo->book_vector[i]!=INTENSITY_HCB)&&(coderInfo->book_vector[i]!=INTENSITY_HCB2)) {
scale_factor[i] = coderInfo->global_gain - scale_factor[i] + SF_OFFSET;
}
}
coderInfo->global_gain = scale_factor[0];
// clamp to valid diff range
{
int previous_scale_factor = coderInfo->global_gain;
int previous_is_factor = 0;
for (i = 0; i < coderInfo->nr_of_sfb; i++) {
if ((coderInfo->book_vector[i]==INTENSITY_HCB) ||
(coderInfo->book_vector[i]==INTENSITY_HCB2)) {
const int diff = scale_factor[i] - previous_is_factor;
if (diff < -60) scale_factor[i] = previous_is_factor - 60;
else if (diff > 60) scale_factor[i] = previous_is_factor + 60;
previous_is_factor = scale_factor[i];
// printf("sf %d: %d diff=%d **\n", i, coderInfo->scale_factor[i], diff);
} else if (coderInfo->book_vector[i]) {
const int diff = scale_factor[i] - previous_scale_factor;
if (diff < -60) scale_factor[i] = previous_scale_factor - 60;
else if (diff > 60) scale_factor[i] = previous_scale_factor + 60;
previous_scale_factor = scale_factor[i];
// printf("sf %d: %d diff=%d\n", i, coderInfo->scale_factor[i], diff);
}
}
}
/* place the codewords and their respective lengths in arrays data[] and len[] respectively */
/* there are 'counter' elements in each array, and these are variable length arrays depending on the input */
#ifdef DRM
coderInfo->iLenReordSpData = 0; /* init length of reordered spectral data */
coderInfo->iLenLongestCW = 0; /* init length of longest codeword */
coderInfo->cur_cw = 0; /* init codeword counter */
#endif
coderInfo->spectral_count = 0;
sb = 0;
for(i = 0; i < coderInfo->nr_of_sfb; i++) {
OutputBits(
coderInfo,
#ifdef DRM
&coderInfo->book_vector[i], /* needed for VCB11 */
#else
coderInfo->book_vector[i],
#endif
xi,
coderInfo->sfb_offset[i],
coderInfo->sfb_offset[i+1]-coderInfo->sfb_offset[i]);
if (coderInfo->book_vector[i])
sb = i;
}
// FIXME: Check those max_sfb/nr_of_sfb. Isn't it the same?
coderInfo->max_sfb = coderInfo->nr_of_sfb = sb + 1;
return bits;
}
int SortForGrouping(CoderInfo* coderInfo,
int *sfb_width_table,
double *xr)
{
int i,j,ii;
int index = 0;
double xr_tmp[FRAME_LEN];
int group_offset=0;
int k=0;
int windowOffset = 0;
/* set up local variables for used quantInfo elements */
int* sfb_offset = coderInfo->sfb_offset;
int* nr_of_sfb = &(coderInfo->nr_of_sfb);
int* window_group_length;
int num_window_groups;
*nr_of_sfb = coderInfo->max_sfb; /* Init to max_sfb */
window_group_length = coderInfo->window_group_length;
num_window_groups = coderInfo->num_window_groups;
/* calc org sfb_offset just for shortblock */
sfb_offset[k]=0;
for (k=1 ; k <*nr_of_sfb+1; k++) {
sfb_offset[k] = sfb_offset[k-1] + sfb_width_table[k-1];
}
/* sort the input spectral coefficients */
index = 0;
group_offset=0;
for (i=0; i< num_window_groups; i++) {
for (k=0; k<*nr_of_sfb; k++) {
for (j=0; j < window_group_length[i]; j++) {
for (ii=0;ii< sfb_width_table[k];ii++)
xr_tmp[index++] = xr[ii+ sfb_offset[k] + BLOCK_LEN_SHORT*j +group_offset];
}
}
group_offset += BLOCK_LEN_SHORT*window_group_length[i];
}
for (k=0; k<FRAME_LEN; k++){
xr[k] = xr_tmp[k];
}
/* now calc the new sfb_offset table for the whole p_spectrum vector*/
index = 0;
sfb_offset[index++] = 0;
windowOffset = 0;
for (i=0; i < num_window_groups; i++) {
for (k=0 ; k <*nr_of_sfb; k++) {
sfb_offset[index] = sfb_offset[index-1] + sfb_width_table[k]*window_group_length[i] ;
index++;
}
windowOffset += window_group_length[i];
}
*nr_of_sfb = *nr_of_sfb * num_window_groups; /* Number interleaved bands. */
return 0;
}
void CalcAvgEnrg(CoderInfo *coderInfo,
const double *xr)
{
int end, l;
int last = 0;
double totenrg = 0.0;
end = coderInfo->sfb_offset[coderInfo->nr_of_sfb];
for (l = 0; l < end; l++)
{
if (xr[l])
{
last = l;
totenrg += xr[l] * xr[l];
}
}
last++;
coderInfo->lastx = last;
coderInfo->avgenrg = totenrg / last;
}