1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/***********************************************************************
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*       File: dtx.c                                                    *
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                                                      *
205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen*       Description:DTX functions                                  *
21e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                                                      *
22e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard************************************************************************/
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <stdio.h>
25e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <stdlib.h>
26e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "oper_32b.h"
29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "math_op.h"
30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "cnst.h"
31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "acelp.h"                         /* prototype of functions    */
32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "bits.h"
33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "dtx.h"
34e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "log2.h"
35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "mem_align.h"
36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void aver_isf_history(
385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf_old[],
395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 indices[],
405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 isf_aver[]
415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        );
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void find_frame_indices(
445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf_old_tx[],
455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 indices[],
465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st
475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        );
48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 dithering_control(
505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st
515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        );
52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* excitation energy adjustment depending on speech coder mode used, Q7 */
54e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 en_adjust[9] =
55e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    230,                                   /* mode0 = 7k  :  -5.4dB  */
575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    179,                                   /* mode1 = 9k  :  -4.2dB  */
585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    141,                                   /* mode2 = 12k :  -3.3dB  */
595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    128,                                   /* mode3 = 14k :  -3.0dB  */
605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    122,                                   /* mode4 = 16k :  -2.85dB */
615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    115,                                   /* mode5 = 18k :  -2.7dB  */
625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    115,                                   /* mode6 = 20k :  -2.7dB  */
635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    115,                                   /* mode7 = 23k :  -2.7dB  */
645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    115                                    /* mode8 = 24k :  -2.7dB  */
65e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard};
66e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
67e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
68e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
69e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : dtx_enc_init
70e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
71e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
72e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP)
73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    dtx_encState *s;
755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (st == (dtx_encState **) NULL)
775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "dtx_enc_init: invalid parameter\n");
795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *st = NULL;
825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* allocate memory */
845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if ((s = (dtx_encState *)mem_malloc(pMemOP, sizeof(dtx_encState), 32, VO_INDEX_ENC_AMRWB)) == NULL)
855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");
875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    dtx_enc_reset(s, isf_init);
905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *st = s;
915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
94e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : dtx_enc_reset
97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
99e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[])
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
1025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (st == (dtx_encState *) NULL)
1045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "dtx_enc_reset: invalid parameter\n");
1065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
1075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->hist_ptr = 0;
1095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->log_en_index = 0;
1105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Init isf_hist[] */
1125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE; i++)
1135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Copy(isf_init, &st->isf_hist[i * M], M);
1155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->cng_seed = RANDOM_INITSEED;
1175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Reset energy history */
1195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Set_zero(st->log_en_hist, DTX_HIST_SIZE);
1205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->dtxHangoverCount = DTX_HANG_CONST;
1225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->decAnaElapsedCount = 32767;
1235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 28; i++)
1255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->D[i] = 0;
1275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE - 1; i++)
1305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sumD[i] = 0;
1325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 1;
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : dtx_enc_exit
140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP)
143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (st == NULL || *st == NULL)
1455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return;
1465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* deallocate memory */
1475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mem_free(pMemOP, *st, VO_INDEX_ENC_AMRWB);
1485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *st = NULL;
1495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
152e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
153e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
154e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
155e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : dtx_enc
156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
158e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 dtx_enc(
1595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st,                    /* i/o : State struct                                         */
1605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf[M],                        /* o   : CN ISF vector                                        */
1615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * exc2,                        /* o   : CN excitation                                        */
1625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 ** prms
1635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen          )
164e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, j;
1665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 indice[7];
1675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 log_en, gain, level, exp, exp0, tmp;
1685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 log_en_int_e, log_en_int_m;
1695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_isf[M], ener32, level32;
1705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 isf_order[3];
1715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 CN_dith;
1725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* VOX mode computation of SID parameters */
1745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = 0;
1755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < M; i++)
1765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_isf[i] = 0;
1785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* average energy and isf */
1805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE; i++)
1815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer. log_en is in Q10 */
1835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        log_en = add(log_en, st->log_en_hist[i]);
1845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    find_frame_indices(st->isf_hist, isf_order, st);
1875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    aver_isf_history(st->isf_hist, isf_order, L_isf);
1885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (j = 0; j < M; j++)
1905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        isf[j] = (Word16)(L_isf[j] >> 3);  /* divide by 8 */
1925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E).  */
1955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */
1965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* increase dynamics to 7 bits (Q8) */
1985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = (log_en >> 2);
1995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Add 2 in Q8 = 512 to get log2(E) between 0:24 */
2015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = add(log_en, 512);
2025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */
2045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = mult(log_en, 21504);
2055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Quantize Energy */
2075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->log_en_index = shr(log_en, 6);
2085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(st->log_en_index > 63)
2105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->log_en_index = 63;
2125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (st->log_en_index < 0)
2145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->log_en_index = 0;
2165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Quantize ISFs */
2185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Qisf_ns(isf, isf, indice);
2195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(indice[0], 6, prms);
2225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(indice[1], 6, prms);
2235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(indice[2], 6, prms);
2245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(indice[3], 5, prms);
2255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(indice[4], 5, prms);
2265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial((st->log_en_index), 6, prms);
2285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    CN_dith = dithering_control(st);
2305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Parm_serial(CN_dith, 1, prms);
2315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) );    */
2335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* log2(E) in Q9 (log2(E) lies in between -2:22) */
2345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = shl(st->log_en_index, 15 - 6);
2355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Divide by 2.625; log_en will be between 0:24  */
2375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = mult(log_en, 12483);
2385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* the result corresponds to log2(gain) in Q10 */
2395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find integer part  */
2415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en_int_e = (log_en >> 10);
2425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find fractional part */
2445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en_int_m = (Word16) (log_en & 0x3ff);
2455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en_int_m = shl(log_en_int_m, 5);
2465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Subtract 2 from log_en in Q9, i.e divide the gain by 2 (energy by 4) */
2485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Add 16 in order to have the result of pow2 in Q16 */
2495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en_int_e = add(log_en_int_e, 16 - 1);
2505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
2525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp0 = norm_l(level32);
2535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level32 = (level32 << exp0);        /* level in Q31 */
2545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp0 = (15 - exp0);
2555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level = extract_h(level32);            /* level in Q15 */
2565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* generate white noise vector */
2585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < L_FRAME; i++)
2595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        exc2[i] = (Random(&(st->cng_seed)) >> 4);
2615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
2645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* energy of generated excitation */
2665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
267e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Isqrt_n(&ener32, &exp);
269e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    gain = extract_h(ener32);
271e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    gain = mult(level, gain);              /* gain in Q15 */
273e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp = add(exp0, exp);
275e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
2775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp += 4;
278e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < L_FRAME; i++)
2805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        tmp = mult(exc2[i], gain);         /* Q0 * Q15 */
2825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        exc2[i] = shl(tmp, exp);
2835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
284e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
2855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
290e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : dtx_buffer Purpose     : handles the DTX buffer
291e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
292e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
293e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 dtx_buffer(
2945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st,                    /* i/o : State struct                    */
2955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf_new[],                     /* i   : isf vector                      */
2965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 enr,                           /* i   : residual energy (in L_FRAME)    */
2975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 codec_mode
2985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
299e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
3005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 log_en;
3015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 log_en_e;
3035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 log_en_m;
3045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->hist_ptr = add(st->hist_ptr, 1);
3055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(st->hist_ptr == DTX_HIST_SIZE)
3065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->hist_ptr = 0;
3085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* copy lsp vector into buffer */
3105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M);
3115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f);  */
3135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Log2(enr, &log_en_e, &log_en_m);
3145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
3165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = shl(log_en_e, 7);             /* Q7 */
3175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = add(log_en, shr(log_en_m, 15 - 7));
3185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The
3205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * constant 0.0059322 takes into account windowings and analysis length from autocorrelation
3215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * computations; 7.39722 in Q7 = 947  */
3225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
3235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */
3245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0  (1024 in Q7) */
3265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
3275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    log_en = sub(log_en, add(1024, en_adjust[codec_mode]));
3295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Insert into the buffer */
3315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->log_en_hist[st->hist_ptr] = log_en;
3325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
333e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
334e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************************************************
336e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
337e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Function    : tx_dtx_handler Purpose     : adds extra speech hangover
338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                            to analyze speech on
339e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                            the decoding side.
340e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard**************************************************************************/
341e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid tx_dtx_handler(dtx_encState * st,     /* i/o : State struct           */
3425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 vad_flag,                      /* i   : vad decision           */
3435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * usedMode                     /* i/o : mode changed or not    */
3445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
345e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
346e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
3475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* this state machine is in synch with the GSMEFR txDtx machine      */
3485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);
3495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (vad_flag != 0)
3515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->dtxHangoverCount = DTX_HANG_CONST;
3535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
3545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {                                      /* non-speech */
3555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (st->dtxHangoverCount == 0)
3565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {                                  /* out of decoder analysis hangover  */
3575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->decAnaElapsedCount = 0;
3585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            *usedMode = MRDTX;
3595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        } else
3605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {                                  /* in possible analysis hangover */
3615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);
3625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */
3645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),
3655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                        DTX_ELAPSED_FRAMES_THRESH) < 0)
3665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
3675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                *usedMode = MRDTX;
3685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                /* if short time since decoder update, do not add extra HO */
3695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
3705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* else override VAD and stay in speech mode *usedMode and add extra hangover */
3715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
3725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
376e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
378e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
379e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void aver_isf_history(
3805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf_old[],
3815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 indices[],
3825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 isf_aver[]
3835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
3855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, j, k;
3865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 isf_tmp[2 * M];
3875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_tmp;
3885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Memorize in isf_tmp[][] the ISF vectors to be replaced by */
3905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* the median ISF vector prior to the averaging               */
3915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (k = 0; k < 2; k++)
3925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if ((indices[k] + 1) != 0)
3945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
3955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            for (i = 0; i < M; i++)
3965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
3975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                isf_tmp[k * M + i] = isf_old[indices[k] * M + i];
3985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i];
3995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
4005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Perform the ISF averaging */
4045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (j = 0; j < M; j++)
4055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = 0;
4075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        for (i = 0; i < DTX_HIST_SIZE; i++)
4095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j]));
4115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        isf_aver[j] = L_tmp;
4135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */
4165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (k = 0; k < 2; k++)
4175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if ((indices[k] + 1) != 0)
4195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            for (i = 0; i < M; i++)
4215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
4225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                isf_old[indices[k] * M + i] = isf_tmp[k * M + i];
4235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
4245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
428e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
429e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
430e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void find_frame_indices(
4315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 isf_old_tx[],
4325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 indices[],
4335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st
4345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
435e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
4365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_tmp, summin, summax, summax2nd;
4375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 i, j, tmp;
4385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 ptr;
4395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Remove the effect of the oldest frame from the column */
4415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* sum sumD[0..DTX_HIST_SIZE-1]. sumD[DTX_HIST_SIZE] is    */
4425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* not updated since it will be removed later.           */
4435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    tmp = DTX_HIST_SIZE_MIN_ONE;
4455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    j = -1;
4465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)
4475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        j = add(j, tmp);
4495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sumD[i] = L_sub(st->sumD[i], st->D[j]);
4505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        tmp = sub(tmp, 1);
4515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Shift the column sum sumD. The element sumD[DTX_HIST_SIZE-1]    */
4545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* corresponding to the oldest frame is removed. The sum of     */
4555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* the distances between the latest isf and other isfs, */
4565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* i.e. the element sumD[0], will be computed during this call. */
4575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Hence this element is initialized to zero.                   */
4585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = DTX_HIST_SIZE_MIN_ONE; i > 0; i--)
4605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sumD[i] = st->sumD[i - 1];
4625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->sumD[0] = 0;
4645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Remove the oldest frame from the distance matrix.           */
4665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Note that the distance matrix is replaced by a one-         */
4675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* dimensional array to save static memory.                    */
4685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    tmp = 0;
4705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 27; i >= 12; i = (Word16) (i - tmp))
4715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        tmp = add(tmp, 1);
4735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        for (j = tmp; j > 0; j--)
4745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->D[i - j + 1] = st->D[i - j - tmp];
4765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Compute the first column of the distance matrix D            */
4805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */
4815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ptr = st->hist_ptr;
4835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 1; i < DTX_HIST_SIZE; i++)
4845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /* Compute the distance between the latest isf and the other isfs. */
4865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        ptr = sub(ptr, 1);
4875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (ptr < 0)
4885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            ptr = DTX_HIST_SIZE_MIN_ONE;
4905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_tmp = 0;
4925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        for (j = 0; j < M; j++)
4935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);
4955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            L_tmp = L_mac(L_tmp, tmp, tmp);
4965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->D[i - 1] = L_tmp;
4985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /* Update also the column sums. */
5005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]);
5015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]);
5025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find the minimum and maximum distances */
5055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summax = st->sumD[0];
5065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summin = st->sumD[0];
5075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    indices[0] = 0;
5085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    indices[2] = 0;
5095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 1; i < DTX_HIST_SIZE; i++)
5105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (L_sub(st->sumD[i], summax) > 0)
5125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            indices[0] = i;
5145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            summax = st->sumD[i];
5155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
5165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (L_sub(st->sumD[i], summin) < 0)
5175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            indices[2] = i;
5195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            summin = st->sumD[i];
5205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
5215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Find the second largest distance */
5245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summax2nd = -2147483647L;
5255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    indices[1] = -1;
5265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE; i++)
5275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0))
5295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            indices[1] = i;
5315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            summax2nd = st->sumD[i];
5325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
5335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 3; i++)
5365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        indices[i] = sub(st->hist_ptr, indices[i]);
5385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (indices[i] < 0)
5395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            indices[i] = add(indices[i], DTX_HIST_SIZE);
5415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
5425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* If maximum distance/MED_THRESH is smaller than minimum distance */
5455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* then the median ISF vector replacement is not performed         */
5465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    tmp = norm_l(summax);
5475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summax = (summax << tmp);
5485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summin = (summin << tmp);
5495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = L_mult(voround(summax), INV_MED_THRESH);
5505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(L_tmp <= summin)
5515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        indices[0] = -1;
5535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* If second largest distance/MED_THRESH is smaller than     */
5555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* minimum distance then the median ISF vector replacement is    */
5565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* not performed                                                 */
5575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    summax2nd = L_shl(summax2nd, tmp);
5585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_tmp = L_mult(voround(summax2nd), INV_MED_THRESH);
5595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(L_tmp <= summin)
5605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        indices[1] = -1;
5625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
564e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
565e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
566e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 dithering_control(
5675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        dtx_encState * st
5685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
569e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
5705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 tmp, mean, CN_dith, gain_diff;
5715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, ISF_diff;
5725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* determine how stationary the spectrum of background noise is */
5745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ISF_diff = 0;
5755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 8; i++)
5765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        ISF_diff = L_add(ISF_diff, st->sumD[i]);
5785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if ((ISF_diff >> 26) > 0)
5805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        CN_dith = 1;
5825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
5835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        CN_dith = 0;
5855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* determine how stationary the energy of background noise is */
5885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mean = 0;
5895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE; i++)
5905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        mean = add(mean, st->log_en_hist[i]);
5925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mean = (mean >> 3);
5945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    gain_diff = 0;
5955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < DTX_HIST_SIZE; i++)
5965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        tmp = abs_s(sub(st->log_en_hist[i], mean));
5985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        gain_diff = add(gain_diff, tmp);
5995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (gain_diff > GAIN_THR)
6015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        CN_dith = 1;
6035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return CN_dith;
605e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
606