static void search_for_quantizers_faac(AVCodecContext *avctx, AACEncContext *s,

                                       SingleChannelElement *sce,

                                       const float lambda)

{

    int start = 0, i, w, w2, g;

    float uplim[128], maxq[128];

    int minq, maxsf;

    float distfact = ((sce->ics.num_windows > 1) ? 85.80 : 147.84) / lambda;

    int last = 0, lastband = 0, curband = 0;

    float avg_energy = 0.0;

    if (sce->ics.num_windows == 1) {

        start = 0;

        for (i = 0; i < 1024; i++) {

            if (i - start >= sce->ics.swb_sizes[curband]) {

                start += sce->ics.swb_sizes[curband];

                curband++;

            }

            if (sce->coeffs[i]) {

                avg_energy += sce->coeffs[i] * sce->coeffs[i];

                last = i;

                lastband = curband;

            }

        }

    } else {

        for (w = 0; w < 8; w++) {

            const float *coeffs = sce->coeffs + w*128;

            curband = start = 0;

            for (i = 0; i < 128; i++) {

                if (i - start >= sce->ics.swb_sizes[curband]) {

                    start += sce->ics.swb_sizes[curband];

                    curband++;

                }

                if (coeffs[i]) {

                    avg_energy += coeffs[i] * coeffs[i];

                    last = FFMAX(last, i);

                    lastband = FFMAX(lastband, curband);

                }

            }

        }

    }

    last++;

    avg_energy /= last;

    if (avg_energy == 0.0f) {

        for (i = 0; i < FF_ARRAY_ELEMS(sce->sf_idx); i++)

            sce->sf_idx[i] = SCALE_ONE_POS;

        return;

    }

    for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {

        start = w*128;

        for (g = 0; g < sce->ics.num_swb; g++) {

            float *coefs   = sce->coeffs + start;

            const int size = sce->ics.swb_sizes[g];

            int start2 = start, end2 = start + size, peakpos = start;

            float maxval = -1, thr = 0.0f, t;

            maxq[w*16+g] = 0.0f;

            if (g > lastband) {

                maxq[w*16+g] = 0.0f;

                start += size;

                for (w2 = 0; w2 < sce->ics.group_len[w]; w2++)

                    memset(coefs + w2*128, 0, sizeof(coefs[0])*size);

                continue;

            }

            for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {

                for (i = 0; i < size; i++) {

                    float t = coefs[w2*128+i]*coefs[w2*128+i];

                    maxq[w*16+g] = FFMAX(maxq[w*16+g], fabsf(coefs[w2*128 + i]));

                    thr += t;

                    if (sce->ics.num_windows == 1 && maxval < t) {

                        maxval  = t;

                        peakpos = start+i;

                    }

                }

            }

            if (sce->ics.num_windows == 1) {

                start2 = FFMAX(peakpos - 2, start2);

                end2   = FFMIN(peakpos + 3, end2);

            } else {

                start2 -= start;

                end2   -= start;

            }

            start += size;

            thr = pow(thr / (avg_energy * (end2 - start2)), 0.3 + 0.1*(lastband - g) / lastband);

            t   = 1.0 - (1.0 * start2 / last);

            uplim[w*16+g] = distfact / (1.4 * thr + t*t*t + 0.075);

        }

    }

    memset(sce->sf_idx, 0, sizeof(sce->sf_idx));

    abs_pow34_v(s->scoefs, sce->coeffs, 1024);

    for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {

        start = w*128;

        for (g = 0;  g < sce->ics.num_swb; g++) {

            const float *coefs  = sce->coeffs + start;

            const float *scaled = s->scoefs   + start;

            const int size      = sce->ics.swb_sizes[g];

            int scf, prev_scf, step;

            int min_scf = -1, max_scf = 256;

            float curdiff;

            if (maxq[w*16+g] < 21.544) {

                sce->zeroes[w*16+g] = 1;

                start += size;

                continue;

            }

            sce->zeroes[w*16+g] = 0;

            scf  = prev_scf = av_clip(SCALE_ONE_POS - SCALE_DIV_512 - log2f(1/maxq[w*16+g])*16/3, 60, 218);

            for (;;) {

                float dist = 0.0f;

                int quant_max;



                for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {

                    int b;

                    dist += quantize_band_cost(s, coefs + w2*128,

                                               scaled + w2*128,

                                               sce->ics.swb_sizes[g],

                                               scf,

                                               ESC_BT,

                                               lambda,

                                               INFINITY,

                                               &b,

                                               0);

                    dist -= b;

                }

                dist *= 1.0f / 512.0f / lambda;

                quant_max = quant(maxq[w*16+g], ff_aac_pow2sf_tab[POW_SF2_ZERO - scf + SCALE_ONE_POS - SCALE_DIV_512], ROUND_STANDARD);

                if (quant_max >= 8191) { // too much, return to the previous quantizer

                    sce->sf_idx[w*16+g] = prev_scf;

                    break;

                }

                prev_scf = scf;

                curdiff = fabsf(dist - uplim[w*16+g]);

                if (curdiff <= 1.0f)

                    step = 0;

                else

                    step = log2f(curdiff);

                if (dist > uplim[w*16+g])

                    step = -step;

                scf += step;

                scf = av_clip_uint8(scf);

                step = scf - prev_scf;

                if (FFABS(step) <= 1 || (step > 0 && scf >= max_scf) || (step < 0 && scf <= min_scf)) {

                    sce->sf_idx[w*16+g] = av_clip(scf, min_scf, max_scf);

                    break;

                }

                if (step > 0)

                    min_scf = prev_scf;

                else

                    max_scf = prev_scf;

            }

            start += size;

        }

    }

    minq = sce->sf_idx[0] ? sce->sf_idx[0] : INT_MAX;

    for (i = 1; i < 128; i++) {

        if (!sce->sf_idx[i])

            sce->sf_idx[i] = sce->sf_idx[i-1];

        else

            minq = FFMIN(minq, sce->sf_idx[i]);

    }

    if (minq == INT_MAX)

        minq = 0;

    minq = FFMIN(minq, SCALE_MAX_POS);

    maxsf = FFMIN(minq + SCALE_MAX_DIFF, SCALE_MAX_POS);

    for (i = 126; i >= 0; i--) {

        if (!sce->sf_idx[i])

            sce->sf_idx[i] = sce->sf_idx[i+1];

        sce->sf_idx[i] = av_clip(sce->sf_idx[i], minq, maxsf);

    }

}
