pure sdk for main
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_H
|
||||
#define DEC_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
void D_MAIN_reset(void *st, Word16 reset_all);
|
||||
Word32 D_MAIN_init(void **spd_state);
|
||||
void D_MAIN_close(void **spd_state);
|
||||
Word32 D_MAIN_decode(Word16 mode, Word16 prms[], Word16 synth16k[],
|
||||
void *spd_state, UWord8 frame_type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,692 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "dec_util.h"
|
||||
#include "osal/string.h"
|
||||
#define L_SUBFR 64 /* Subframe size */
|
||||
#define PRED_ORDER 4
|
||||
#define MEAN_ENER 30 /* average innovation energy */
|
||||
extern const Word16 D_ROM_ph_imp_low[];
|
||||
extern const Word16 D_ROM_ph_imp_mid[];
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_add_pulse
|
||||
*
|
||||
* Parameters:
|
||||
* pos I: position of pulse
|
||||
* nb_pulse I: number of pulses
|
||||
* track I: track
|
||||
* code O: fixed codebook
|
||||
*
|
||||
* Function:
|
||||
* Add pulses to fixed codebook
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_add_pulse(Word32 pos[], Word32 nb_pulse,
|
||||
Word32 track, Word16 code[])
|
||||
{
|
||||
Word32 i, k;
|
||||
|
||||
for(k = 0; k < nb_pulse; k++)
|
||||
{
|
||||
/* i = ((pos[k] & (16-1))*NB_TRACK) + track; */
|
||||
i = ((pos[k] & (16 - 1)) << 2) + track;
|
||||
|
||||
if((pos[k] & 16) == 0)
|
||||
{
|
||||
code[i] = (Word16)(code[i] + 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i] = (Word16)(code[i] - 512);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_1p_N1
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
|
||||
*
|
||||
* Function:
|
||||
* Decode 1 pulse with N+1 bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_1p_N1(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 i, pos1, mask;
|
||||
|
||||
mask = ((1 << N) - 1);
|
||||
|
||||
/*
|
||||
* Decode 1 pulse with N+1 bits
|
||||
*/
|
||||
pos1 = ((index & mask) + offset);
|
||||
i = ((index >> N) & 1);
|
||||
|
||||
if(i == 1)
|
||||
{
|
||||
pos1 += 16;
|
||||
}
|
||||
|
||||
pos[0] = pos1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_2p_2N1
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 2 pulses with 2*N+1 bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_2p_2N1(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 i, pos1, pos2;
|
||||
Word32 mask;
|
||||
|
||||
mask = ((1 << N) - 1);
|
||||
|
||||
/*
|
||||
* Decode 2 pulses with 2*N+1 bits
|
||||
*/
|
||||
pos1 = (((index >> N) & mask) + offset);
|
||||
i = (index >> (2 * N)) & 1;
|
||||
pos2 = ((index & mask) + offset);
|
||||
|
||||
if((pos2 - pos1) < 0)
|
||||
{
|
||||
if(i == 1)
|
||||
{
|
||||
pos1 += 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos2 += 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i == 1)
|
||||
{
|
||||
pos1 += 16;
|
||||
pos2 += 16;
|
||||
}
|
||||
}
|
||||
|
||||
pos[0] = pos1;
|
||||
pos[1] = pos2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_3p_3N1
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 3 pulses with 3*N+1 bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_3p_3N1(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 j, mask, idx;
|
||||
|
||||
/*
|
||||
* Decode 3 pulses with 3*N+1 bits
|
||||
*/
|
||||
mask = ((1 << ((2 * N) - 1)) - 1);
|
||||
idx = index & mask;
|
||||
j = offset;
|
||||
|
||||
if(((index >> ((2 * N) - 1)) & 1) == 1)
|
||||
{
|
||||
j += (1 << (N - 1));
|
||||
}
|
||||
|
||||
D_ACELP_decode_2p_2N1(idx, N - 1, j, pos);
|
||||
mask = ((1 << (N + 1)) - 1);
|
||||
idx = (index >> (2 * N)) & mask;
|
||||
D_ACELP_decode_1p_N1(idx, N, offset, pos + 2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_4p_4N1
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 4 pulses with 4*N+1 bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_4p_4N1(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 j, mask, idx;
|
||||
|
||||
/*
|
||||
* Decode 4 pulses with 4*N+1 bits
|
||||
*/
|
||||
mask = ((1 << ((2 * N) - 1)) - 1);
|
||||
idx = index & mask;
|
||||
j = offset;
|
||||
|
||||
if(((index >> ((2 * N) - 1)) & 1) == 1)
|
||||
{
|
||||
j += (1 << (N - 1));
|
||||
}
|
||||
|
||||
D_ACELP_decode_2p_2N1(idx, N - 1, j, pos);
|
||||
mask = ((1 << ((2 * N) + 1)) - 1);
|
||||
idx = (index >> (2 * N)) & mask;
|
||||
D_ACELP_decode_2p_2N1(idx, N, offset, pos + 2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_4p_4N
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 4 pulses with 4*N bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_4p_4N(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 j, n_1;
|
||||
|
||||
/*
|
||||
* Decode 4 pulses with 4*N bits
|
||||
*/
|
||||
n_1 = N - 1;
|
||||
j = offset + (1 << n_1);
|
||||
|
||||
switch((index >> ((4 * N) - 2)) & 3)
|
||||
{
|
||||
case 0:
|
||||
if(((index >> ((4 * n_1) + 1)) & 1) == 0)
|
||||
{
|
||||
D_ACELP_decode_4p_4N1(index, n_1, offset, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_ACELP_decode_4p_4N1(index, n_1, j, pos);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
D_ACELP_decode_1p_N1((index >> ((3 * n_1) + 1)), n_1, offset, pos);
|
||||
D_ACELP_decode_3p_3N1(index, n_1, j, pos + 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
D_ACELP_decode_2p_2N1((index >> ((2 * n_1) + 1)), n_1, offset, pos);
|
||||
D_ACELP_decode_2p_2N1(index, n_1, j, pos + 2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
D_ACELP_decode_3p_3N1((index >> (n_1 + 1)), n_1, offset, pos);
|
||||
D_ACELP_decode_1p_N1(index, n_1, j, pos + 3);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_5p_5N
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 5 pulses with 5*N bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_5p_5N(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 j, n_1;
|
||||
Word32 idx;
|
||||
|
||||
/*
|
||||
* Decode 5 pulses with 5*N bits
|
||||
*/
|
||||
n_1 = N - 1;
|
||||
j = offset + (1 << n_1);
|
||||
idx = (index >> ((2 * N) + 1));
|
||||
|
||||
if(((index >> ((5 * N) - 1)) & 1) == 0)
|
||||
{
|
||||
D_ACELP_decode_3p_3N1(idx, n_1, offset, pos);
|
||||
D_ACELP_decode_2p_2N1(index, N, offset, pos + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_ACELP_decode_3p_3N1(idx, n_1, j, pos);
|
||||
D_ACELP_decode_2p_2N1(index, N, offset, pos + 3);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_6p_6N_2
|
||||
*
|
||||
* Parameters:
|
||||
* index I: pulse index
|
||||
* N I: number of bits for position
|
||||
* offset I: offset
|
||||
* pos O: position of the pulse
|
||||
*
|
||||
* Function:
|
||||
* Decode 6 pulses with 6*N-2 bits
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_ACELP_decode_6p_6N_2(Word32 index, Word32 N,
|
||||
Word32 offset, Word32 pos[])
|
||||
{
|
||||
Word32 j, n_1, offsetA, offsetB;
|
||||
|
||||
n_1 = N - 1;
|
||||
j = offset + (1 << n_1);
|
||||
offsetA = offsetB = j;
|
||||
|
||||
if(((index >> ((6 * N) - 5)) & 1) == 0)
|
||||
{
|
||||
offsetA = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetB = offset;
|
||||
}
|
||||
|
||||
switch((index >> ((6 * N) - 4)) & 3)
|
||||
{
|
||||
case 0:
|
||||
D_ACELP_decode_5p_5N(index >> N, n_1, offsetA, pos);
|
||||
D_ACELP_decode_1p_N1(index, n_1, offsetA, pos + 5);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
D_ACELP_decode_5p_5N(index >> N, n_1, offsetA, pos);
|
||||
D_ACELP_decode_1p_N1(index, n_1, offsetB, pos + 5);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
D_ACELP_decode_4p_4N(index >> ((2 * n_1) + 1), n_1, offsetA, pos);
|
||||
D_ACELP_decode_2p_2N1(index, n_1, offsetB, pos + 4);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
D_ACELP_decode_3p_3N1(index >> ((3 * n_1) + 1), n_1, offset, pos);
|
||||
D_ACELP_decode_3p_3N1(index, n_1, j, pos + 3);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_2t
|
||||
*
|
||||
* Parameters:
|
||||
* index I: 12 bits index
|
||||
* code O: (Q9) algebraic (fixed) codebook excitation
|
||||
*
|
||||
* Function:
|
||||
* 12 bits algebraic codebook decoder.
|
||||
* 2 tracks x 32 positions per track = 64 samples.
|
||||
*
|
||||
* 12 bits --> 2 pulses in a frame of 64 samples.
|
||||
*
|
||||
* All pulses can have two (2) possible amplitudes: +1 or -1.
|
||||
* Each pulse can have 32 possible positions.
|
||||
*
|
||||
* codevector length 64
|
||||
* number of track 2
|
||||
* number of position 32
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_ACELP_decode_2t(Word16 index, Word16 code[])
|
||||
{
|
||||
Word32 i0, i1;
|
||||
|
||||
memset(code, 0, 64 * sizeof(Word16));
|
||||
|
||||
/* decode the positions and signs of pulses and build the codeword */
|
||||
i0 = (index >> 5) & 0x0000003E;
|
||||
i1 = ((index & 0x0000001F) << 1) + 1;
|
||||
|
||||
if(((index >> 6) & 32) == 0)
|
||||
{
|
||||
code[i0] = 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i0] = -512;
|
||||
}
|
||||
|
||||
if((index & 32) == 0)
|
||||
{
|
||||
code[i1] = 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i1] = -512;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_decode_4t
|
||||
*
|
||||
* Parameters:
|
||||
* index I: index
|
||||
* mode I: speech mode
|
||||
* code I: (Q9) algebraic (fixed) codebook excitation
|
||||
*
|
||||
* Function:
|
||||
* 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook.
|
||||
* 4 tracks x 16 positions per track = 64 samples.
|
||||
*
|
||||
* 20 bits 5+5+5+5 --> 4 pulses in a frame of 64 samples.
|
||||
* 36 bits 9+9+9+9 --> 8 pulses in a frame of 64 samples.
|
||||
* 44 bits 13+9+13+9 --> 10 pulses in a frame of 64 samples.
|
||||
* 52 bits 13+13+13+13 --> 12 pulses in a frame of 64 samples.
|
||||
* 64 bits 2+2+2+2+14+14+14+14 --> 16 pulses in a frame of 64 samples.
|
||||
* 72 bits 10+2+10+2+10+14+10+14 --> 18 pulses in a frame of 64 samples.
|
||||
* 88 bits 11+11+11+11+11+11+11+11 --> 24 pulses in a frame of 64 samples.
|
||||
*
|
||||
* All pulses can have two (2) possible amplitudes: +1 or -1.
|
||||
* Each pulse can sixteen (16) possible positions.
|
||||
*
|
||||
* codevector length 64
|
||||
* number of track 4
|
||||
* number of position 16
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_ACELP_decode_4t(Word16 index[], Word16 nbbits, Word16 code[])
|
||||
{
|
||||
Word32 k, L_index, pos[6];
|
||||
|
||||
memset(code, 0, 64 * sizeof(Word16));
|
||||
|
||||
/* decode the positions and signs of pulses and build the codeword */
|
||||
if(nbbits == 20)
|
||||
{
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
L_index = index[k];
|
||||
D_ACELP_decode_1p_N1(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 1, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 36)
|
||||
{
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
L_index = index[k];
|
||||
D_ACELP_decode_2p_2N1(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 2, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 44)
|
||||
{
|
||||
for(k = 0; k < 4 - 2; k++)
|
||||
{
|
||||
L_index = index[k];
|
||||
D_ACELP_decode_3p_3N1(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 3, k, code);
|
||||
}
|
||||
|
||||
for(k = 2; k < 4; k++)
|
||||
{
|
||||
L_index = index[k];
|
||||
D_ACELP_decode_2p_2N1(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 2, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 52)
|
||||
{
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
L_index = index[k];
|
||||
D_ACELP_decode_3p_3N1(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 3, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 64)
|
||||
{
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
L_index = ((index[k] << 14) + index[k + 4]);
|
||||
D_ACELP_decode_4p_4N(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 4, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 72)
|
||||
{
|
||||
for(k = 0; k < 4 - 2; k++)
|
||||
{
|
||||
L_index = ((index[k] << 10) + index[k + 4]);
|
||||
D_ACELP_decode_5p_5N(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 5, k, code);
|
||||
}
|
||||
|
||||
for(k = 2; k < 4; k++)
|
||||
{
|
||||
L_index = ((index[k] << 14) + index[k + 4]);
|
||||
D_ACELP_decode_4p_4N(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 4, k, code);
|
||||
}
|
||||
}
|
||||
else if(nbbits == 88)
|
||||
{
|
||||
for(k = 0; k < 4; k++)
|
||||
{
|
||||
L_index = ((index[k] << 11) + index[k + 4]);
|
||||
D_ACELP_decode_6p_6N_2(L_index, 4, 0, pos);
|
||||
D_ACELP_add_pulse(pos, 6, k, code);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_ACELP_phase_dispersion
|
||||
*
|
||||
* Parameters:
|
||||
* gain_code I: (Q0) gain of code
|
||||
* gain_pit I: (Q14) gain of pitch
|
||||
* code I/O: code vector
|
||||
* mode I: level, 0=hi, 1=lo, 2=off
|
||||
* disp_mem I/O: static memory (size = 8)
|
||||
*
|
||||
* Function:
|
||||
* An adaptive anti-sparseness post-processing procedure is
|
||||
* applied to the fixed codebook vector in order to
|
||||
* reduce perceptual artifacts arising from the sparseness
|
||||
* of the algebraic fixed codebook vectors with only
|
||||
* a few non-zero samples per subframe.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_ACELP_phase_dispersion(Word16 gain_code, Word16 gain_pit, Word16 code[],
|
||||
Word16 mode, Word16 disp_mem[])
|
||||
{
|
||||
Word32 code2[2 * L_SUBFR] = {0};
|
||||
Word32 i, j, state;
|
||||
Word16 *prev_gain_pit, *prev_gain_code, *prev_state;
|
||||
|
||||
prev_state = disp_mem;
|
||||
prev_gain_code = disp_mem + 1;
|
||||
prev_gain_pit = disp_mem + 2;
|
||||
|
||||
if(gain_pit < 9830) /* 0.6 in Q14 */
|
||||
{
|
||||
state = 0;
|
||||
}
|
||||
else if(gain_pit < 14746) /* 0.9 in Q14 */
|
||||
{
|
||||
state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
}
|
||||
|
||||
for(i = 5; i > 0; i--)
|
||||
{
|
||||
prev_gain_pit[i] = prev_gain_pit[i - 1];
|
||||
}
|
||||
prev_gain_pit[0] = gain_pit;
|
||||
|
||||
if((gain_code - *prev_gain_code) > (*prev_gain_code << 1))
|
||||
{
|
||||
/* onset */
|
||||
if(state < 2)
|
||||
{
|
||||
state = state + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
|
||||
for(i = 0; i < 6; i++)
|
||||
{
|
||||
if(prev_gain_pit[i] < 9830) /* 0.6 in Q14 */
|
||||
j = (j + 1);
|
||||
}
|
||||
|
||||
if(j > 2)
|
||||
{
|
||||
state = 0;
|
||||
}
|
||||
|
||||
if((state - *prev_state) > 1)
|
||||
{
|
||||
state = state - 1;
|
||||
}
|
||||
}
|
||||
*prev_gain_code = gain_code;
|
||||
*prev_state = (Word16)state;
|
||||
|
||||
/* circular convolution */
|
||||
state = state + mode; /* level of dispersion */
|
||||
|
||||
if(state == 0)
|
||||
{
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
if(code[i] != 0)
|
||||
{
|
||||
for(j = 0; j < L_SUBFR; j++)
|
||||
{
|
||||
code2[i + j] = code2[i + j] +
|
||||
(((code[i] * D_ROM_ph_imp_low[j]) + 0x4000) >> 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(state == 1)
|
||||
{
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
if(code[i] != 0)
|
||||
{
|
||||
for(j = 0; j < L_SUBFR; j++)
|
||||
{
|
||||
code2[i + j] = code2[i + j] +
|
||||
(((code[i] * D_ROM_ph_imp_mid[j]) + 0x4000) >> 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(state < 2)
|
||||
{
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
code[i] = (Word16)(code2[i] + code2[i + L_SUBFR]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_ACELP_H
|
||||
#define DEC_ACELP_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
void D_ACELP_decode_2t(Word16 index, Word16 code[]);
|
||||
void D_ACELP_decode_4t(Word16 index[], Word16 nbbits, Word16 code[]);
|
||||
void D_ACELP_phase_dispersion(Word16 gain_code, Word16 gain_pit, Word16 code[],
|
||||
Word16 mode, Word16 disp_mem[]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,758 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
#include "typedef.h"
|
||||
#include "dec_dtx.h"
|
||||
#include "dec_lpc.h"
|
||||
#include "dec_util.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
#define MAX_31 (Word32)0x3FFFFFFF
|
||||
#define L_FRAME 256 /* Frame size */
|
||||
#define RX_SPEECH_LOST 2
|
||||
#define RX_SPEECH_BAD 3
|
||||
#define RX_SID_FIRST 4
|
||||
#define RX_SID_UPDATE 5
|
||||
#define RX_SID_BAD 6
|
||||
#define RX_NO_DATA 7
|
||||
#define ISF_GAP 128 /* 50 */
|
||||
#define D_DTX_MAX_EMPTY_THRESH 50
|
||||
#define GAIN_FACTOR 75
|
||||
#define ISF_FACTOR_LOW 256
|
||||
#define ISF_FACTOR_STEP 2
|
||||
#define ISF_DITH_GAP 448
|
||||
#define D_DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */
|
||||
#define D_DTX_ELAPSED_FRAMES_THRESH (24 + 7 - 1)
|
||||
#define RANDOM_INITSEED 21845 /* own random init value */
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_reset
|
||||
*
|
||||
* Parameters:
|
||||
* st O: state struct
|
||||
*
|
||||
* Function:
|
||||
* Initializes state memory
|
||||
*
|
||||
* Returns:
|
||||
* non-zero with error, zero for ok
|
||||
*/
|
||||
int D_DTX_reset(D_DTX_State *st, const Word16 *isf_init)
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
if(st == (D_DTX_State*)NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
st->mem_since_last_sid = 0;
|
||||
st->mem_true_sid_period_inv = (1 << 13); /* 0.25 in Q15 */
|
||||
st->mem_log_en = 3500;
|
||||
st->mem_log_en_prev = 3500;
|
||||
|
||||
/* low level noise for better performance in DTX handover cases */
|
||||
st->mem_cng_seed = RANDOM_INITSEED;
|
||||
st->mem_hist_ptr = 0;
|
||||
|
||||
/* Init isf_hist[] and decoder log frame energy */
|
||||
memcpy(st->mem_isf, isf_init, M * sizeof(Word16));
|
||||
memcpy(st->mem_isf_prev, isf_init, M * sizeof(Word16));
|
||||
|
||||
for(i = 0; i < D_DTX_HIST_SIZE; i++)
|
||||
{
|
||||
memcpy(&st->mem_isf_buf[i * M], isf_init, M * sizeof(Word16));
|
||||
st->mem_log_en_buf[i] = 3500;
|
||||
}
|
||||
st->mem_dtx_hangover_count = D_DTX_HANG_CONST;
|
||||
st->mem_dec_ana_elapsed_count = 127;
|
||||
st->mem_sid_frame = 0;
|
||||
st->mem_valid_data = 0;
|
||||
st->mem_dtx_hangover_added = 0;
|
||||
st->mem_dtx_global_state = SPEECH;
|
||||
st->mem_data_updated = 0;
|
||||
st->mem_dither_seed = RANDOM_INITSEED;
|
||||
st->mem_cn_dith = 0;
|
||||
st->mem_dtx_vad_hist = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_init
|
||||
*
|
||||
* Parameters:
|
||||
* st I/O: state struct
|
||||
*
|
||||
* Function:
|
||||
* Allocates state memory and initializes state memory
|
||||
*
|
||||
* Returns:
|
||||
* non-zero with error, zero for ok
|
||||
*/
|
||||
int D_DTX_init(D_DTX_State **st, const Word16 *isf_init)
|
||||
{
|
||||
D_DTX_State *s;
|
||||
|
||||
if(st == (D_DTX_State**)NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
*st = NULL;
|
||||
|
||||
/* allocate memory */
|
||||
if((s = (D_DTX_State*)malloc(sizeof(D_DTX_State))) == NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
D_DTX_reset(s, isf_init);
|
||||
*st = s;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_exit
|
||||
*
|
||||
* Parameters:
|
||||
* state I/0: State struct
|
||||
*
|
||||
* Function:
|
||||
* The memory used for state memory is freed
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_DTX_exit(D_DTX_State **st)
|
||||
{
|
||||
if(st == NULL || *st == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* deallocate memory */
|
||||
free(*st);
|
||||
*st = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_rx_handler
|
||||
*
|
||||
* Parameters:
|
||||
* st I/O: State struct
|
||||
* frame_type I: Frame type
|
||||
*
|
||||
* Function:
|
||||
* Analyze received frame
|
||||
*
|
||||
* Table of new SPD synthesis states
|
||||
*
|
||||
* | previous SPD_synthesis_state
|
||||
* Incoming |
|
||||
* frame_type | SPEECH | DTX | D_DTX_MUTE
|
||||
* ---------------------------------------------------------------
|
||||
* RX_SPEECH_GOOD , | | |
|
||||
* RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
|
||||
* ----------------------------------------------------------------
|
||||
* RX_SPEECH_BAD, | SPEECH | DTX | D_DTX_MUTE
|
||||
* ----------------------------------------------------------------
|
||||
* RX_SID_FIRST, | DTX | DTX/(D_DTX_MUTE)| D_DTX_MUTE
|
||||
* ----------------------------------------------------------------
|
||||
* RX_SID_UPDATE, | DTX | DTX | DTX
|
||||
* ----------------------------------------------------------------
|
||||
* RX_SID_BAD, | DTX | DTX/(D_DTX_MUTE)| D_DTX_MUTE
|
||||
* ----------------------------------------------------------------
|
||||
* RX_NO_DATA, | SPEECH | DTX/(D_DTX_MUTE)| D_DTX_MUTE
|
||||
* RX_SPARE |(class2 garb.)| |
|
||||
* ----------------------------------------------------------------
|
||||
*
|
||||
* Returns:
|
||||
* new state
|
||||
*/
|
||||
UWord8 D_DTX_rx_handler(D_DTX_State *st, UWord8 frame_type)
|
||||
{
|
||||
UWord8 newState;
|
||||
UWord8 encState;
|
||||
|
||||
/* DTX if SID frame or previously in DTX{_MUTE}
|
||||
* and (NO_RX OR BAD_SPEECH)
|
||||
*/
|
||||
if((frame_type == RX_SID_FIRST) | (frame_type == RX_SID_UPDATE) |
|
||||
(frame_type == RX_SID_BAD) | (((st->mem_dtx_global_state == DTX) |
|
||||
(st->mem_dtx_global_state == D_DTX_MUTE)) & ((frame_type == RX_NO_DATA) |
|
||||
(frame_type == RX_SPEECH_BAD) | (frame_type == RX_SPEECH_LOST))))
|
||||
{
|
||||
newState = DTX;
|
||||
|
||||
/* stay in mute for these input types */
|
||||
if((st->mem_dtx_global_state == D_DTX_MUTE) &
|
||||
((frame_type == RX_SID_BAD) | (frame_type == RX_SID_FIRST) |
|
||||
(frame_type == RX_SPEECH_LOST) | (frame_type == RX_NO_DATA)))
|
||||
{
|
||||
newState = D_DTX_MUTE;
|
||||
}
|
||||
|
||||
/* evaluate if noise parameters are too old */
|
||||
/* since_last_sid is reset when CN parameters have been updated */
|
||||
st->mem_since_last_sid = D_UTIL_saturate(st->mem_since_last_sid + 1);
|
||||
|
||||
/* no update of sid parameters in DTX for a Word32 while */
|
||||
if ((frame_type != RX_SID_UPDATE) &&
|
||||
(st->mem_since_last_sid > D_DTX_MAX_EMPTY_THRESH))
|
||||
{
|
||||
newState = D_DTX_MUTE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = SPEECH;
|
||||
st->mem_since_last_sid = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* reset the decAnaElapsed Counter when receiving CNI data the first
|
||||
* time, to robustify counter missmatch after handover
|
||||
* this might delay the bwd CNI analysis in the new decoder slightly.
|
||||
*/
|
||||
if((st->mem_data_updated == 0) & (frame_type == RX_SID_UPDATE))
|
||||
{
|
||||
st->mem_dec_ana_elapsed_count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* update the SPE-SPD DTX hangover synchronization
|
||||
* to know when SPE has added dtx hangover
|
||||
*/
|
||||
st->mem_dec_ana_elapsed_count++;
|
||||
|
||||
/* saturate */
|
||||
if(st->mem_dec_ana_elapsed_count > 127)
|
||||
{
|
||||
st->mem_dec_ana_elapsed_count = 127;
|
||||
}
|
||||
|
||||
st->mem_dtx_hangover_added = 0;
|
||||
|
||||
if((frame_type == RX_SID_FIRST) | (frame_type == RX_SID_UPDATE) |
|
||||
(frame_type == RX_SID_BAD) |
|
||||
((frame_type == RX_NO_DATA) && ((st->mem_dtx_global_state != SPEECH) ||
|
||||
(st->mem_dtx_vad_hist >= D_DTX_HANG_CONST))))
|
||||
|
||||
{
|
||||
encState = DTX;
|
||||
}
|
||||
else
|
||||
{
|
||||
encState = SPEECH;
|
||||
}
|
||||
|
||||
if(encState == SPEECH)
|
||||
{
|
||||
st->mem_dtx_hangover_count = D_DTX_HANG_CONST;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(st->mem_dec_ana_elapsed_count > D_DTX_ELAPSED_FRAMES_THRESH)
|
||||
{
|
||||
st->mem_dtx_hangover_added = 1;
|
||||
st->mem_dec_ana_elapsed_count = 0;
|
||||
st->mem_dtx_hangover_count = 0;
|
||||
}
|
||||
else if(st->mem_dtx_hangover_count == 0)
|
||||
{
|
||||
st->mem_dec_ana_elapsed_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
st->mem_dtx_hangover_count--;
|
||||
}
|
||||
}
|
||||
|
||||
if(newState != SPEECH)
|
||||
{
|
||||
/*
|
||||
* DTX or D_DTX_MUTE
|
||||
* CN data is not in a first SID, first SIDs are marked as SID_BAD
|
||||
* but will do backwards analysis if a hangover period has been added
|
||||
* according to the state machine above
|
||||
*/
|
||||
st->mem_sid_frame = 0;
|
||||
st->mem_valid_data = 0;
|
||||
|
||||
if(frame_type == RX_SID_FIRST)
|
||||
{
|
||||
st->mem_sid_frame = 1;
|
||||
}
|
||||
else if(frame_type == RX_SID_UPDATE)
|
||||
{
|
||||
st->mem_sid_frame = 1;
|
||||
st->mem_valid_data = 1;
|
||||
}
|
||||
else if(frame_type == RX_SID_BAD)
|
||||
{
|
||||
st->mem_sid_frame = 1;
|
||||
st->mem_dtx_hangover_added = 0; /* use old data */
|
||||
}
|
||||
}
|
||||
|
||||
return newState;
|
||||
|
||||
/* newState is used by both SPEECH AND DTX synthesis routines */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_cn_dithering
|
||||
*
|
||||
* Parameters:
|
||||
* isf I/O: CN ISF vector
|
||||
* L_log_en_int I/O: energy parameter
|
||||
* dither_seed I/O: random seed
|
||||
*
|
||||
* Function:
|
||||
* Confort noise dithering
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_DTX_cn_dithering(Word16 isf[M], Word32 *L_log_en_int,
|
||||
Word16 *dither_seed)
|
||||
{
|
||||
Word32 temp, temp1, i, dither_fac, rand_dith,rand_dith2;
|
||||
|
||||
/* Insert comfort noise dithering for energy parameter */
|
||||
rand_dith = D_UTIL_random(dither_seed) >> 1;
|
||||
rand_dith2 = D_UTIL_random(dither_seed) >>1;
|
||||
rand_dith = rand_dith + rand_dith2;
|
||||
*L_log_en_int = *L_log_en_int + ((rand_dith * GAIN_FACTOR) << 1);
|
||||
|
||||
if(*L_log_en_int < 0)
|
||||
{
|
||||
*L_log_en_int = 0;
|
||||
}
|
||||
|
||||
/* Insert comfort noise dithering for spectral parameters (ISF-vector) */
|
||||
dither_fac = ISF_FACTOR_LOW;
|
||||
rand_dith = D_UTIL_random(dither_seed) >> 1;
|
||||
rand_dith2 = D_UTIL_random(dither_seed) >> 1;
|
||||
rand_dith = rand_dith + rand_dith2;
|
||||
temp = isf[0] + (((rand_dith * dither_fac) + 0x4000) >> 15);
|
||||
|
||||
/* Make sure that isf[0] will not get negative values */
|
||||
if(temp < ISF_GAP)
|
||||
{
|
||||
isf[0] = ISF_GAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
isf[0] = (Word16)temp;
|
||||
}
|
||||
|
||||
for(i = 1; i < M - 1; i++)
|
||||
{
|
||||
dither_fac = dither_fac + ISF_FACTOR_STEP;
|
||||
rand_dith = D_UTIL_random(dither_seed) >> 1;
|
||||
rand_dith2 = D_UTIL_random(dither_seed) >> 1;
|
||||
rand_dith = rand_dith + rand_dith2;
|
||||
temp = isf[i] + (((rand_dith * dither_fac) + 0x4000) >> 15);
|
||||
temp1 = temp - isf[i - 1];
|
||||
|
||||
/* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */
|
||||
if(temp1 < ISF_DITH_GAP)
|
||||
{
|
||||
isf[i] = (Word16)(isf[i - 1] + ISF_DITH_GAP);
|
||||
}
|
||||
else
|
||||
{
|
||||
isf[i] = (Word16)temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that isf[M-2] will not get values above 16384 */
|
||||
if(isf[M - 2] > 16384)
|
||||
{
|
||||
isf[M - 2] = 16384;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_exe
|
||||
*
|
||||
* Parameters:
|
||||
* st I/O: state struct
|
||||
* exc2 O: CN excitation
|
||||
* new_state I: New DTX state
|
||||
* prms I: Vector of synthesis parameters
|
||||
* isf O: CN ISF vector
|
||||
*
|
||||
* Function:
|
||||
* Confort noise generation
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_DTX_exe(D_DTX_State *st, Word16 *exc2, Word16 new_state, Word16 isf[],
|
||||
Word16 **prms)
|
||||
{
|
||||
|
||||
Word32 i, j, L_tmp, ptr;
|
||||
Word32 exp0, int_fac;
|
||||
Word32 gain;
|
||||
Word32 L_isf[M], L_log_en_int, level32, ener32;
|
||||
Word16 log_en_index;
|
||||
Word16 tmp_int_length;
|
||||
Word16 exp, log_en_int_e, log_en_int_m, level;
|
||||
|
||||
|
||||
/*
|
||||
* This function is called if synthesis state is not SPEECH.
|
||||
* The globally passed inputs to this function are
|
||||
* st->sid_frame
|
||||
* st->valid_data
|
||||
* st->dtxHangoverAdded
|
||||
* new_state (SPEECH, DTX, D_DTX_MUTE)
|
||||
*/
|
||||
if((st->mem_dtx_hangover_added != 0) & (st->mem_sid_frame != 0))
|
||||
{
|
||||
/* sid_first after dtx hangover period
|
||||
* or sid_upd after dtxhangover
|
||||
* consider twice the last frame
|
||||
*/
|
||||
ptr = st->mem_hist_ptr + 1;
|
||||
|
||||
if(ptr == D_DTX_HIST_SIZE)
|
||||
{
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
memcpy(&st->mem_isf_buf[ptr * M], &st->mem_isf_buf[st->mem_hist_ptr * M],
|
||||
M * sizeof(Word16));
|
||||
|
||||
st->mem_log_en_buf[ptr] = st->mem_log_en_buf[st->mem_hist_ptr];
|
||||
|
||||
/* compute mean log energy and isf from decoded signal (SID_FIRST) */
|
||||
st->mem_log_en = 0;
|
||||
memset(L_isf, 0, M * sizeof(Word32));
|
||||
|
||||
/* average energy and isf */
|
||||
for(i = 0; i < D_DTX_HIST_SIZE; i++)
|
||||
{
|
||||
/*
|
||||
* Division by D_DTX_HIST_SIZE = 8 has been done in dtx_buffer log_en
|
||||
* is in Q10
|
||||
*/
|
||||
st->mem_log_en = (Word16)(st->mem_log_en + st->mem_log_en_buf[i]);
|
||||
|
||||
for(j = 0; j < M; j++)
|
||||
{
|
||||
L_isf[j] = L_isf[j] + st->mem_isf_buf[i * M + j];
|
||||
}
|
||||
}
|
||||
|
||||
/* st->log_en in Q9 */
|
||||
st->mem_log_en = (Word16)(st->mem_log_en >> 1);
|
||||
|
||||
/*
|
||||
* Add 2 in Q9, in order to have only positive values for Pow2
|
||||
* this value is subtracted back after Pow2 function
|
||||
*/
|
||||
st->mem_log_en = (Word16)(st->mem_log_en + 1024);
|
||||
|
||||
if(st->mem_log_en < 0)
|
||||
{
|
||||
st->mem_log_en = 0;
|
||||
}
|
||||
|
||||
for(j = 0; j < M; j++)
|
||||
{
|
||||
st->mem_isf[j] = (Word16)(L_isf[j]>>3); /* divide by 8 */
|
||||
}
|
||||
}
|
||||
|
||||
if(st->mem_sid_frame != 0)
|
||||
{
|
||||
/*
|
||||
* Set old SID parameters, always shift
|
||||
* even if there is no new valid_data
|
||||
*/
|
||||
memcpy(st->mem_isf_prev, st->mem_isf, M * sizeof(Word16));
|
||||
st->mem_log_en_prev = st->mem_log_en;
|
||||
|
||||
if(st->mem_valid_data != 0) /* new data available (no CRC) */
|
||||
{
|
||||
/* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
|
||||
|
||||
/*
|
||||
* Compute interpolation factor, since the division only works
|
||||
* for values of since_last_sid < 32 we have to limit
|
||||
* the interpolation to 32 frames
|
||||
*/
|
||||
tmp_int_length = st->mem_since_last_sid;
|
||||
|
||||
if(tmp_int_length > 32)
|
||||
{
|
||||
tmp_int_length = 32;
|
||||
}
|
||||
|
||||
if(tmp_int_length >= 2)
|
||||
{
|
||||
st->mem_true_sid_period_inv =
|
||||
(Word16)(0x2000000 / (tmp_int_length << 10));
|
||||
}
|
||||
else
|
||||
{
|
||||
st->mem_true_sid_period_inv = 1 << 14; /* 0.5 it Q15 */
|
||||
}
|
||||
|
||||
D_LPC_isf_noise_d(*prms, st->mem_isf);
|
||||
(*prms) += 5;
|
||||
log_en_index = *(*prms)++;
|
||||
|
||||
/* read background noise stationarity information */
|
||||
st->mem_cn_dith = *(*prms)++;
|
||||
|
||||
/*
|
||||
* st->log_en = (Float32)log_en_index / 2.625 - 2.0;
|
||||
* log2(E) in Q9 (log2(E) lies in between -2:22)
|
||||
*/
|
||||
st->mem_log_en = (Word16)(log_en_index << (15 - 6));
|
||||
|
||||
/* Divide by 2.625 */
|
||||
st->mem_log_en = (Word16)((st->mem_log_en * 12483) >> 15);
|
||||
|
||||
/*
|
||||
* Subtract 2 in Q9 is done later, after Pow2 function
|
||||
* no interpolation at startup after coder reset
|
||||
* or when SID_UPD has been received right after SPEECH
|
||||
*/
|
||||
if((st->mem_data_updated == 0) ||
|
||||
(st->mem_dtx_global_state == SPEECH))
|
||||
{
|
||||
memcpy(st->mem_isf_prev, st->mem_isf, M * sizeof(Word16));
|
||||
st->mem_log_en_prev = st->mem_log_en;
|
||||
}
|
||||
} /* endif valid_data */
|
||||
} /* endif sid_frame */
|
||||
|
||||
if((st->mem_sid_frame != 0) && (st->mem_valid_data != 0))
|
||||
{
|
||||
st->mem_since_last_sid = 0;
|
||||
}
|
||||
|
||||
/* Interpolate SID info */
|
||||
if(st->mem_since_last_sid < 32)
|
||||
{
|
||||
int_fac = st->mem_since_last_sid << 10; /* Q10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
int_fac = 32767;
|
||||
}
|
||||
/* Q10 * Q15 -> Q10 */
|
||||
int_fac = (int_fac * st->mem_true_sid_period_inv) >> 15;
|
||||
|
||||
/* Maximize to 1.0 in Q10 */
|
||||
if(int_fac > 1024)
|
||||
{
|
||||
int_fac = 1024;
|
||||
}
|
||||
int_fac = int_fac << 4; /* Q10 -> Q14 */
|
||||
L_log_en_int = (int_fac * st->mem_log_en) << 1; /* Q14 * Q9 -> Q24 */
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
/* Q14 * Q15 -> Q14 */
|
||||
isf[i] = (Word16)((int_fac * st->mem_isf[i]) >> 15);
|
||||
}
|
||||
int_fac = 16384 - int_fac; /* 1-k in Q14 */
|
||||
|
||||
/* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */
|
||||
L_log_en_int = L_log_en_int + ((int_fac * st->mem_log_en_prev) << 1);
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
/* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
|
||||
L_tmp = isf[i] + ((int_fac * st->mem_isf_prev[i]) >> 15);
|
||||
isf[i] = (Word16)(L_tmp << 1); /* Q14 -> Q15 */
|
||||
}
|
||||
|
||||
/* If background noise is non-stationary, insert comfort noise dithering */
|
||||
if(st->mem_cn_dith != 0)
|
||||
{
|
||||
D_DTX_cn_dithering(isf, &L_log_en_int, &st->mem_dither_seed);
|
||||
}
|
||||
|
||||
/* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
|
||||
L_log_en_int = (L_log_en_int >> 9); /* Q25 -> Q16 */
|
||||
|
||||
/* Find integer part */
|
||||
log_en_int_e = (Word16)((L_log_en_int)>>16);
|
||||
|
||||
/* Find fractional part */
|
||||
log_en_int_m = (Word16)((L_log_en_int - (log_en_int_e << 16)) >> 1);
|
||||
|
||||
/*
|
||||
* Subtract 2 from L_log_en_int in Q9,
|
||||
* i.e divide the gain by 2 (energy by 4)
|
||||
* Add 16 in order to have the result of pow2 in Q16
|
||||
*/
|
||||
log_en_int_e = (Word16)(log_en_int_e + (16 - 1));
|
||||
|
||||
/* level = (Float32)( pow( 2.0f, log_en ) ); */
|
||||
level32 = D_UTIL_pow2(log_en_int_e, log_en_int_m); /* Q16 */
|
||||
exp0 = D_UTIL_norm_l(level32);
|
||||
level32 = (level32 << exp0); /* level in Q31 */
|
||||
exp0 = (15 - exp0);
|
||||
level = (Word16)(level32 >> 16); /* level in Q15 */
|
||||
|
||||
/* generate white noise vector */
|
||||
for(i = 0; i < L_FRAME; i++)
|
||||
{
|
||||
exc2[i] = (Word16)((D_UTIL_random(&(st->mem_cng_seed)) >> 4));
|
||||
}
|
||||
|
||||
/* gain = level / sqrt(ener) * sqrt(L_FRAME) */
|
||||
/* energy of generated excitation */
|
||||
ener32 = D_UTIL_dot_product12(exc2, exc2, L_FRAME, &exp);
|
||||
D_UTIL_normalised_inverse_sqrt(&ener32, &exp);
|
||||
gain = ener32 >>16;
|
||||
gain = (level * gain) >> 15; /* gain in Q15 */
|
||||
|
||||
/* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
|
||||
exp = (Word16)(exp0 + exp + 4);
|
||||
|
||||
if(exp >= 0)
|
||||
{
|
||||
for(i = 0; i < L_FRAME; i++)
|
||||
{
|
||||
L_tmp = (exc2[i] * gain) >> 15; /* Q0 * Q15 */
|
||||
exc2[i] = (Word16)(L_tmp << exp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exp = (Word16)-exp;
|
||||
|
||||
for(i = 0; i < L_FRAME; i++)
|
||||
{
|
||||
L_tmp = (exc2[i] * gain) >> 15; /* Q0 * Q15 */
|
||||
exc2[i] = (Word16)(L_tmp >> exp);
|
||||
}
|
||||
}
|
||||
|
||||
if(new_state == D_DTX_MUTE)
|
||||
{
|
||||
/*
|
||||
* mute comfort noise as it has been quite a long time since
|
||||
* last SID update was performed
|
||||
*/
|
||||
tmp_int_length = st->mem_since_last_sid;
|
||||
|
||||
if(tmp_int_length > 32)
|
||||
{
|
||||
tmp_int_length = 32;
|
||||
}
|
||||
|
||||
/* safety guard against division by zero */
|
||||
if(tmp_int_length <= 0) {
|
||||
tmp_int_length = 8;
|
||||
}
|
||||
st->mem_true_sid_period_inv = D_UTIL_saturate((0x02000000 / (tmp_int_length << 10)));
|
||||
st->mem_since_last_sid = 0;
|
||||
st->mem_log_en_prev = st->mem_log_en;
|
||||
|
||||
/* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
|
||||
st->mem_log_en = D_UTIL_saturate(st->mem_log_en - 64);
|
||||
}
|
||||
|
||||
/* reset interpolation length timer if data has been updated. */
|
||||
if((st->mem_sid_frame != 0) && ((st->mem_valid_data != 0) ||
|
||||
((st->mem_valid_data == 0) && (st->mem_dtx_hangover_added) != 0)))
|
||||
{
|
||||
st->mem_since_last_sid = 0;
|
||||
st->mem_data_updated = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_DTX_activity_update
|
||||
*
|
||||
* Parameters:
|
||||
* st I/O: state struct
|
||||
* isf O: ISF vector
|
||||
* exc O: excitation
|
||||
*
|
||||
* Function:
|
||||
* Confort noise generation
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_DTX_activity_update(D_DTX_State *st, Word16 isf[], Word16 exc[])
|
||||
{
|
||||
|
||||
Word32 L_frame_en, log_en;
|
||||
Word32 i;
|
||||
Word16 log_en_e, log_en_m;
|
||||
|
||||
st->mem_hist_ptr = (Word16)(st->mem_hist_ptr + 1);
|
||||
|
||||
if(st->mem_hist_ptr == D_DTX_HIST_SIZE)
|
||||
{
|
||||
st->mem_hist_ptr = 0;
|
||||
}
|
||||
|
||||
memcpy(&st->mem_isf_buf[st->mem_hist_ptr * M], isf, M * sizeof(Word16));
|
||||
|
||||
/* compute log energy based on excitation frame energy in Q0 */
|
||||
L_frame_en = 0;
|
||||
|
||||
for(i = 0; i < L_FRAME; i++)
|
||||
{
|
||||
L_frame_en = L_frame_en + (exc[i] * exc[i]);
|
||||
if (L_frame_en > MAX_31)
|
||||
{
|
||||
L_frame_en = MAX_31;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* log_en =
|
||||
* (Float32)log10(L_frame_en/(Float32)L_FRAME)/(Float32)log10(2.0f);
|
||||
*/
|
||||
D_UTIL_log2(L_frame_en, &log_en_e, &log_en_m);
|
||||
|
||||
/*
|
||||
* convert exponent and mantissa to Word16 Q7.
|
||||
* Q7 is used to simplify averaging in dtx_enc
|
||||
*/
|
||||
log_en = log_en_e << 7; /* Q7 */
|
||||
log_en = log_en + (log_en_m >> (15 - 7));
|
||||
|
||||
/* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
|
||||
log_en = log_en - 1024;
|
||||
|
||||
/* insert into log energy buffer */
|
||||
st->mem_log_en_buf[st->mem_hist_ptr] = (Word16)log_en;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_DTX_H
|
||||
#define DEC_DTX_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
#define M 16 /* Order of LP filter */
|
||||
#define SPEECH 0
|
||||
#define DTX 1
|
||||
#define D_DTX_MUTE 2
|
||||
#define D_DTX_HIST_SIZE 8
|
||||
|
||||
typedef struct {
|
||||
Word16 mem_isf_buf[M * D_DTX_HIST_SIZE]; /* ISF vector history (8 frames)*/
|
||||
Word16 mem_isf[M]; /* ISF vector */
|
||||
Word16 mem_isf_prev[M]; /* Previous ISF vector */
|
||||
Word16 mem_log_en_buf[D_DTX_HIST_SIZE];/* logarithmic frame energy history*/
|
||||
Word16 mem_true_sid_period_inv; /* inverse of true SID update rate */
|
||||
Word16 mem_log_en; /* logarithmic frame energy */
|
||||
Word16 mem_log_en_prev; /* previous logarithmic frame energy */
|
||||
Word16 mem_cng_seed; /* Comfort noise excitation seed */
|
||||
Word16 mem_hist_ptr; /* index to beginning of LSF history */
|
||||
Word16 mem_dither_seed; /* comfort noise dithering seed */
|
||||
Word16 mem_cn_dith; /* background noise stationarity information*/
|
||||
Word16 mem_since_last_sid; /* number of frames since last SID frame */
|
||||
|
||||
UWord8 mem_dec_ana_elapsed_count;/* counts elapsed speech frames after DTX*/
|
||||
UWord8 mem_dtx_global_state; /* DTX state flags */
|
||||
UWord8 mem_data_updated; /* flags CNI updates */
|
||||
UWord8 mem_dtx_hangover_count;/* counts down in hangover period */
|
||||
UWord8 mem_sid_frame; /* flags SID frames */
|
||||
UWord8 mem_valid_data; /* flags SID frames containing valid data */
|
||||
UWord8 mem_dtx_hangover_added;/* flags hangover period at end of speech */
|
||||
Word16 mem_dtx_vad_hist; /* "hangover counter" */
|
||||
|
||||
} D_DTX_State;
|
||||
|
||||
int D_DTX_init(D_DTX_State **st, const Word16 *isf_init);
|
||||
int D_DTX_reset(D_DTX_State *st, const Word16 *isf_init);
|
||||
void D_DTX_exit(D_DTX_State **st);
|
||||
UWord8 D_DTX_rx_handler(D_DTX_State *st, UWord8 frame_type);
|
||||
void D_DTX_exe(D_DTX_State *st, Word16 *exc2, Word16 new_state,
|
||||
Word16 isf[], Word16 **prms);
|
||||
void D_DTX_activity_update(D_DTX_State *st, Word16 isf[], Word16 exc[]);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,964 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "dec_util.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
#define L_SUBFR 64 /* Subframe size */
|
||||
#define L_LTPHIST 5
|
||||
#define ONE_PER_3 10923
|
||||
#define ONE_PER_LTPHIST 6554
|
||||
#define UP_SAMP 4
|
||||
#define L_INTERPOL2 16
|
||||
|
||||
extern const Word16 D_ROM_inter4_2[];
|
||||
extern const Word16 D_ROM_pdown_unusable[];
|
||||
extern const Word16 D_ROM_pdown_usable[];
|
||||
extern const Word16 D_ROM_cdown_unusable[];
|
||||
extern const Word16 D_ROM_cdown_usable[];
|
||||
extern const Word16 D_ROM_qua_gain6b[];
|
||||
extern const Word16 D_ROM_qua_gain7b[];
|
||||
|
||||
/*
|
||||
* D_GAIN_init
|
||||
*
|
||||
* Parameters:
|
||||
* mem O: static memory
|
||||
*
|
||||
* Function:
|
||||
* Initialisation of 2nd order quantiser energy predictor.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_init(Word16 *mem)
|
||||
{
|
||||
|
||||
/* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
|
||||
mem[0] = -14336; /* past_qua_en[0] */
|
||||
mem[1] = -14336; /* past_qua_en[1] */
|
||||
mem[2] = -14336; /* past_qua_en[2] */
|
||||
mem[3] = -14336; /* past_qua_en[3] */
|
||||
/*
|
||||
* mem[4] = 0; past_gain_pit
|
||||
* mem[5] = 0; past_gain_code
|
||||
* mem[6] = 0; prev_gc
|
||||
* mem[7 - 11] = 0; pbuf[i]
|
||||
* mem[12 - 16] = 0; gbuf[i]
|
||||
* mem[17 - 21] = 0; pbuf2[i]
|
||||
*/
|
||||
memset(&mem[4], 0, 18 * sizeof(Word16));
|
||||
|
||||
mem[22] = 21845; /* seed */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_median
|
||||
*
|
||||
* Parameters:
|
||||
* buf I: previous gains
|
||||
*
|
||||
* Function:
|
||||
* Median of gains
|
||||
*
|
||||
* Returns:
|
||||
* median of 5 previous gains
|
||||
*/
|
||||
static Word16 D_GAIN_median(Word16 x[])
|
||||
{
|
||||
Word16 x1, x2, x3, x4, x5;
|
||||
Word16 tmp;
|
||||
x1 = x[ - 2];
|
||||
x2 = x[ - 1];
|
||||
x3 = x[0];
|
||||
x4 = x[1];
|
||||
x5 = x[2];
|
||||
|
||||
if(x2 < x1)
|
||||
{
|
||||
tmp = x1;
|
||||
x1 = x2;
|
||||
x2 = tmp;
|
||||
}
|
||||
|
||||
if(x3 < x1)
|
||||
{
|
||||
tmp = x1;
|
||||
x1 = x3;
|
||||
x3 = tmp;
|
||||
}
|
||||
|
||||
if(x4 < x1)
|
||||
{
|
||||
tmp = x1;
|
||||
x1 = x4;
|
||||
x4 = tmp;
|
||||
}
|
||||
|
||||
if(x5 < x1)
|
||||
{
|
||||
x5 = x1;
|
||||
}
|
||||
|
||||
if(x3 < x2)
|
||||
{
|
||||
tmp = x2;
|
||||
x2 = x3;
|
||||
x3 = tmp;
|
||||
}
|
||||
|
||||
if(x4 < x2)
|
||||
{
|
||||
tmp = x2;
|
||||
x2 = x4;
|
||||
x4 = tmp;
|
||||
}
|
||||
|
||||
if(x5 < x2)
|
||||
{
|
||||
x5 = x2;
|
||||
}
|
||||
|
||||
if(x4 < x3)
|
||||
{
|
||||
x3 = x4;
|
||||
}
|
||||
|
||||
if(x5 < x3)
|
||||
{
|
||||
x3 = x5;
|
||||
}
|
||||
|
||||
return(x3);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_decode
|
||||
*
|
||||
* Parameters:
|
||||
* index I: Quantization index
|
||||
* nbits I: number of bits (6 or 7)
|
||||
* code I: Innovative code vector
|
||||
* L_subfr I: Subframe size
|
||||
* gain_pit O: (Q14) Quantized pitch gain
|
||||
* gain_code O: (Q16) Quantized codebook gain
|
||||
* bfi I: Bad frame indicator
|
||||
* prev_bfi I: Previous BF indicator
|
||||
* state I: State of BFH
|
||||
* unusable_frame I: UF indicator
|
||||
* vad_hist I: number of non-speech frames
|
||||
* mem I/O: static memory (4 words)
|
||||
*
|
||||
*
|
||||
* Function:
|
||||
* Decoding of pitch and codebook gains
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_decode(Word16 index, Word16 nbits, Word16 code[], Word16 *gain_pit,
|
||||
Word32 *gain_cod, Word16 bfi, Word16 prev_bfi,
|
||||
Word16 state, Word16 unusable_frame, Word16 vad_hist,
|
||||
Word16 *mem)
|
||||
{
|
||||
|
||||
Word32 gcode0, qua_ener, L_tmp;
|
||||
const Word16 * p;
|
||||
Word16 *past_gain_pit, *past_gain_code, *past_qua_en, *prev_gc;
|
||||
Word16 *gbuf, *pbuf, *pbuf2;
|
||||
Word16 i, tmp, exp, frac, exp_gcode0, gcode_inov;
|
||||
Word16 g_code;
|
||||
|
||||
past_qua_en = mem;
|
||||
past_gain_pit = mem + 4;
|
||||
past_gain_code = mem + 5;
|
||||
prev_gc = mem + 6;
|
||||
pbuf = mem + 7;
|
||||
gbuf = mem + 12;
|
||||
pbuf2 = mem + 17;
|
||||
|
||||
/*
|
||||
* Find energy of code and compute:
|
||||
*
|
||||
* L_tmp = 1.0 / sqrt(energy of code/ L_subfr)
|
||||
*/
|
||||
L_tmp = D_UTIL_dot_product12(code, code, L_SUBFR, &exp);
|
||||
exp = (Word16)(exp - (18 + 6)); /* exp: -18 (code in Q9), -6 (/L_subfr) */
|
||||
D_UTIL_normalised_inverse_sqrt(&L_tmp, &exp);
|
||||
|
||||
if(exp > 3)
|
||||
{
|
||||
L_tmp <<= (exp - 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
L_tmp >>= (3 - exp);
|
||||
}
|
||||
|
||||
gcode_inov = (Word16)(L_tmp >>16); /* g_code_inov in Q12 */
|
||||
|
||||
/*
|
||||
* Case of erasure.
|
||||
*/
|
||||
if(bfi != 0)
|
||||
{
|
||||
tmp = D_GAIN_median(&pbuf[2]);
|
||||
*past_gain_pit = tmp;
|
||||
|
||||
if(*past_gain_pit > 15565)
|
||||
{
|
||||
*past_gain_pit = 15565; /* 0.95 in Q14 */
|
||||
}
|
||||
|
||||
if(unusable_frame != 0)
|
||||
{
|
||||
*gain_pit =
|
||||
(Word16)((D_ROM_pdown_unusable[state] * *past_gain_pit) >> 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
*gain_pit =
|
||||
(Word16)((D_ROM_pdown_usable[state] * *past_gain_pit) >> 15);
|
||||
}
|
||||
|
||||
tmp = D_GAIN_median(&gbuf[2]);
|
||||
|
||||
if(vad_hist > 2)
|
||||
{
|
||||
*past_gain_code = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(unusable_frame != 0)
|
||||
{
|
||||
*past_gain_code =
|
||||
(Word16)((D_ROM_cdown_unusable[state] * tmp) >> 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
*past_gain_code =
|
||||
(Word16)((D_ROM_cdown_usable[state] * tmp) >> 15);
|
||||
}
|
||||
}
|
||||
|
||||
/* update table of past quantized energies */
|
||||
L_tmp = past_qua_en[0] + past_qua_en[1]+ past_qua_en[2] + past_qua_en[3];
|
||||
qua_ener = L_tmp >> 2;
|
||||
qua_ener = qua_ener - 3072; /* -3 in Q10 */
|
||||
|
||||
if(qua_ener < - 14336)
|
||||
{
|
||||
qua_ener = -14336; /* -14 in Q10 */
|
||||
}
|
||||
|
||||
past_qua_en[3] = past_qua_en[2];
|
||||
past_qua_en[2] = past_qua_en[1];
|
||||
past_qua_en[1] = past_qua_en[0];
|
||||
past_qua_en[0] = (Word16)qua_ener;
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
gbuf[i - 1] = gbuf[i];
|
||||
}
|
||||
gbuf[4] = *past_gain_code;
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
pbuf[i - 1] = pbuf[i];
|
||||
}
|
||||
pbuf[4] = *past_gain_pit;
|
||||
|
||||
/* adjust gain according to energy of code */
|
||||
/* past_gain_code(Q3) * gcode_inov(Q12) => Q16 */
|
||||
*gain_cod = (*past_gain_code * gcode_inov) << 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute gcode0.
|
||||
* = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code
|
||||
*/
|
||||
|
||||
/* MEAN_ENER in Q24 = 0x1e000000 */
|
||||
/* MA prediction coeff = {0.5, 0.4, 0.3, 0.2} in Q13 */
|
||||
L_tmp = 0xF000000 + (4096 * past_qua_en[0]); /* Q13*Q10 -> Q24 */
|
||||
L_tmp = L_tmp + (3277 * past_qua_en[1]); /* Q13*Q10 -> Q24 */
|
||||
L_tmp = L_tmp + (2458 * past_qua_en[2]); /* Q13*Q10 -> Q24 */
|
||||
L_tmp = L_tmp + (1638 * past_qua_en[3]); /* Q13*Q10 -> Q24 */
|
||||
gcode0 = L_tmp >> 15; /* From Q24 to Q8 */
|
||||
|
||||
/*
|
||||
* gcode0 = pow(10.0, gcode0/20)
|
||||
* = pow(2, 3.321928*gcode0/20)
|
||||
* = pow(2, 0.166096*gcode0)
|
||||
*/
|
||||
L_tmp = (gcode0 * 5443) >> 7;
|
||||
/* *0.166096 in Q15 -> Q24, From Q24 to Q16 */
|
||||
D_UTIL_l_extract(L_tmp, &exp_gcode0, &frac);
|
||||
/* Extract exponant of gcode0 */
|
||||
gcode0 = D_UTIL_pow2(14, frac); /* Put 14 as exponant so that */
|
||||
|
||||
/*
|
||||
* output of Pow2() will be:
|
||||
* 16384 < Pow2() <= 32767
|
||||
*/
|
||||
exp_gcode0 = (Word16)(exp_gcode0 - 14);
|
||||
|
||||
/* Read the quantized gains */
|
||||
if(nbits == 6)
|
||||
{
|
||||
p = &D_ROM_qua_gain6b[(index << 1)];
|
||||
}
|
||||
else
|
||||
{
|
||||
p = &D_ROM_qua_gain7b[(index << 1)];
|
||||
}
|
||||
|
||||
*gain_pit = *p++; /* selected pitch gain in Q14 */
|
||||
g_code = *p++; /* selected code gain in Q11 */
|
||||
L_tmp = g_code * gcode0;
|
||||
exp_gcode0 += 5;
|
||||
|
||||
if(exp_gcode0 >= 0)
|
||||
{
|
||||
*gain_cod = L_tmp << exp_gcode0; /* gain of code in Q16 */
|
||||
}
|
||||
else
|
||||
{
|
||||
*gain_cod = L_tmp >> -exp_gcode0; /* gain of code in Q16 */
|
||||
}
|
||||
|
||||
if(prev_bfi == 1)
|
||||
{
|
||||
L_tmp = (*prev_gc * 5120) << 1; /* prev_gc(Q3) * 1.25(Q12) = Q16 */
|
||||
|
||||
/* if((*gain_cod > ((*prev_gc) * 1.25)) && (*gain_cod > 100.0)) */
|
||||
if((*gain_cod > L_tmp) & (*gain_cod > 6553600))
|
||||
{
|
||||
*gain_cod = L_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* keep past gain code in Q3 for frame erasure (can saturate) */
|
||||
L_tmp = (*gain_cod + 0x1000) >> 13;
|
||||
|
||||
if(L_tmp < 32768)
|
||||
{
|
||||
*past_gain_code = (Word16)L_tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
*past_gain_code = 32767;
|
||||
}
|
||||
|
||||
*past_gain_pit = *gain_pit;
|
||||
*prev_gc = *past_gain_code;
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
gbuf[i - 1] = gbuf[i];
|
||||
}
|
||||
gbuf[4] = *past_gain_code;
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
pbuf[i - 1] = pbuf[i];
|
||||
}
|
||||
pbuf[4] = *past_gain_pit;
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
{
|
||||
pbuf2[i - 1] = pbuf2[i];
|
||||
}
|
||||
pbuf2[4] = *past_gain_pit;
|
||||
|
||||
/* adjust gain according to energy of code */
|
||||
D_UTIL_l_extract(*gain_cod, &exp, &frac);
|
||||
L_tmp = D_UTIL_mpy_32_16(exp, frac, gcode_inov);
|
||||
|
||||
if(L_tmp < 0xFFFFFFF)
|
||||
{
|
||||
*gain_cod = (L_tmp << 3); /* gcode_inov in Q12 */
|
||||
}
|
||||
else
|
||||
{
|
||||
*gain_cod = 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* qua_ener = 20*log10(g_code)
|
||||
* = 6.0206*log2(g_code)
|
||||
* = 6.0206*(log2(g_codeQ11) - 11)
|
||||
*/
|
||||
L_tmp = (Word32)(g_code);
|
||||
D_UTIL_log2(L_tmp, &exp, &frac);
|
||||
exp = (Word16)(exp - 11);
|
||||
L_tmp = D_UTIL_mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
|
||||
qua_ener = L_tmp >>3; /* result in Q10 */
|
||||
|
||||
/* update table of past quantized energies */
|
||||
past_qua_en[3] = past_qua_en[2];
|
||||
past_qua_en[2] = past_qua_en[1];
|
||||
past_qua_en[1] = past_qua_en[0];
|
||||
past_qua_en[0] = (Word16)qua_ener;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_adaptive_control
|
||||
*
|
||||
* Parameters:
|
||||
* sig_in I: postfilter input signal
|
||||
* sig_out I/O: postfilter output signal
|
||||
* l_trm I: subframe size
|
||||
*
|
||||
* Function:
|
||||
* Adaptive gain control is used to compensate for
|
||||
* the gain difference between the non-emphasized excitation and
|
||||
* emphasized excitation.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_adaptive_control(Word16 *sig_in, Word16 *sig_out, Word16 l_trm)
|
||||
{
|
||||
Word32 s, temp, i, exp;
|
||||
Word32 gain_in, gain_out, g0;
|
||||
|
||||
/* calculate gain_out with exponent */
|
||||
temp = sig_out[0] >> 2;
|
||||
s = temp * temp;
|
||||
|
||||
for(i = 1; i < l_trm; i++)
|
||||
{
|
||||
temp = sig_out[i] >> 2;
|
||||
s += temp * temp;
|
||||
}
|
||||
|
||||
s <<= 1;
|
||||
|
||||
if(s == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
exp = (D_UTIL_norm_l(s) - 1);
|
||||
|
||||
if(exp >= 0)
|
||||
{
|
||||
gain_out = ((s << exp) + 0x8000) >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
gain_out = ((s >> -exp) + 0x8000) >> 16;
|
||||
}
|
||||
|
||||
/* calculate gain_in with exponent */
|
||||
temp = sig_in[0] >> 2;
|
||||
s = temp * temp;
|
||||
|
||||
for(i = 1; i < l_trm; i++)
|
||||
{
|
||||
temp = sig_in[i] >> 2;
|
||||
s += temp * temp;
|
||||
}
|
||||
|
||||
s <<= 1;
|
||||
|
||||
if(s == 0)
|
||||
{
|
||||
g0 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = D_UTIL_norm_l(s);
|
||||
s = ((s << i) + 0x8000) >> 16;
|
||||
|
||||
if((s < 32768) & (s > 0))
|
||||
{
|
||||
gain_in = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
gain_in = 32767;
|
||||
}
|
||||
exp = exp - i;
|
||||
|
||||
/*
|
||||
* g0 = sqrt(gain_in/gain_out)
|
||||
*/
|
||||
s = (gain_out << 15) / gain_in;
|
||||
s = s << (7 - exp); /* s = gain_out / gain_in */
|
||||
s = D_UTIL_inverse_sqrt(s);
|
||||
g0 = ((s << 9) + 0x8000) >> 16;
|
||||
}
|
||||
|
||||
/* sig_out(n) = gain(n) sig_out(n) */
|
||||
for(i = 0; i < l_trm; i++)
|
||||
{
|
||||
s = (sig_out[i] * g0) >> 13;
|
||||
sig_out[i] = D_UTIL_saturate(s);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_insert_lag
|
||||
*
|
||||
* Parameters:
|
||||
* array I/O: pitch lag history
|
||||
* n I: history size
|
||||
* x I: lag value
|
||||
*
|
||||
* Function:
|
||||
* Insert lag into correct location
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_GAIN_insert_lag(Word16 array[], Word32 n, Word16 x)
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
for(i = n - 1; i >= 0; i--)
|
||||
{
|
||||
if(x < array[i])
|
||||
{
|
||||
array[i + 1] = array[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
array[i + 1] = x;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_sort_lag
|
||||
*
|
||||
* Parameters:
|
||||
* array I/O: pitch lag history
|
||||
* n I: history size
|
||||
*
|
||||
* Function:
|
||||
* Sorting of the lag history
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_GAIN_sort_lag(Word16 array[], Word16 n)
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
D_GAIN_insert_lag(array, i, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_lag_concealment_init
|
||||
*
|
||||
* Parameters:
|
||||
* lag_hist O: pitch lag history
|
||||
*
|
||||
* Function:
|
||||
* Initialise lag history to 64
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_lag_concealment_init(Word16 lag_hist[])
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
for(i = 0; i < L_LTPHIST; i++)
|
||||
{
|
||||
lag_hist[i] = 64;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_lag_concealment
|
||||
*
|
||||
* Parameters:
|
||||
* gain_hist I: gain history
|
||||
* lag_hist I: pitch lag history
|
||||
* T0 O: current lag
|
||||
* old_T0 I: previous lag
|
||||
* seed I/O: seed for random
|
||||
* unusable_frame I: lost frame
|
||||
*
|
||||
* Function:
|
||||
* Concealment of LTP lags during bad frames
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_lag_concealment(Word16 gain_hist[], Word16 lag_hist[],
|
||||
Word32 *T0, Word16 *old_T0, Word16 *seed,
|
||||
Word16 unusable_frame)
|
||||
{
|
||||
Word32 i, lagDif, tmp, tmp2, D2, meanLag = 0;
|
||||
Word16 lag_hist2[L_LTPHIST] = {0};
|
||||
Word16 maxLag, minLag, lastLag;
|
||||
Word16 minGain, lastGain, secLastGain;
|
||||
Word16 D;
|
||||
|
||||
/*
|
||||
* Is lag index such that it can be aplied directly
|
||||
* or does it has to be subtituted
|
||||
*/
|
||||
lastGain = gain_hist[4];
|
||||
secLastGain = gain_hist[3];
|
||||
lastLag = lag_hist[0];
|
||||
|
||||
/* SMALLEST history lag */
|
||||
minLag = lag_hist[0];
|
||||
|
||||
for(i = 1; i < L_LTPHIST; i++)
|
||||
{
|
||||
if(lag_hist[i] < minLag)
|
||||
{
|
||||
minLag = lag_hist[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* BIGGEST history lag */
|
||||
maxLag = lag_hist[0];
|
||||
|
||||
for(i = 1; i < L_LTPHIST; i++)
|
||||
{
|
||||
if(lag_hist[i] > maxLag)
|
||||
{
|
||||
maxLag = lag_hist[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* SMALLEST history gain */
|
||||
minGain = gain_hist[0];
|
||||
|
||||
for(i = 1; i < L_LTPHIST; i++)
|
||||
{
|
||||
if(gain_hist[i] < minGain)
|
||||
{
|
||||
minGain = gain_hist[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Difference between MAX and MIN lag */
|
||||
lagDif = maxLag - minLag;
|
||||
|
||||
if(unusable_frame != 0)
|
||||
{
|
||||
/*
|
||||
* LTP-lag for RX_SPEECH_LOST
|
||||
* Recognition of the LTP-history
|
||||
*/
|
||||
if((minGain > 8192) & (lagDif < 10))
|
||||
{
|
||||
*T0 = *old_T0;
|
||||
}
|
||||
else if((lastGain > 8192) && (secLastGain > 8192))
|
||||
{
|
||||
*T0 = lag_hist[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* SORT
|
||||
* The sorting of the lag history
|
||||
*/
|
||||
for(i = 0; i < L_LTPHIST; i++)
|
||||
{
|
||||
lag_hist2[i] = lag_hist[i];
|
||||
}
|
||||
D_GAIN_sort_lag(lag_hist2, 5);
|
||||
|
||||
/*
|
||||
* Lag is weighted towards bigger lags
|
||||
* and random variation is added
|
||||
*/
|
||||
lagDif = (lag_hist2[4] - lag_hist2[2]);
|
||||
|
||||
if(lagDif > 40)
|
||||
{
|
||||
lagDif = 40;
|
||||
}
|
||||
|
||||
D = D_UTIL_random(seed); /* D={-1, ...,1} */
|
||||
|
||||
/* D2={-lagDif/2..lagDif/2} */
|
||||
tmp = lagDif >> 1;
|
||||
D2 = (tmp * D) >> 15;
|
||||
tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
|
||||
*T0 = ((tmp * ONE_PER_3) >> 15) + D2;
|
||||
}
|
||||
|
||||
/* New lag is not allowed to be bigger or smaller than last lag values */
|
||||
if(*T0 > maxLag)
|
||||
{
|
||||
*T0 = maxLag;
|
||||
}
|
||||
|
||||
if(*T0 < minLag)
|
||||
{
|
||||
*T0 = minLag;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* LTP-lag for RX_BAD_FRAME
|
||||
* MEAN lag
|
||||
*/
|
||||
meanLag = 0;
|
||||
|
||||
for(i = 0; i < L_LTPHIST; i++)
|
||||
{
|
||||
meanLag = meanLag + lag_hist[i];
|
||||
}
|
||||
|
||||
meanLag = (meanLag * ONE_PER_LTPHIST) >> 15;
|
||||
tmp = *T0 - maxLag;
|
||||
tmp2 = *T0 - lastLag;
|
||||
|
||||
if((lagDif < 10) & (*T0 > (minLag - 5)) & (tmp < 5))
|
||||
{
|
||||
*T0 = *T0;
|
||||
}
|
||||
else if((lastGain > 8192) & (secLastGain > 8192) & ((tmp2 > - 10)
|
||||
& (tmp2 < 10)))
|
||||
{
|
||||
*T0 = *T0;
|
||||
}
|
||||
else if((minGain < 6554) & (lastGain == minGain) & ((*T0 > minLag)
|
||||
& (*T0 < maxLag)))
|
||||
{
|
||||
*T0 = *T0;
|
||||
}
|
||||
else if((lagDif < 70) & (*T0 > minLag) & (*T0 < maxLag))
|
||||
{
|
||||
*T0 = *T0;
|
||||
}
|
||||
else if((*T0 > meanLag) & (*T0 < maxLag))
|
||||
{
|
||||
*T0 = *T0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((minGain > 8192) & (lagDif < 10))
|
||||
{
|
||||
*T0 = lag_hist[0];
|
||||
}
|
||||
else if((lastGain > 8192) & (secLastGain > 8192))
|
||||
{
|
||||
*T0 = lag_hist[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* SORT
|
||||
* The sorting of the lag history
|
||||
*/
|
||||
for(i = 0; i < L_LTPHIST; i++)
|
||||
{
|
||||
lag_hist2[i] = lag_hist[i];
|
||||
}
|
||||
|
||||
D_GAIN_sort_lag(lag_hist2, 5);
|
||||
|
||||
/*
|
||||
* Lag is weighted towards bigger lags
|
||||
* and random variation is added
|
||||
*/
|
||||
lagDif = lag_hist2[4] - lag_hist2[2];
|
||||
|
||||
if(lagDif > 40)
|
||||
{
|
||||
lagDif = 40;
|
||||
}
|
||||
|
||||
D = D_UTIL_random(seed); /* D={-1,.., 1} */
|
||||
|
||||
/* D2={-lagDif/2..lagDif/2} */
|
||||
tmp = lagDif >> 1;
|
||||
D2 = (tmp * D) >> 15;
|
||||
tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
|
||||
*T0 = ((tmp * ONE_PER_3) >> 15) + D2;
|
||||
}
|
||||
|
||||
/*
|
||||
* New lag is not allowed to be bigger or
|
||||
* smaller than last lag values
|
||||
*/
|
||||
if(*T0 > maxLag)
|
||||
{
|
||||
*T0 = maxLag;
|
||||
}
|
||||
|
||||
if(*T0 < minLag)
|
||||
{
|
||||
*T0 = minLag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_adaptive_codebook_excitation
|
||||
*
|
||||
* Parameters:
|
||||
* exc I/O: excitation buffer
|
||||
* T0 I: integer pitch lag
|
||||
* frac I: fraction of lag
|
||||
*
|
||||
* Function:
|
||||
* Compute the result of Word32 term prediction with fractional
|
||||
* interpolation of resolution 1/4.
|
||||
*
|
||||
* Returns:
|
||||
* interpolated signal (adaptive codebook excitation)
|
||||
*/
|
||||
void D_GAIN_adaptive_codebook_excitation(Word16 exc[], Word32 T0, Word32 frac)
|
||||
{
|
||||
Word32 i, j, k, sum;
|
||||
Word16 *x;
|
||||
|
||||
x = &exc[ - T0];
|
||||
frac = -(frac);
|
||||
|
||||
if(frac < 0)
|
||||
{
|
||||
frac = (frac + UP_SAMP);
|
||||
x--;
|
||||
}
|
||||
x = x - L_INTERPOL2 + 1;
|
||||
|
||||
for(j = 0; j < L_SUBFR + 1; j++)
|
||||
{
|
||||
sum = 0L;
|
||||
|
||||
for(i = 0, k = ((UP_SAMP - 1) - frac); i < 2 * L_INTERPOL2; i++,
|
||||
k += UP_SAMP)
|
||||
{
|
||||
sum += x[i] * D_ROM_inter4_2[k];
|
||||
}
|
||||
sum = (sum + 0x2000) >> 14;
|
||||
|
||||
exc[j] = D_UTIL_saturate(sum);
|
||||
|
||||
x++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_pitch_sharpening
|
||||
*
|
||||
* Parameters:
|
||||
* x I/O: impulse response (or algebraic code)
|
||||
* pit_lag I: pitch lag
|
||||
* sharp I: (Q15) pitch sharpening factor
|
||||
*
|
||||
* Function:
|
||||
* Performs Pitch sharpening routine for one subframe.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_GAIN_pitch_sharpening(Word16 *x, Word32 pit_lag, Word16 sharp)
|
||||
{
|
||||
Word32 i;
|
||||
Word32 tmp;
|
||||
|
||||
for(i = pit_lag; i < L_SUBFR; i++)
|
||||
{
|
||||
tmp = x[i] << 15;
|
||||
tmp += x[i - pit_lag] * sharp;
|
||||
x[i] = (Word16)((tmp + 0x4000) >> 15);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_GAIN_find_voice_factor
|
||||
*
|
||||
* Parameters:
|
||||
* exc I: pitch excitation
|
||||
* Q_exc I: exc format
|
||||
* gain_pit I: (Q14) gain of pitch
|
||||
* code I: (Q9) fixed codebook excitation
|
||||
* gain_code I: (Q0) gain of code
|
||||
* L_subfr I: subframe length
|
||||
*
|
||||
* Function:
|
||||
* Find the voicing factor.
|
||||
*
|
||||
* Returns:
|
||||
* (Q15) 1=voice to -1=unvoiced
|
||||
*/
|
||||
Word16 D_GAIN_find_voice_factor(Word16 exc[], Word16 Q_exc,
|
||||
Word16 gain_pit, Word16 code[],
|
||||
Word16 gain_code, Word16 L_subfr)
|
||||
{
|
||||
|
||||
Word32 tmp, ener1, ener2, i;
|
||||
Word16 exp, exp1, exp2;
|
||||
|
||||
ener1 = (D_UTIL_dot_product12(exc, exc, L_subfr, &exp1)) >> 16;
|
||||
exp1 = (Word16)(exp1 - (Q_exc + Q_exc));
|
||||
tmp = (gain_pit * gain_pit) << 1;
|
||||
exp = D_UTIL_norm_l(tmp);
|
||||
tmp = (tmp << exp) >> 16;
|
||||
ener1 = (ener1 * tmp) >> 15;
|
||||
exp1 = (Word16)((exp1 - exp) - 10); /* 10 -> gain_pit Q14 to Q9 */
|
||||
ener2 = D_UTIL_dot_product12(code, code, L_subfr, &exp2) >> 16;
|
||||
exp = D_UTIL_norm_s(gain_code);
|
||||
tmp = gain_code << exp;
|
||||
tmp = (tmp * tmp) >> 15;
|
||||
ener2 = (ener2 * tmp) >> 15;
|
||||
exp2 = (Word16)(exp2 - (exp << 1));
|
||||
i = exp1 - exp2;
|
||||
|
||||
if(i >= 0)
|
||||
{
|
||||
ener1 = ener1 >> 1;
|
||||
ener2 = ener2 >> (i + 1);
|
||||
}
|
||||
else if(i > (-16))
|
||||
{
|
||||
ener1 = ener1 >> (1 - i);
|
||||
ener2 = ener2 >> 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ener1 = 0;
|
||||
ener2 = ener2 >> 1;
|
||||
}
|
||||
|
||||
tmp = ener1 - ener2;
|
||||
ener1 = (ener1 + ener2) + 1;
|
||||
tmp = (tmp << 15) / ener1;
|
||||
|
||||
return((Word16)tmp);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_GAIN_H
|
||||
#define DEC_GAIN_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
void D_GAIN_init(Word16 *mem);
|
||||
void D_GAIN_decode(Word16 index, Word16 nbits, Word16 code[], Word16 *gain_pit,
|
||||
Word32 *gain_cod, Word16 bfi, Word16 prev_bfi,
|
||||
Word16 state, Word16 unusable_frame, Word16 vad_hist,
|
||||
Word16 *mem);
|
||||
void D_GAIN_adaptive_control(Word16 *sig_in, Word16 *sig_out, Word16 l_trm);
|
||||
void D_GAIN_lag_concealment_init(Word16 lag_hist[]);
|
||||
void D_GAIN_lag_concealment(Word16 gain_hist[], Word16 lag_hist[], Word32 *T0,
|
||||
Word16 *old_T0, Word16 *seed,
|
||||
Word16 unusable_frame);
|
||||
void D_GAIN_adaptive_codebook_excitation(Word16 exc[], Word32 T0, Word32 frac);
|
||||
void D_GAIN_pitch_sharpening(Word16 *x, Word32 pit_lag, Word16 sharp);
|
||||
Word16 D_GAIN_find_voice_factor(Word16 exc[], Word16 Q_exc, Word16 gain_pit,
|
||||
Word16 code[], Word16 gain_code,
|
||||
Word16 L_subfr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,959 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "dec_if.h"
|
||||
#include "if_rom.h"
|
||||
#include "dec.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
#define L_FRAME16k 320 /* Frame size at 16kHz */
|
||||
#define MODE_7k 0 /* modes */
|
||||
#define MODE_9k 1
|
||||
#define MODE_12k 2
|
||||
#define MODE_14k 3
|
||||
#define MODE_16k 4
|
||||
#define MODE_18k 5
|
||||
#define MODE_20k 6
|
||||
#define MODE_23k 7
|
||||
#define MODE_24k 8
|
||||
#define MRDTX 9
|
||||
#define NUM_OF_MODES 10
|
||||
#define LOST_FRAME 14
|
||||
#define MRNO_DATA 15
|
||||
#define EHF_MASK (Word16)0x0008 /* homing frame pattern */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Word16 reset_flag_old; /* previous was homing frame */
|
||||
Word16 prev_ft; /* previous frame type */
|
||||
Word16 prev_mode; /* previous mode */
|
||||
void *decoder_state; /* Points decoder state */
|
||||
} WB_dec_if_state;
|
||||
|
||||
Word16 nb_of_param_first[NUM_OF_SPMODES]=
|
||||
{
|
||||
9, 14, 15,
|
||||
15, 15, 19,
|
||||
19, 19, 19
|
||||
};
|
||||
|
||||
extern const Word16 mode_7k[];
|
||||
extern const Word16 mode_9k[];
|
||||
extern const Word16 mode_12k[];
|
||||
extern const Word16 mode_14k[];
|
||||
extern const Word16 mode_16k[];
|
||||
extern const Word16 mode_18k[];
|
||||
extern const Word16 mode_20k[];
|
||||
extern const Word16 mode_23k[];
|
||||
extern const Word16 mode_24k[];
|
||||
extern const Word16 mode_DTX[];
|
||||
|
||||
extern const Word16 nb_of_param[];
|
||||
|
||||
extern const Word16 dfh_M7k[];
|
||||
extern const Word16 dfh_M9k[];
|
||||
extern const Word16 dfh_M12k[];
|
||||
extern const Word16 dfh_M14k[];
|
||||
extern const Word16 dfh_M16k[];
|
||||
extern const Word16 dfh_M18k[];
|
||||
extern const Word16 dfh_M20k[];
|
||||
extern const Word16 dfh_M23k[];
|
||||
extern const Word16 dfh_M24k[];
|
||||
|
||||
/* overall table with the parameters of the
|
||||
decoder homing frames for all modes */
|
||||
|
||||
extern const Word16 *dhf[10];
|
||||
|
||||
/*
|
||||
* Decoder_Interface_Homing_Frame_test
|
||||
*
|
||||
* Parameters:
|
||||
* input_frame I: input parameters
|
||||
* mode I: speech mode
|
||||
*
|
||||
* Function:
|
||||
* Check parameters for matching homing frame
|
||||
*
|
||||
* Returns:
|
||||
* If homing frame
|
||||
*/
|
||||
Word16 D_IF_homing_frame_test(Word16 input_frame[], Word16 mode)
|
||||
{
|
||||
|
||||
if (mode != MODE_24k)
|
||||
{
|
||||
/* perform test for COMPLETE parameter frame */
|
||||
return (Word16)!memcmp(input_frame, dhf[mode], nb_of_param[mode] * sizeof(Word16));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* discard high-band energy */
|
||||
return (Word16)!(
|
||||
(memcmp(input_frame, dhf[MODE_24k], 19 * sizeof(Word16))) |
|
||||
(memcmp(input_frame + 20, dhf[MODE_24k] + 20, 11 * sizeof(Word16))) |
|
||||
(memcmp(input_frame + 32, dhf[MODE_24k] + 32, 11 * sizeof(Word16))) |
|
||||
(memcmp(input_frame + 44, dhf[MODE_24k] + 44, 11 * sizeof(Word16))) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Word16 D_IF_homing_frame_test_first(Word16 input_frame[], Word16 mode)
|
||||
{
|
||||
/* perform test for FIRST SUBFRAME of parameter frame ONLY */
|
||||
return (Word16)!memcmp(input_frame, dhf[mode], nb_of_param_first[mode] * sizeof(Word16));
|
||||
}
|
||||
|
||||
#ifdef IF2
|
||||
/*
|
||||
* D_IF_conversion
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* param O: AMR parameters
|
||||
* stream I: input bitstream
|
||||
* frame_type O: frame type
|
||||
* speech_mode O: speech mode in DTX
|
||||
* fqi O: frame quality indicator
|
||||
*
|
||||
* Function:
|
||||
* Unpacks IF2 octet stream
|
||||
*
|
||||
* Returns:
|
||||
* mode used mode
|
||||
*/
|
||||
Word16 D_IF_conversion(Word16 *param, UWord8 *stream, UWord8 *frame_type,
|
||||
Word16 *speech_mode, Word16 *fqi)
|
||||
{
|
||||
Word32 mode;
|
||||
Word32 j;
|
||||
Word16 const *mask;
|
||||
|
||||
memset(param, 0, PRMNO_24k << 1);
|
||||
mode = *stream >> 4;
|
||||
*fqi = (Word16)((*stream >> 3) & 0x1);
|
||||
*stream <<= (HEADER_SIZE - 1);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MRDTX:
|
||||
mask = mode_DTX;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_SID; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
/* get SID type bit */
|
||||
|
||||
*frame_type = RX_SID_FIRST;
|
||||
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
*frame_type = RX_SID_UPDATE;
|
||||
}
|
||||
|
||||
*stream <<= 1;
|
||||
|
||||
/* speech mode indicator */
|
||||
*speech_mode = (Word16)(*stream >> 4);
|
||||
break;
|
||||
|
||||
case MRNO_DATA:
|
||||
*frame_type = RX_NO_DATA;
|
||||
break;
|
||||
|
||||
case LOST_FRAME:
|
||||
*frame_type = RX_SPEECH_LOST;
|
||||
break;
|
||||
|
||||
case MODE_7k:
|
||||
mask = mode_7k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_7k; j++)
|
||||
{
|
||||
if ( *stream & 0x80 )
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_9k:
|
||||
mask = mode_9k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_9k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_12k:
|
||||
mask = mode_12k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_12k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_14k:
|
||||
mask = mode_14k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_14k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_16k:
|
||||
mask = mode_16k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_16k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_18k:
|
||||
mask = mode_18k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_18k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_20k:
|
||||
mask = mode_20k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_20k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_23k:
|
||||
mask = mode_23k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_23k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_24k:
|
||||
mask = mode_24k;
|
||||
|
||||
for (j = HEADER_SIZE; j < T_NBBITS_24k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
default:
|
||||
*frame_type = RX_SPEECH_LOST;
|
||||
*fqi = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (*fqi == 0)
|
||||
{
|
||||
if (*frame_type == RX_SPEECH_GOOD)
|
||||
{
|
||||
*frame_type = RX_SPEECH_BAD;
|
||||
}
|
||||
if ((*frame_type == RX_SID_FIRST) | (*frame_type == RX_SID_UPDATE))
|
||||
{
|
||||
*frame_type = RX_SID_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
return (Word16)mode;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* D_IF_mms_conversion
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* param O: AMR parameters
|
||||
* stream I: input bitstream
|
||||
* frame_type O: frame type
|
||||
* speech_mode O: speech mode in DTX
|
||||
* fqi O: frame quality indicator
|
||||
*
|
||||
* Function:
|
||||
* Unpacks MMS formatted octet stream (see RFC 3267, section 5.3)
|
||||
*
|
||||
* Returns:
|
||||
* mode used mode
|
||||
*/
|
||||
Word16 D_IF_mms_conversion(Word16 *param, UWord8 *stream, UWord8 *frame_type,
|
||||
Word16 *speech_mode, Word16 *fqi)
|
||||
{
|
||||
Word32 mode;
|
||||
Word32 j;
|
||||
Word16 const *mask;
|
||||
|
||||
memset(param, 0, PRMNO_24k << 1);
|
||||
|
||||
*fqi = (Word16)((*stream >> 2) & 0x01);
|
||||
mode = (Word32)((*stream >> 3) & 0x0F);
|
||||
|
||||
stream++;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MRDTX:
|
||||
mask = mode_DTX;
|
||||
|
||||
for (j = 1; j <= NBBITS_SID; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
/* get SID type bit */
|
||||
|
||||
*frame_type = RX_SID_FIRST;
|
||||
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
*frame_type = RX_SID_UPDATE;
|
||||
}
|
||||
|
||||
*stream <<= 1;
|
||||
|
||||
/* speech mode indicator */
|
||||
*speech_mode = (Word16)(*stream >> 4);
|
||||
break;
|
||||
|
||||
case MRNO_DATA:
|
||||
*frame_type = RX_NO_DATA;
|
||||
break;
|
||||
|
||||
case LOST_FRAME:
|
||||
*frame_type = RX_SPEECH_LOST;
|
||||
break;
|
||||
|
||||
case MODE_7k:
|
||||
mask = mode_7k;
|
||||
|
||||
for (j = 1; j <= NBBITS_7k; j++)
|
||||
{
|
||||
if ( *stream & 0x80 )
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_9k:
|
||||
mask = mode_9k;
|
||||
|
||||
for (j = 1; j <= NBBITS_9k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_12k:
|
||||
mask = mode_12k;
|
||||
|
||||
for (j = 1; j <= NBBITS_12k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_14k:
|
||||
mask = mode_14k;
|
||||
|
||||
for (j = 1; j <= NBBITS_14k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if ( j % 8 )
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_16k:
|
||||
mask = mode_16k;
|
||||
|
||||
for (j = 1; j <= NBBITS_16k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_18k:
|
||||
mask = mode_18k;
|
||||
|
||||
for (j = 1; j <= NBBITS_18k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_20k:
|
||||
mask = mode_20k;
|
||||
|
||||
for (j = 1; j <= NBBITS_20k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_23k:
|
||||
mask = mode_23k;
|
||||
|
||||
for (j = 1; j <= NBBITS_23k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
case MODE_24k:
|
||||
mask = mode_24k;
|
||||
|
||||
for (j = 1; j <= NBBITS_24k; j++)
|
||||
{
|
||||
if (*stream & 0x80)
|
||||
{
|
||||
param[*mask] = (Word16)(param[*mask] + *(mask + 1));
|
||||
}
|
||||
|
||||
mask += 2;
|
||||
|
||||
if (j % 8)
|
||||
{
|
||||
*stream <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*frame_type = RX_SPEECH_GOOD;
|
||||
break;
|
||||
|
||||
default:
|
||||
*frame_type = RX_SPEECH_LOST;
|
||||
*fqi = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (*fqi == 0)
|
||||
{
|
||||
if (*frame_type == RX_SPEECH_GOOD)
|
||||
{
|
||||
*frame_type = RX_SPEECH_BAD;
|
||||
}
|
||||
if ((*frame_type == RX_SID_FIRST) | (*frame_type == RX_SID_UPDATE))
|
||||
{
|
||||
*frame_type = RX_SID_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
return (Word16)mode;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* D_IF_decode
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* st B: pointer to state structure
|
||||
* bits I: bitstream form the encoder
|
||||
* synth O: decoder output
|
||||
* lfi I: lost frame indicator
|
||||
* _good_frame, _bad_frame, _lost_frame, _no_frame
|
||||
*
|
||||
* Function:
|
||||
* Decoding one frame of speech. Lost frame indicator can be used
|
||||
* to inform encoder about the problems in the received frame.
|
||||
* _good_frame:good speech or sid frame is received.
|
||||
* _bad_frame: frame with possible bit errors
|
||||
* _lost_frame:speech of sid frame is lost in transmission
|
||||
* _no_frame: indicates non-received frames in dtx-operation
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
void D_IF_decode( void *st, UWord8 *bits, Word16 *synth, Word32 lfi)
|
||||
{
|
||||
Word32 i;
|
||||
Word16 mode = 0; /* AMR mode */
|
||||
Word16 speech_mode = MODE_7k; /* speech mode */
|
||||
Word16 fqi; /* frame quality indicator */
|
||||
|
||||
Word16 prm[PRMNO_24k]; /* AMR parameters */
|
||||
|
||||
UWord8 frame_type; /* frame type */
|
||||
Word16 reset_flag = 0; /* reset flag */
|
||||
WB_dec_if_state * s; /* pointer to structure */
|
||||
|
||||
s = (WB_dec_if_state*)st;
|
||||
|
||||
/* bits -> param, if needed */
|
||||
if ((lfi == _good_frame) | (lfi == _bad_frame))
|
||||
{
|
||||
/* add fqi data */
|
||||
#ifdef IF2
|
||||
*bits = (UWord8)((Word32)*bits & ~(lfi << 3));
|
||||
#else
|
||||
*bits = (UWord8)((Word32)*bits & ~(lfi << 2));
|
||||
#endif
|
||||
/*
|
||||
* extract mode information and frame_type,
|
||||
* octets to parameters
|
||||
*/
|
||||
#ifdef IF2
|
||||
mode = D_IF_conversion( prm, bits, &frame_type, &speech_mode, &fqi);
|
||||
#else
|
||||
mode = D_IF_mms_conversion( prm, bits, &frame_type, &speech_mode, &fqi);
|
||||
#endif
|
||||
|
||||
}
|
||||
else if (lfi == _no_frame)
|
||||
{
|
||||
frame_type = RX_NO_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_type = RX_SPEECH_LOST;
|
||||
}
|
||||
|
||||
/*
|
||||
* if no mode information
|
||||
* guess one from the previous frame
|
||||
*/
|
||||
if ((frame_type == RX_SPEECH_LOST) | (frame_type == RX_NO_DATA))
|
||||
{
|
||||
mode = s->prev_mode;
|
||||
}
|
||||
|
||||
if (mode == MRDTX)
|
||||
{
|
||||
mode = speech_mode;
|
||||
}
|
||||
|
||||
/* if homed: check if this frame is another homing frame */
|
||||
if (s->reset_flag_old == 1)
|
||||
{
|
||||
/* only check until end of first subframe */
|
||||
reset_flag = D_IF_homing_frame_test_first(prm, mode);
|
||||
}
|
||||
|
||||
/* produce encoder homing frame if homed & input=decoder homing frame */
|
||||
if ((reset_flag != 0) && (s->reset_flag_old != 0))
|
||||
{
|
||||
for (i = 0; i < L_FRAME16k; i++)
|
||||
{
|
||||
synth[i] = EHF_MASK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D_MAIN_decode(mode, prm, synth, s->decoder_state, frame_type);
|
||||
}
|
||||
|
||||
for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */
|
||||
{
|
||||
synth[i] = (Word16) (synth[i] & 0xfffC);
|
||||
}
|
||||
|
||||
/* if not homed: check whether current frame is a homing frame */
|
||||
if ((s->reset_flag_old == 0) & (mode < 9))
|
||||
{
|
||||
/* check whole frame */
|
||||
reset_flag = D_IF_homing_frame_test(prm, mode);
|
||||
}
|
||||
/* reset decoder if current frame is a homing frame */
|
||||
if (reset_flag != 0)
|
||||
{
|
||||
D_MAIN_reset(s->decoder_state, 1);
|
||||
}
|
||||
s->reset_flag_old = reset_flag;
|
||||
|
||||
s->prev_ft = frame_type;
|
||||
s->prev_mode = mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* D_IF_reset
|
||||
*
|
||||
* Parameters:
|
||||
* st O: state struct
|
||||
*
|
||||
* Function:
|
||||
* Reset homing frame counter
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_IF_reset(WB_dec_if_state *st)
|
||||
{
|
||||
st->reset_flag_old = 1;
|
||||
st->prev_ft = RX_SPEECH_GOOD;
|
||||
st->prev_mode = MODE_7k; /* minimum bitrate */
|
||||
}
|
||||
|
||||
/*
|
||||
* D_IF_init
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* Function:
|
||||
* Allocates state memory and initializes state memory
|
||||
*
|
||||
* Returns:
|
||||
* pointer to encoder interface structure
|
||||
*/
|
||||
void *D_IF_init( void)
|
||||
{
|
||||
WB_dec_if_state *s = NULL;
|
||||
|
||||
/* allocate memory */
|
||||
if ((s = (WB_dec_if_state*) malloc(sizeof(WB_dec_if_state))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D_MAIN_init(&(s->decoder_state));
|
||||
if (s->decoder_state == NULL)
|
||||
{
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D_IF_reset(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* D_IF_exit
|
||||
*
|
||||
* Parameters:
|
||||
* state I: state structure
|
||||
*
|
||||
* Function:
|
||||
* The memory used for state memory is freed
|
||||
*
|
||||
* Returns:
|
||||
* Void
|
||||
*/
|
||||
void D_IF_exit(void *state)
|
||||
{
|
||||
WB_dec_if_state *s;
|
||||
|
||||
s = (WB_dec_if_state *)state;
|
||||
|
||||
/* free memory */
|
||||
D_MAIN_close(&s->decoder_state);
|
||||
free(s);
|
||||
state = NULL;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_IF_H
|
||||
#define DEC_IF_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
#define NB_SERIAL_MAX 61 /* max serial size */
|
||||
#define L_FRAME16k 320 /* Frame size at 16kHz */
|
||||
|
||||
#define _good_frame 0
|
||||
#define _bad_frame 1
|
||||
#define _lost_frame 2
|
||||
#define _no_frame 3
|
||||
|
||||
void D_IF_decode(void *st, UWord8 *bits, Word16 *synth, Word32 bfi);
|
||||
void * D_IF_init(void);
|
||||
void D_IF_exit(void *state);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,874 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "typedef.h"
|
||||
#include "dec_util.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
#define M 16 /* Order of LP filter */
|
||||
#define MP1 (M + 1)
|
||||
#define M16k 20
|
||||
#define NC16k (M16k / 2)
|
||||
#define MU 10923 /* Prediction factor (1.0/3.0) in Q15 */
|
||||
#define L_MEANBUF 3
|
||||
#define ALPHA 29491 /* 0. 9 in Q15 */
|
||||
#define ONE_ALPHA (32768-ALPHA) /* (1.0 - ALPHA) in Q15 */
|
||||
#define ORDER 16 /* order of linear prediction filter */
|
||||
#define ISF_GAP 128 /* 50 Hz */
|
||||
#define INV_LENGTH 2731 /* 1/12 */
|
||||
|
||||
extern const Word16 D_ROM_dico1_isf[];
|
||||
extern const Word16 D_ROM_dico2_isf[];
|
||||
extern const Word16 D_ROM_dico21_isf_36b[];
|
||||
extern const Word16 D_ROM_dico22_isf_36b[];
|
||||
extern const Word16 D_ROM_dico23_isf_36b[];
|
||||
extern const Word16 D_ROM_dico21_isf[];
|
||||
extern const Word16 D_ROM_dico22_isf[];
|
||||
extern const Word16 D_ROM_dico23_isf[];
|
||||
extern const Word16 D_ROM_dico24_isf[];
|
||||
extern const Word16 D_ROM_dico25_isf[];
|
||||
extern const Word16 D_ROM_dico1_isf_noise[];
|
||||
extern const Word16 D_ROM_dico2_isf_noise[];
|
||||
extern const Word16 D_ROM_dico3_isf_noise[];
|
||||
extern const Word16 D_ROM_dico4_isf_noise[];
|
||||
extern const Word16 D_ROM_dico5_isf_noise[];
|
||||
extern const Word16 D_ROM_mean_isf[];
|
||||
extern const Word16 D_ROM_mean_isf_noise[];
|
||||
extern const Word16 D_ROM_cos[];
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_reorder
|
||||
*
|
||||
* Parameters:
|
||||
* isf I/O: vector of isfs
|
||||
* min_dist I: quantized ISFs (in frequency domain)
|
||||
* n I: LPC order
|
||||
*
|
||||
* Function:
|
||||
* To make sure that the isfs are properly order and to keep a certain
|
||||
* minimum distance between consecutive isfs.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_LPC_isf_reorder(Word16 *isf, Word16 min_dist, Word16 n)
|
||||
{
|
||||
Word32 i, isf_min;
|
||||
|
||||
isf_min = min_dist;
|
||||
|
||||
for(i = 0; i < n - 1; i++)
|
||||
{
|
||||
if(isf[i] < isf_min)
|
||||
{
|
||||
isf[i] = (Word16)isf_min;
|
||||
}
|
||||
isf_min = isf[i] + min_dist;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_noise_d
|
||||
*
|
||||
* Parameters:
|
||||
* indice I: indices of the selected codebook entries
|
||||
* isf_q O: quantized ISFs (in frequency domain)
|
||||
*
|
||||
* Function:
|
||||
* Decoding of ISF parameters
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isf_noise_d(Word16 *indice, Word16 *isf_q)
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
for(i = 0; i < 2; i++)
|
||||
{
|
||||
isf_q[i] = D_ROM_dico1_isf_noise[indice[0] * 2 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i + 2] = D_ROM_dico2_isf_noise[indice[1] * 3 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i + 5] = D_ROM_dico3_isf_noise[indice[2] * 3 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
isf_q[i + 8] = D_ROM_dico4_isf_noise[indice[3] * 4 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
isf_q[i + 12] = D_ROM_dico5_isf_noise[indice[4] * 4 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
isf_q[i] = (Word16)(isf_q[i]+ D_ROM_mean_isf_noise[i]);
|
||||
}
|
||||
|
||||
D_LPC_isf_reorder(isf_q, ISF_GAP, ORDER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_isp_conversion
|
||||
*
|
||||
* Parameters:
|
||||
* isp O: (Q15) isp[m] (range: -1<=val<1)
|
||||
* isf I: (Q15) isf[m] normalized (range: 0.0 <= val <= 0.5)
|
||||
* m I: LPC order
|
||||
*
|
||||
* Function:
|
||||
* Transformation isf to isp
|
||||
*
|
||||
* ISP are immitance spectral pair in cosine domain (-1 to 1).
|
||||
* ISF are immitance spectral pair in frequency domain (0 to 6400).
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isf_isp_conversion(Word16 isf[], Word16 isp[], Word16 m)
|
||||
{
|
||||
Word32 i, ind, offset, tmp;
|
||||
|
||||
for(i = 0; i < m - 1; i++)
|
||||
{
|
||||
isp[i] = isf[i];
|
||||
}
|
||||
isp[m - 1] = (Word16)(isf[m - 1] << 1);
|
||||
|
||||
for(i = 0; i < m; i++)
|
||||
{
|
||||
ind = isp[i] >> 7; /* ind = b7-b15 of isf[i] */
|
||||
offset = isp[i] & 0x007f; /* offset = b0-b6 of isf[i] */
|
||||
|
||||
/* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */
|
||||
tmp = (D_ROM_cos[ind + 1] - D_ROM_cos[ind]) * offset;
|
||||
isp[i] = (Word16)(D_ROM_cos[ind] + (tmp >> 7));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isp_pol_get
|
||||
*
|
||||
* Parameters:
|
||||
* isp I: Immitance spectral pairs (cosine domaine)
|
||||
* f O: the coefficients of F1 or F2
|
||||
* n I: no of coefficients (m/2)
|
||||
* k16 I: 16k flag
|
||||
*
|
||||
* Function:
|
||||
* Find the polynomial F1(z) or F2(z) from the ISPs.
|
||||
* This is performed by expanding the product polynomials:
|
||||
*
|
||||
* F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 )
|
||||
* i=0,2,4,6,8
|
||||
* F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 )
|
||||
* i=1,3,5,7
|
||||
*
|
||||
* where isp_i are the ISPs in the cosine domain.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
static void D_LPC_isp_pol_get(Word16 *isp, Word32 *f, Word32 n, Word16 k16)
|
||||
{
|
||||
Word32 i, j, t0, s1, s2;
|
||||
Word16 hi, lo;
|
||||
|
||||
s1 = 8388608;
|
||||
s2 = 512;
|
||||
|
||||
if(k16)
|
||||
{
|
||||
s1 >>= 2;
|
||||
s2 >>= 2;
|
||||
}
|
||||
|
||||
/* All computation in Q23 */
|
||||
f[0] = s1; /* f[0] = 1.0; in Q23 */
|
||||
f[1] = isp[0] * (-s2); /* f[1] = -2.0*isp[0] in Q23 */
|
||||
f += 2; /* Advance f pointer */
|
||||
isp += 2; /* Advance isp pointer */
|
||||
|
||||
for(i = 2; i <= n; i++)
|
||||
{
|
||||
*f = f[ - 2];
|
||||
|
||||
for(j = 1; j < i; j++, f--)
|
||||
{
|
||||
D_UTIL_l_extract(f[- 1], &hi, &lo);
|
||||
t0 = D_UTIL_mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */
|
||||
t0 = (t0 << 1);
|
||||
*f = (*f - t0); /* *f -= t0 */
|
||||
*f = (*f + f[ - 2]); /* *f += f[-2] */
|
||||
}
|
||||
|
||||
*f = *f - (*isp * s2); /* *f -= isp << 8 */
|
||||
f += i; /* Advance f pointer */
|
||||
isp += 2; /* Advance isp pointer */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isp_a_conversion
|
||||
*
|
||||
* Parameters:
|
||||
* isp I: (Q15) Immittance spectral pairs
|
||||
* a O: (Q12) Predictor coefficients (order = M)
|
||||
* m I: order of LP filter
|
||||
*
|
||||
* Function:
|
||||
* Convert ISPs to predictor coefficients a[]
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isp_a_conversion(Word16 isp[], Word16 a[], Word32 adaptive_scaling,
|
||||
Word16 m)
|
||||
{
|
||||
Word32 j, i, nc, tmax, q, q_sug, r;
|
||||
Word32 f1[NC16k + 1], f2[NC16k];
|
||||
Word32 t0;
|
||||
Word16 hi, lo;
|
||||
|
||||
nc = m >> 1;
|
||||
|
||||
if(nc > 8)
|
||||
{
|
||||
D_LPC_isp_pol_get(&isp[0], f1, nc, 1);
|
||||
|
||||
for(i = 0; i <= nc; i++)
|
||||
{
|
||||
f1[i] = (f1[i] << 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D_LPC_isp_pol_get(&isp[0], f1, nc, 0);
|
||||
}
|
||||
|
||||
if(nc > 8)
|
||||
{
|
||||
D_LPC_isp_pol_get(&isp[1], f2, nc - 1, 1);
|
||||
|
||||
for(i = 0; i <= nc - 1; i++)
|
||||
{
|
||||
f2[i] = (f2[i] << 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D_LPC_isp_pol_get(&isp[1], f2, nc - 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply F2(z) by (1 - z^-2)
|
||||
*/
|
||||
for(i = nc - 1; i > 1; i--)
|
||||
{
|
||||
f2[i] = f2[i] - f2[i - 2]; /* f2[i] -= f2[i-2]; */
|
||||
}
|
||||
|
||||
/*
|
||||
* Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1])
|
||||
*/
|
||||
for(i = 0; i < nc; i++)
|
||||
{
|
||||
/* f1[i] *= (1.0 + isp[M-1]); */
|
||||
D_UTIL_l_extract(f1[i], &hi, &lo);
|
||||
t0 = D_UTIL_mpy_32_16(hi, lo, isp[m - 1]);
|
||||
f1[i] = f1[i] + t0;
|
||||
|
||||
/* f2[i] *= (1.0 - isp[M-1]); */
|
||||
D_UTIL_l_extract(f2[i], &hi, &lo);
|
||||
t0 = D_UTIL_mpy_32_16(hi, lo, isp[m - 1]);
|
||||
f2[i] = f2[i] - t0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A(z) = (F1(z)+F2(z))/2
|
||||
* F1(z) is symmetric and F2(z) is antisymmetric
|
||||
*/
|
||||
|
||||
/* a[0] = 1.0; */
|
||||
a[0] = 4096;
|
||||
tmax = 1;
|
||||
|
||||
for(i = 1, j = m - 1; i < nc; i++, j--)
|
||||
{
|
||||
/* a[i] = 0.5*(f1[i] + f2[i]); */
|
||||
t0 = f1[i] + f2[i]; /* f1[i] + f2[i] */
|
||||
tmax |= labs(t0);
|
||||
a[i] = (Word16)((t0 + 0x800) >> 12); /* from Q23 to Q12 and * 0.5 */
|
||||
|
||||
/* a[j] = 0.5*(f1[i] - f2[i]); */
|
||||
t0 = (f1[i] - f2[i]); /* f1[i] - f2[i] */
|
||||
tmax |= labs(t0);
|
||||
a[j] = (Word16)((t0 + 0x800) >> 12); /* from Q23 to Q12 and * 0.5 */
|
||||
}
|
||||
|
||||
/* rescale data if overflow has occured and reprocess the loop */
|
||||
|
||||
if (adaptive_scaling)
|
||||
{
|
||||
q = 4 - D_UTIL_norm_l(tmax); /* adaptive scaling enabled */
|
||||
}
|
||||
else
|
||||
{
|
||||
q = 0; /* adaptive scaling disabled */
|
||||
}
|
||||
|
||||
if (q > 0)
|
||||
{
|
||||
q_sug = 12 + q;
|
||||
r = 1 << (q_sug - 1);
|
||||
|
||||
for (i = 1, j = m - 1; i < nc; i++, j--)
|
||||
{
|
||||
/* a[i] = 0.5*(f1[i] + f2[i]); */
|
||||
t0 = f1[i] + f2[i]; /* f1[i] + f2[i] */
|
||||
a[i] = (Word16)((t0 + r) >> q_sug); /* from Q23 to Q12 and * 0.5 */
|
||||
|
||||
/* a[j] = 0.5*(f1[i] - f2[i]); */
|
||||
t0 = f1[i] - f2[i]; /* f1[i] - f2[i] */
|
||||
a[j] = (Word16)((t0 + r) >> q_sug); /* from Q23 to Q12 and * 0.5 */
|
||||
}
|
||||
a[0] = (Word16)(a[0] >> q);
|
||||
}
|
||||
else
|
||||
{
|
||||
q_sug = 12;
|
||||
r = 1 << (q_sug - 1);
|
||||
q = 0;
|
||||
}
|
||||
|
||||
/* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */
|
||||
D_UTIL_l_extract(f1[nc], &hi, &lo);
|
||||
t0 = D_UTIL_mpy_32_16(hi, lo, isp[m - 1]);
|
||||
t0 = f1[nc] + t0;
|
||||
a[nc] = (Word16)((t0 + r) >> q_sug); /* from Q23 to Q12 and * 0.5 */
|
||||
|
||||
/* a[m] = isp[m-1]; */
|
||||
a[m] = (Word16)((isp[m - 1] >> (2 + q)) + 1); /* from Q15 to Q12 */
|
||||
a[m] = (Word16)(a[m] >> 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_a_weight
|
||||
*
|
||||
* Parameters:
|
||||
* a I: LP filter coefficients
|
||||
* ap O: weighted LP filter coefficients
|
||||
* gamma I: weighting factor
|
||||
* m I: order of LP filter
|
||||
*
|
||||
* Function:
|
||||
* Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i).
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_a_weight(Word16 a[], Word16 ap[], Word16 gamma, Word16 m)
|
||||
{
|
||||
Word32 i, fac;
|
||||
|
||||
ap[0] = a[0];
|
||||
fac = gamma;
|
||||
|
||||
for(i = 1; i < m; i++)
|
||||
{
|
||||
ap[i] = (Word16)(((a[i] * fac) + 0x4000) >> 15);
|
||||
fac = ((fac * gamma) + 0x4000) >> 15;
|
||||
}
|
||||
|
||||
ap[m] = (Word16)(((a[m] * fac) + 0x4000) >> 15);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_2s3s_decode
|
||||
*
|
||||
* Parameters:
|
||||
* indice I: quantisation indices
|
||||
* isf_q O: quantised ISFs in the cosine domain
|
||||
* past_isfq I/O: past ISF quantizer
|
||||
* isfold I: past quantised ISF
|
||||
* isf_buf O: isf buffer
|
||||
* bfi I: Bad frame indicator
|
||||
*
|
||||
* Function:
|
||||
* Decoding of ISF parameters.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isf_2s3s_decode(Word16 *indice, Word16 *isf_q, Word16 *past_isfq,
|
||||
Word16 *isfold, Word16 *isf_buf, Word16 bfi)
|
||||
{
|
||||
|
||||
Word32 ref_isf[M];
|
||||
Word32 L_tmp, i, j;
|
||||
Word16 tmp;
|
||||
|
||||
if(bfi == 0) /* Good frame */
|
||||
{
|
||||
for(i = 0; i < 9; i++)
|
||||
{
|
||||
isf_q[i] = D_ROM_dico1_isf[indice[0] * 9 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 7; i++)
|
||||
{
|
||||
isf_q[i + 9] = D_ROM_dico2_isf[indice[1] * 7 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 5; i++)
|
||||
{
|
||||
isf_q[i] =
|
||||
(Word16)(isf_q[i] + D_ROM_dico21_isf_36b[indice[2] * 5 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
isf_q[i + 5] =
|
||||
(Word16)(isf_q[i + 5] + D_ROM_dico22_isf_36b[indice[3] * 4 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 7; i++)
|
||||
{
|
||||
isf_q[i + 9] =
|
||||
(Word16)(isf_q[i + 9] + D_ROM_dico23_isf_36b[indice[4] * 7 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
tmp = isf_q[i];
|
||||
isf_q[i] =
|
||||
(Word16)((tmp + D_ROM_mean_isf[i]) + ((MU * past_isfq[i]) >> 15));
|
||||
past_isfq[i] = tmp;
|
||||
}
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
for(j = (L_MEANBUF - 1); j > 0; j--)
|
||||
{
|
||||
isf_buf[j * M + i] = isf_buf[(j - 1) * M + i];
|
||||
}
|
||||
isf_buf[i] = isf_q[i];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{ /* bad frame */
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
L_tmp = D_ROM_mean_isf[i];
|
||||
|
||||
for(j = 0; j < L_MEANBUF; j++)
|
||||
{
|
||||
L_tmp = L_tmp + isf_buf[j * M + i];
|
||||
}
|
||||
ref_isf[i] = (L_tmp + 0x1) >> 2;
|
||||
}
|
||||
|
||||
/* use the past ISFs slightly shifted towards their mean */
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
isf_q[i] = (Word16)((((ALPHA * isfold[i]) >> 15) +
|
||||
((ONE_ALPHA * ref_isf[i]) >> 15)));
|
||||
}
|
||||
|
||||
/* estimate past quantized residual to be used in next frame */
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
/* predicted ISF */
|
||||
L_tmp = ref_isf[i] + ((past_isfq[i] * MU) >> 15);
|
||||
/* past_isfq[i] *= 0.5 */
|
||||
past_isfq[i] = (Word16)((isf_q[i] - L_tmp) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
D_LPC_isf_reorder(isf_q, ISF_GAP, ORDER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_2s5s_decode
|
||||
*
|
||||
* Parameters:
|
||||
* indice I: quantization indices
|
||||
* isf_q O: quantized ISFs in the cosine domain
|
||||
* past_isfq I/O: past ISF quantizer
|
||||
* isfold I: past quantized ISF
|
||||
* isf_buf O: isf buffer
|
||||
* bfi I: Bad frame indicator
|
||||
*
|
||||
* Function:
|
||||
* Decoding of ISF parameters.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isf_2s5s_decode(Word16 *indice, Word16 *isf_q, Word16 *past_isfq,
|
||||
Word16 *isfold, Word16 *isf_buf, Word16 bfi)
|
||||
{
|
||||
Word32 ref_isf[M];
|
||||
Word32 i, j, L_tmp;
|
||||
Word16 tmp;
|
||||
|
||||
if(bfi == 0) /* Good frame */
|
||||
{
|
||||
for(i = 0; i < 9; i++)
|
||||
{
|
||||
isf_q[i] = D_ROM_dico1_isf[indice[0] * 9 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 7; i++)
|
||||
{
|
||||
isf_q[i + 9] = D_ROM_dico2_isf[indice[1] * 7 + i];
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i] = (Word16)(isf_q[i] + D_ROM_dico21_isf[indice[2] * 3 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i + 3] =
|
||||
(Word16)(isf_q[i + 3] + D_ROM_dico22_isf[indice[3] * 3 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i + 6] =
|
||||
(Word16)(isf_q[i + 6] + D_ROM_dico23_isf[indice[4] * 3 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
isf_q[i + 9] =
|
||||
(Word16)(isf_q[i + 9] + D_ROM_dico24_isf[indice[5] * 3 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
isf_q[i + 12] =
|
||||
(Word16)(isf_q[i + 12] + D_ROM_dico25_isf[indice[6] * 4 + i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
tmp = isf_q[i];
|
||||
isf_q[i] =
|
||||
(Word16)((tmp + D_ROM_mean_isf[i]) + ((MU * past_isfq[i]) >> 15));
|
||||
past_isfq[i] = tmp;
|
||||
}
|
||||
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
for(j = (L_MEANBUF - 1); j > 0; j--)
|
||||
{
|
||||
isf_buf[j * M + i] = isf_buf[(j - 1) * M + i];
|
||||
}
|
||||
isf_buf[i] = isf_q[i];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{ /* bad frame */
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
L_tmp = D_ROM_mean_isf[i];
|
||||
|
||||
for(j = 0; j < L_MEANBUF; j++)
|
||||
{
|
||||
L_tmp = L_tmp + isf_buf[j * M + i];
|
||||
}
|
||||
|
||||
ref_isf[i] = (L_tmp + 0x1) >> 2;
|
||||
}
|
||||
|
||||
/* use the past ISFs slightly shifted towards their mean */
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
isf_q[i] = (Word16)(((ALPHA * isfold[i]) >> 15) +
|
||||
((ONE_ALPHA * ref_isf[i]) >> 15));
|
||||
}
|
||||
|
||||
/* estimate past quantized residual to be used in next frame */
|
||||
for(i = 0; i < ORDER; i++)
|
||||
{
|
||||
/* predicted ISF */
|
||||
L_tmp = ref_isf[i] + ((past_isfq[i] * MU) >> 15);
|
||||
/* past_isfq[i] *= 0.5 */
|
||||
past_isfq[i] = (Word16)((isf_q[i] - L_tmp) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
D_LPC_isf_reorder(isf_q, ISF_GAP, ORDER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_int_isp_find
|
||||
*
|
||||
* Parameters:
|
||||
* isp_old I: isps from past frame
|
||||
* isp_new I: isps from present frame
|
||||
* frac I: (Q15) fraction for 3 first subfr
|
||||
* Az O: LP coefficients in 4 subframes
|
||||
*
|
||||
* Function:
|
||||
* Find the interpolated ISP parameters for all subframes.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_int_isp_find(Word16 isp_old[], Word16 isp_new[],
|
||||
const Word16 frac[], Word16 Az[])
|
||||
{
|
||||
Word32 tmp, i, k, fac_old, fac_new;
|
||||
Word16 isp[M];
|
||||
|
||||
for(k = 0; k < 3; k++)
|
||||
{
|
||||
fac_new = frac[k];
|
||||
fac_old = (32767 - fac_new) + 1; /* 1.0 - fac_new */
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
tmp = isp_old[i] * fac_old;
|
||||
tmp += isp_new[i] * fac_new;
|
||||
isp[i] = (Word16)((tmp + 0x4000) >> 15);
|
||||
}
|
||||
|
||||
D_LPC_isp_a_conversion(isp, Az, 0, M);
|
||||
Az += MP1;
|
||||
}
|
||||
|
||||
/* 4th subframe: isp_new (frac=1.0) */
|
||||
D_LPC_isp_a_conversion(isp_new, Az, 0, M);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* D_LPC_isf_extrapolation
|
||||
*
|
||||
* Parameters:
|
||||
* HfIsf I/O: ISF vector
|
||||
*
|
||||
* Function:
|
||||
* Conversion of 16th-order 12.8kHz ISF vector
|
||||
* into 20th-order 16kHz ISF vector
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_LPC_isf_extrapolation(Word16 HfIsf[])
|
||||
{
|
||||
Word32 IsfDiff[M - 2];
|
||||
Word32 IsfCorr[3];
|
||||
Word32 tmp, tmp2, tmp3, mean, i;
|
||||
Word32 MaxCorr, exp, exp2, coeff;
|
||||
Word16 hi, lo;
|
||||
|
||||
HfIsf[M16k - 1] = HfIsf[M - 1];
|
||||
|
||||
/* Difference vector */
|
||||
for(i = 1; i < M - 1; i++)
|
||||
{
|
||||
IsfDiff[i - 1] = HfIsf[i] - HfIsf[i - 1];
|
||||
}
|
||||
|
||||
tmp = 0;
|
||||
|
||||
/* Mean of difference vector */
|
||||
for(i = 3; i < (M - 1); i++)
|
||||
{
|
||||
tmp = tmp + (IsfDiff[i - 1] * INV_LENGTH);
|
||||
}
|
||||
|
||||
mean = (tmp + 0x4000) >> 15;
|
||||
IsfCorr[0] = 0;
|
||||
IsfCorr[1] = 0;
|
||||
IsfCorr[2] = 0;
|
||||
tmp = 0;
|
||||
|
||||
for(i = 0; i < M - 2; i++)
|
||||
{
|
||||
if(IsfDiff[i] > tmp)
|
||||
{
|
||||
tmp = IsfDiff[i];
|
||||
}
|
||||
}
|
||||
|
||||
exp = D_UTIL_norm_s((Word16)tmp);
|
||||
|
||||
for(i = 0; i < M - 2; i++)
|
||||
{
|
||||
IsfDiff[i] = IsfDiff[i] << exp;
|
||||
}
|
||||
|
||||
mean = mean << exp;
|
||||
|
||||
for(i = 7; i < M - 2; i++)
|
||||
{
|
||||
tmp2 = IsfDiff[i] - mean;
|
||||
tmp3 = IsfDiff[i - 2] - mean;
|
||||
tmp = (tmp2 * tmp3) << 1;
|
||||
D_UTIL_l_extract(tmp, &hi, &lo);
|
||||
tmp = D_UTIL_mpy_32(hi, lo, hi, lo);
|
||||
IsfCorr[0] = (IsfCorr[0] + tmp);
|
||||
}
|
||||
|
||||
for(i = 7; i < M - 2; i++)
|
||||
{
|
||||
tmp2 = IsfDiff[i] - mean;
|
||||
tmp3 = IsfDiff[i - 3] - mean;
|
||||
tmp = (tmp2 * tmp3) << 1;
|
||||
D_UTIL_l_extract(tmp, &hi, &lo);
|
||||
tmp = D_UTIL_mpy_32(hi, lo, hi, lo);
|
||||
IsfCorr[1] = (IsfCorr[1] + tmp);
|
||||
}
|
||||
|
||||
for(i = 7; i < M - 2; i++)
|
||||
{
|
||||
tmp2 = IsfDiff[i] - mean;
|
||||
tmp3 = IsfDiff[i - 4] - mean;
|
||||
tmp = (tmp2 * tmp3) << 1;
|
||||
D_UTIL_l_extract(tmp, &hi, &lo);
|
||||
tmp = D_UTIL_mpy_32(hi, lo, hi, lo);
|
||||
IsfCorr[2] = (IsfCorr[2] + tmp);
|
||||
}
|
||||
|
||||
if(IsfCorr[0] > IsfCorr[1])
|
||||
{
|
||||
MaxCorr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxCorr = 1;
|
||||
}
|
||||
|
||||
if(IsfCorr[2] > IsfCorr[MaxCorr])
|
||||
{
|
||||
MaxCorr = 2;
|
||||
}
|
||||
|
||||
MaxCorr = MaxCorr + 1; /* Maximum correlation of difference vector */
|
||||
|
||||
for(i = M - 1; i < (M16k - 1); i++)
|
||||
{
|
||||
tmp = (HfIsf[i - 1 - MaxCorr] - HfIsf[i - 2 - MaxCorr]);
|
||||
HfIsf[i] = (Word16)(HfIsf[i - 1] + tmp);
|
||||
}
|
||||
|
||||
/* tmp=7965+(HfIsf[2]-HfIsf[3]-HfIsf[4])/6; */
|
||||
tmp = HfIsf[4] + HfIsf[3];
|
||||
tmp = HfIsf[2] - tmp;
|
||||
tmp = (tmp * 5461) >> 15;
|
||||
tmp = tmp + 20390;
|
||||
|
||||
if(tmp > 19456)
|
||||
{ /* Maximum value of ISF should be at most 7600 Hz */
|
||||
tmp = 19456;
|
||||
}
|
||||
|
||||
tmp = tmp - HfIsf[M - 2];
|
||||
tmp2 = HfIsf[M16k - 2] - HfIsf[M - 2];
|
||||
exp2 = D_UTIL_norm_s((Word16)tmp2);
|
||||
exp = D_UTIL_norm_s((Word16)tmp);
|
||||
exp = exp - 1;
|
||||
tmp = tmp << exp;
|
||||
tmp2 = tmp2 << exp2;
|
||||
coeff = (tmp << 15) / tmp2; /* Coefficient for stretching the ISF vector */
|
||||
exp = exp2 - exp;
|
||||
|
||||
if(exp >= 0)
|
||||
{
|
||||
for(i = M - 1; i < M16k - 1; i++)
|
||||
{
|
||||
tmp = ((HfIsf[i] - HfIsf[i - 1]) * coeff) >> 15;
|
||||
IsfDiff[i - (M - 1)] = tmp << exp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exp = 15 - exp;
|
||||
|
||||
for(i = M - 1; i < M16k - 1; i++)
|
||||
{
|
||||
IsfDiff[i - (M - 1)] = ((HfIsf[i] - HfIsf[i - 1]) * coeff) >> exp;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = M; i < (M16k - 1); i++)
|
||||
{
|
||||
/* The difference between ISF(n) and ISF(n-2) should be at least 500 Hz */
|
||||
tmp = ((IsfDiff[i - (M - 1)] + IsfDiff[i - M]) - 1280);
|
||||
|
||||
if(tmp < 0)
|
||||
{
|
||||
if(IsfDiff[i - (M - 1)] > IsfDiff[i - M])
|
||||
{
|
||||
IsfDiff[i - M] = (1280 - IsfDiff[i - (M - 1)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsfDiff[i - (M - 1)] = (1280 - IsfDiff[i - M]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = M - 1; i < M16k - 1; i++)
|
||||
{
|
||||
HfIsf[i] = (Word16)(HfIsf[i - 1] + IsfDiff[i - (M - 1)]);
|
||||
}
|
||||
|
||||
for(i = 0; i < M16k - 1; i++)
|
||||
{
|
||||
HfIsf[i] = (Word16)((HfIsf[i] * 13107) >> 14);
|
||||
/* Scale the ISF vector correctly for 16000 kHz */
|
||||
}
|
||||
|
||||
D_LPC_isf_isp_conversion(HfIsf, HfIsf, M16k);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_LPC_H
|
||||
#define DEC_LPC_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
void D_LPC_isf_noise_d(Word16 *indice, Word16 *isf_q);
|
||||
void D_LPC_isf_isp_conversion(Word16 isf[], Word16 isp[], Word16 m);
|
||||
void D_LPC_isp_a_conversion(Word16 isp[], Word16 a[], Word32 adaptive_scaling,
|
||||
Word16 m);
|
||||
void D_LPC_a_weight(Word16 a[], Word16 ap[], Word16 gamma, Word16 m);
|
||||
void D_LPC_isf_2s3s_decode(Word16 *indice, Word16 *isf_q, Word16* past_isfq,
|
||||
Word16 *isfold, Word16 *isf_buf, Word16 bfi);
|
||||
void D_LPC_isf_2s5s_decode(Word16 *indice, Word16 *isf_q, Word16 *past_isfq,
|
||||
Word16 *isfold, Word16 *isf_buf, Word16 bfi);
|
||||
void D_LPC_int_isp_find(Word16 isp_old[], Word16 isp_new[],
|
||||
const Word16 frac[], Word16 Az[]);
|
||||
void D_LPC_isf_extrapolation(Word16 HfIsf[]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "typedef.h"
|
||||
#include "dec_main.h"
|
||||
#include "dec_dtx.h"
|
||||
#include "dec_acelp.h"
|
||||
#include "dec_gain.h"
|
||||
#include "dec_lpc.h"
|
||||
#include "dec_util.h"
|
||||
|
||||
#define MAX_16 (Word16)0x7fff
|
||||
#define MIN_16 (Word16)0x8000
|
||||
|
||||
#define L_FRAME 256 /* Frame size */
|
||||
#define NB_SUBFR 4 /* Number of subframe per frame */
|
||||
#define L_SUBFR 64 /* Subframe size */
|
||||
#define MODE_7k 0 /* modes */
|
||||
#define MODE_9k 1
|
||||
#define MODE_12k 2
|
||||
#define MODE_14k 3
|
||||
#define MODE_16k 4
|
||||
#define MODE_18k 5
|
||||
#define MODE_20k 6
|
||||
#define MODE_23k 7
|
||||
#define MODE_24k 8
|
||||
#define RX_SPEECH_PROBABLY_DEGRADED 1 /* rx types */
|
||||
#define RX_SPEECH_LOST 2
|
||||
#define RX_SPEECH_BAD 3
|
||||
#define RX_NO_DATA 7
|
||||
#define Q_MAX 8 /* scaling max for signal */
|
||||
#define PIT_SHARP 27853 /* pitch sharpening factor = 0.85 Q15 */
|
||||
#define PIT_MIN 34 /* Minimum pitch lag with resolution 1/4 */
|
||||
#define PIT_FR2 128 /* Minimum pitch lag with resolution 1/2 */
|
||||
#define PIT_FR1_9b 160 /* Minimum pitch lag with resolution 1 */
|
||||
#define PIT_FR1_8b 92 /* Minimum pitch lag with resolution 1 */
|
||||
|
||||
extern const Word16 D_ROM_isp[];
|
||||
extern const Word16 D_ROM_isf[];
|
||||
extern const Word16 D_ROM_interpol_frac[];
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning( disable : 4310)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Decoder_reset
|
||||
*
|
||||
* Parameters:
|
||||
* st I/O: pointer to state structure
|
||||
* reset_all I: perform full reset
|
||||
*
|
||||
* Function:
|
||||
* Initialisation of variables for the decoder section.
|
||||
*
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_MAIN_reset(void *st, Word16 reset_all)
|
||||
{
|
||||
Word32 i;
|
||||
|
||||
Decoder_State *dec_state;
|
||||
|
||||
dec_state = (Decoder_State*)st;
|
||||
memset(dec_state->mem_exc, 0, (PIT_MAX + L_INTERPOL) * sizeof(Word16));
|
||||
memset(dec_state->mem_isf_q, 0, M * sizeof(Word16));
|
||||
dec_state->mem_T0_frac = 0; /* old pitch value = 64.0 */
|
||||
dec_state->mem_T0 = 64;
|
||||
dec_state->mem_first_frame = 1;
|
||||
dec_state->mem_gc_thres = 0;
|
||||
dec_state->mem_tilt_code = 0;
|
||||
memset(dec_state->mem_ph_disp, 0, 8 * sizeof(Word16));
|
||||
|
||||
/* scaling memories for excitation */
|
||||
dec_state->mem_q = Q_MAX;
|
||||
dec_state->mem_subfr_q[3] = Q_MAX;
|
||||
dec_state->mem_subfr_q[2] = Q_MAX;
|
||||
dec_state->mem_subfr_q[1] = Q_MAX;
|
||||
dec_state->mem_subfr_q[0] = Q_MAX;
|
||||
|
||||
if(reset_all != 0)
|
||||
{
|
||||
/* routines initialization */
|
||||
D_GAIN_init(dec_state->mem_gain);
|
||||
memset(dec_state->mem_oversamp, 0, (2 * 12) * sizeof(Word16));
|
||||
memset(dec_state->mem_sig_out, 0, 6 * sizeof(Word16));
|
||||
memset(dec_state->mem_hf, 0, (31 - 1) * sizeof(Word16));
|
||||
memset(dec_state->mem_hf3, 0, (31 - 1) * sizeof(Word16));
|
||||
memset(dec_state->mem_hp400, 0, 6 * sizeof(Word16));
|
||||
D_GAIN_lag_concealment_init(dec_state->mem_lag);
|
||||
|
||||
/* isp initialization */
|
||||
memcpy(dec_state->mem_isp, D_ROM_isp, M * sizeof(Word16));
|
||||
memcpy(dec_state->mem_isf, D_ROM_isf, M * sizeof(Word16));
|
||||
|
||||
for(i = 0; i < L_MEANBUF; i++)
|
||||
{
|
||||
memcpy(&dec_state->mem_isf_buf[i * M], D_ROM_isf, M * sizeof(Word16));
|
||||
}
|
||||
|
||||
/* variable initialization */
|
||||
dec_state->mem_deemph = 0;
|
||||
dec_state->mem_seed = 21845; /* init random with 21845 */
|
||||
dec_state->mem_seed2 = 21845;
|
||||
dec_state->mem_seed3 = 21845;
|
||||
dec_state->mem_state = 0;
|
||||
dec_state->mem_bfi = 0;
|
||||
|
||||
/* Static vectors to zero */
|
||||
memset(dec_state->mem_syn_hf, 0, M16k * sizeof(Word16));
|
||||
memset(dec_state->mem_syn_hi, 0, M * sizeof(Word16));
|
||||
memset(dec_state->mem_syn_lo, 0, M * sizeof(Word16));
|
||||
D_DTX_reset(dec_state->dtx_decSt, D_ROM_isf);
|
||||
dec_state->mem_vad_hist = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decoder_init
|
||||
*
|
||||
* Parameters:
|
||||
* spd_state O: pointer to state structure
|
||||
*
|
||||
* Function:
|
||||
* Initialization of variables for the decoder section.
|
||||
* Memory allocation.
|
||||
*
|
||||
* Returns:
|
||||
* return zero if succesful
|
||||
*/
|
||||
Word32 D_MAIN_init(void **spd_state)
|
||||
{
|
||||
/* Decoder states */
|
||||
Decoder_State *st;
|
||||
|
||||
*spd_state = NULL;
|
||||
|
||||
/*
|
||||
* Memory allocation for coder state.
|
||||
*/
|
||||
if((st = (Decoder_State*)malloc(sizeof(Decoder_State))) == NULL)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
st->dtx_decSt = NULL;
|
||||
D_DTX_init(&st->dtx_decSt, D_ROM_isf);
|
||||
D_MAIN_reset((void *)st, 1);
|
||||
*spd_state = (void *)st;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decoder_close
|
||||
*
|
||||
* Parameters:
|
||||
* spd_state I: pointer to state structure
|
||||
*
|
||||
* Function:
|
||||
* Free coder memory.
|
||||
*
|
||||
* Returns:
|
||||
* void
|
||||
*/
|
||||
void D_MAIN_close(void **spd_state)
|
||||
{
|
||||
D_DTX_exit(&(((Decoder_State *)(*spd_state))->dtx_decSt));
|
||||
free(*spd_state);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decoder_exe
|
||||
*
|
||||
* Parameters:
|
||||
* mode I: used mode
|
||||
* prms I: parameter vector
|
||||
* synth_out O: synthesis speech
|
||||
* spe_state B: state structure
|
||||
* frame_type I: received frame type
|
||||
*
|
||||
* Function:
|
||||
* Main decoder routine.
|
||||
*
|
||||
* Returns:
|
||||
* 0 if successful
|
||||
*/
|
||||
Word32 D_MAIN_decode(Word16 mode, Word16 prms[], Word16 synth16k[],
|
||||
void *spd_state, UWord8 frame_type)
|
||||
{
|
||||
|
||||
Word32 code2[L_SUBFR]; /* algebraic codevector */
|
||||
Word32 L_tmp, L_tmp2, L_gain_code, L_stab_fac;
|
||||
Word32 i, j, i_subfr, pit_flag;
|
||||
Word32 T0, T0_frac, T0_max, select, T0_min = 0;
|
||||
|
||||
Word16 exc2[L_FRAME]; /* excitation vector */
|
||||
Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
|
||||
Word16 code[L_SUBFR]; /* algebraic codevector */
|
||||
Word16 excp[L_SUBFR]; /* excitation vector */
|
||||
Word16 HfIsf[M16k];
|
||||
Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr*/
|
||||
Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
|
||||
Word16 isf_tmp[M]; /* ISF tmp */
|
||||
Word16 ind[8]; /* quantization indices */
|
||||
|
||||
Word16 index, fac, voice_fac, max, Q_new = 0;
|
||||
Word16 gain_pit, gain_code, gain_code_lo, tmp;
|
||||
Word16 corr_gain = 0;
|
||||
UWord16 pit_sharp = 0;
|
||||
|
||||
Word16 *exc; /* Excitation vector */
|
||||
Word16 *p_Aq; /* ptr to A(z) for the 4 subframes */
|
||||
Word16 *p_isf; /* prt to isf */
|
||||
|
||||
Decoder_State *st; /* Decoder states */
|
||||
UWord8 newDTXState, bfi, unusable_frame;
|
||||
UWord8 vad_flag;
|
||||
|
||||
st = (Decoder_State*)spd_state;
|
||||
|
||||
/* find the new DTX state SPEECH OR DTX */
|
||||
newDTXState = D_DTX_rx_handler(st->dtx_decSt, frame_type);
|
||||
|
||||
if(newDTXState != SPEECH)
|
||||
{
|
||||
D_DTX_exe(st->dtx_decSt, exc2, newDTXState, isf, &prms);
|
||||
}
|
||||
|
||||
/* SPEECH action state machine */
|
||||
if((frame_type == RX_SPEECH_BAD) |
|
||||
(frame_type == RX_SPEECH_PROBABLY_DEGRADED))
|
||||
{
|
||||
/* bfi for all index, bits are not usable */
|
||||
bfi = 1;
|
||||
unusable_frame = 0;
|
||||
}
|
||||
else if((frame_type == RX_NO_DATA) | (frame_type == RX_SPEECH_LOST))
|
||||
{
|
||||
/* bfi only for lsf, gains and pitch period */
|
||||
bfi = 1;
|
||||
unusable_frame = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfi = 0;
|
||||
unusable_frame = 0;
|
||||
}
|
||||
|
||||
if(bfi != 0)
|
||||
{
|
||||
st->mem_state = (UWord8)(st->mem_state + 1);
|
||||
|
||||
if(st->mem_state > 6)
|
||||
{
|
||||
st->mem_state = 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
st->mem_state = (UWord8)(st->mem_state >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this frame is the first speech frame after CNI period,
|
||||
* set the BFH state machine to an appropriate state depending
|
||||
* on whether there was DTX muting before start of speech or not
|
||||
* If there was DTX muting, the first speech frame is muted.
|
||||
* If there was no DTX muting, the first speech frame is not
|
||||
* muted. The BFH state machine starts from state 5, however, to
|
||||
* keep the audible noise resulting from a SID frame which is
|
||||
* erroneously interpreted as a good speech frame as small as
|
||||
* possible (the decoder output in this case is quickly muted)
|
||||
*/
|
||||
|
||||
if(st->dtx_decSt->mem_dtx_global_state == DTX)
|
||||
{
|
||||
st->mem_state = 5;
|
||||
st->mem_bfi = 0;
|
||||
}
|
||||
else if(st->dtx_decSt->mem_dtx_global_state == D_DTX_MUTE)
|
||||
{
|
||||
st->mem_state = 5;
|
||||
st->mem_bfi = 1;
|
||||
}
|
||||
|
||||
if(newDTXState == SPEECH)
|
||||
{
|
||||
vad_flag = (UWord8)(*prms++);
|
||||
|
||||
if(bfi == 0)
|
||||
{
|
||||
if(vad_flag == 0)
|
||||
{
|
||||
st->mem_vad_hist = (Word16)(st->mem_vad_hist + 1);
|
||||
st->dtx_decSt->mem_dtx_vad_hist = (Word16)(st->dtx_decSt->mem_dtx_vad_hist + 1);
|
||||
|
||||
if(st->mem_vad_hist > 32767)
|
||||
{
|
||||
st->mem_vad_hist = 32767;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
st->mem_vad_hist = 0;
|
||||
st->dtx_decSt->mem_dtx_vad_hist = 0;
|
||||
}
|
||||
}
|
||||
else if (st->dtx_decSt->mem_dtx_vad_hist > 0)
|
||||
{
|
||||
st->dtx_decSt->mem_dtx_vad_hist = (Word16)(st->dtx_decSt->mem_dtx_vad_hist + 1);
|
||||
}
|
||||
|
||||
if (st->dtx_decSt->mem_dtx_vad_hist > 32767)
|
||||
{
|
||||
st->dtx_decSt->mem_dtx_vad_hist = 32767;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DTX-CNG
|
||||
*/
|
||||
if(newDTXState != SPEECH) /* CNG mode */
|
||||
{
|
||||
/*
|
||||
* increase slightly energy of noise below 200 Hz
|
||||
* Convert ISFs to the cosine domain
|
||||
*/
|
||||
D_LPC_isf_isp_conversion(isf, ispnew, M);
|
||||
D_LPC_isp_a_conversion(ispnew, Aq, 1, M);
|
||||
memcpy(isf_tmp, st->mem_isf, M * sizeof(Word16));
|
||||
|
||||
for(i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
|
||||
{
|
||||
j = (i_subfr >> 6);
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
L_tmp = (isf_tmp[i] * (32767 - D_ROM_interpol_frac[j])) << 1;
|
||||
L_tmp = L_tmp + ((isf[i] * D_ROM_interpol_frac[j]) << 1);
|
||||
HfIsf[i] = (Word16)((L_tmp + 0x8000) >> 16);
|
||||
}
|
||||
|
||||
D_UTIL_dec_synthesis(Aq, &exc2[i_subfr], 0, &synth16k[i_subfr * 5 /4],
|
||||
(Word16) 1, HfIsf, mode, newDTXState, bfi, st);
|
||||
}
|
||||
|
||||
/* reset speech coder memories */
|
||||
D_MAIN_reset(st, 0);
|
||||
memcpy(st->mem_isf, isf, M * sizeof(Word16));
|
||||
st->mem_bfi = bfi;
|
||||
st->dtx_decSt->mem_dtx_global_state = (UWord8)newDTXState;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* ACELP
|
||||
*/
|
||||
|
||||
exc = st->mem_exc + PIT_MAX + L_INTERPOL;
|
||||
|
||||
/* Decode the ISFs */
|
||||
if(mode <= MODE_7k)
|
||||
{
|
||||
ind[0] = *prms++;
|
||||
ind[1] = *prms++;
|
||||
ind[2] = *prms++;
|
||||
ind[3] = *prms++;
|
||||
ind[4] = *prms++;
|
||||
D_LPC_isf_2s3s_decode(ind, isf, st->mem_isf_q, st->mem_isf,
|
||||
st->mem_isf_buf, bfi);
|
||||
}
|
||||
else
|
||||
{
|
||||
ind[0] = *prms++;
|
||||
ind[1] = *prms++;
|
||||
ind[2] = *prms++;
|
||||
ind[3] = *prms++;
|
||||
ind[4] = *prms++;
|
||||
ind[5] = *prms++;
|
||||
ind[6] = *prms++;
|
||||
D_LPC_isf_2s5s_decode(ind, isf, st->mem_isf_q, st->mem_isf,
|
||||
st->mem_isf_buf, bfi);
|
||||
}
|
||||
|
||||
/* Convert ISFs to the cosine domain */
|
||||
D_LPC_isf_isp_conversion(isf, ispnew, M);
|
||||
|
||||
if(st->mem_first_frame != 0)
|
||||
{
|
||||
st->mem_first_frame = 0;
|
||||
memcpy(st->mem_isp, ispnew, M * sizeof(Word16));
|
||||
}
|
||||
|
||||
/* Find the interpolated ISPs and convert to a[] for all subframes */
|
||||
D_LPC_int_isp_find(st->mem_isp, ispnew, D_ROM_interpol_frac, Aq);
|
||||
|
||||
/* update isp memory for the next frame */
|
||||
memcpy(st->mem_isp, ispnew, M * sizeof(Word16));
|
||||
|
||||
/* Check stability on isf : distance between old isf and current isf */
|
||||
L_tmp = 0;
|
||||
p_isf = st->mem_isf;
|
||||
|
||||
for(i = 0; i < M - 1; i++)
|
||||
{
|
||||
tmp = (Word16)((isf[i] - p_isf[i]));
|
||||
L_tmp = L_tmp + (tmp * tmp);
|
||||
}
|
||||
|
||||
if(L_tmp < 3276928)
|
||||
{
|
||||
L_tmp = L_tmp >> 7;
|
||||
L_tmp = (L_tmp * 26214) >> 15; /* tmp = L_tmp*0.8/256 */
|
||||
L_tmp = 20480 - L_tmp; /* 1.25 - tmp */
|
||||
L_stab_fac = L_tmp << 1; /* Q14 -> Q15 with saturation */
|
||||
|
||||
if(L_stab_fac > 0x7FFF)
|
||||
{
|
||||
L_stab_fac = 0x7FFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
L_stab_fac = 0x0;
|
||||
}
|
||||
|
||||
memcpy(isf_tmp, st->mem_isf, M * sizeof(Word16));
|
||||
memcpy(st->mem_isf, isf, M * sizeof(Word16));
|
||||
|
||||
/*
|
||||
* Loop for every subframe in the analysis frame
|
||||
*
|
||||
* The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR
|
||||
* times
|
||||
* - decode the pitch delay and filter mode
|
||||
* - decode algebraic code
|
||||
* - decode pitch and codebook gains
|
||||
* - find voicing factor and tilt of code for next subframe
|
||||
* - find the excitation and compute synthesis speech
|
||||
*/
|
||||
|
||||
p_Aq = Aq; /* pointer to interpolated LPC parameters */
|
||||
|
||||
for(i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
|
||||
{
|
||||
pit_flag = i_subfr;
|
||||
|
||||
if((i_subfr == (2 * L_SUBFR)) & (mode > MODE_7k))
|
||||
{
|
||||
pit_flag = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* - Decode pitch lag
|
||||
* Lag indeces received also in case of BFI,
|
||||
* so that the parameter pointer stays in sync.
|
||||
*/
|
||||
|
||||
if(pit_flag == 0)
|
||||
{
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
index = *prms++;
|
||||
|
||||
if(index < ((PIT_FR1_8b - PIT_MIN) * 2))
|
||||
{
|
||||
T0 = (PIT_MIN + (index >> 1));
|
||||
T0_frac = (index - ((T0 - PIT_MIN) << 1));
|
||||
T0_frac = (T0_frac << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
T0 = index + (PIT_FR1_8b - ((PIT_FR1_8b - PIT_MIN) * 2));
|
||||
T0_frac = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
index = *prms++;
|
||||
|
||||
if(index < ((PIT_FR2 - PIT_MIN) * 4))
|
||||
{
|
||||
T0 = PIT_MIN + (index >> 2);
|
||||
T0_frac = index - ((T0 - PIT_MIN) << 2);
|
||||
}
|
||||
else if(index <
|
||||
((((PIT_FR2 - PIT_MIN) * 4) + ((PIT_FR1_9b - PIT_FR2) * 2))))
|
||||
{
|
||||
index = (Word16)((index - ((PIT_FR2 - PIT_MIN) * 4)));
|
||||
T0 = PIT_FR2 + (index >> 1);
|
||||
T0_frac = index - ((T0 - PIT_FR2) << 1);
|
||||
T0_frac = T0_frac << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
T0 = index + (PIT_FR1_9b - ((PIT_FR2 - PIT_MIN) * 4) -
|
||||
((PIT_FR1_9b - PIT_FR2) * 2));
|
||||
T0_frac = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* find T0_min and T0_max for subframe 2 and 4 */
|
||||
T0_min = T0 - 8;
|
||||
|
||||
if(T0_min < PIT_MIN)
|
||||
{
|
||||
T0_min = PIT_MIN;
|
||||
}
|
||||
|
||||
T0_max = T0_min + 15;
|
||||
|
||||
if(T0_max > PIT_MAX)
|
||||
{
|
||||
T0_max = PIT_MAX;
|
||||
T0_min = T0_max - 15;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* if subframe 2 or 4 */
|
||||
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
index = *prms++;
|
||||
T0 = T0_min + (index >> 1);
|
||||
T0_frac = index - ((T0 - T0_min) << 1);
|
||||
T0_frac = T0_frac << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = *prms++;
|
||||
T0 = T0_min + (index >> 2);
|
||||
T0_frac = index - ((T0 - T0_min) << 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* check BFI after pitch lag decoding */
|
||||
if(bfi != 0) /* if frame erasure */
|
||||
{
|
||||
D_GAIN_lag_concealment(&(st->mem_gain[17]), st->mem_lag, &T0,
|
||||
&(st->mem_T0), &(st->mem_seed3), unusable_frame);
|
||||
T0_frac = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pitch gain, the interpolation filter
|
||||
* and the adaptive codebook vector.
|
||||
*/
|
||||
|
||||
D_GAIN_adaptive_codebook_excitation(&exc[i_subfr], T0, T0_frac);
|
||||
|
||||
if(unusable_frame)
|
||||
{
|
||||
select = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
select = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
select = *prms++;
|
||||
}
|
||||
}
|
||||
|
||||
if(select == 0)
|
||||
{
|
||||
/* find pitch excitation with lp filter */
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
L_tmp = 2949 * exc[i - 1 + i_subfr];
|
||||
L_tmp = L_tmp + (10486 * exc[i + i_subfr]);
|
||||
L_tmp = L_tmp + (2949 * exc[i + 1 + i_subfr]);
|
||||
code[i] = (Word16)((L_tmp + 0x2000) >> 14);
|
||||
}
|
||||
|
||||
memcpy(&exc[i_subfr], code, L_SUBFR * sizeof(Word16));
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode innovative codebook.
|
||||
* Add the fixed-gain pitch contribution to code[].
|
||||
*/
|
||||
|
||||
if(unusable_frame != 0)
|
||||
{
|
||||
/* the innovative code doesn't need to be scaled (see Q_gain2) */
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
code[i] = (Word16)(D_UTIL_random(&(st->mem_seed)) >> 3);
|
||||
}
|
||||
}
|
||||
else if(mode <= MODE_7k)
|
||||
{
|
||||
ind[0] = *prms++;
|
||||
D_ACELP_decode_2t(ind[0], code);
|
||||
}
|
||||
else if(mode <= MODE_9k)
|
||||
{
|
||||
memcpy(ind, prms, 4 * sizeof(Word16));
|
||||
prms += 4;
|
||||
D_ACELP_decode_4t(ind, 20, code);
|
||||
}
|
||||
else if(mode <= MODE_12k)
|
||||
{
|
||||
memcpy(ind, prms, 4 * sizeof(Word16));
|
||||
prms += 4;
|
||||
D_ACELP_decode_4t(ind, 36, code);
|
||||
}
|
||||
else if(mode <= MODE_14k)
|
||||
{
|
||||
memcpy(ind, prms, 4 * sizeof(Word16));
|
||||
prms += 4;
|
||||
D_ACELP_decode_4t(ind, 44, code);
|
||||
}
|
||||
else if(mode <= MODE_16k)
|
||||
{
|
||||
memcpy(ind, prms, 4 * sizeof(Word16));
|
||||
prms += 4;
|
||||
D_ACELP_decode_4t(ind, 52, code);
|
||||
}
|
||||
else if(mode <= MODE_18k)
|
||||
{
|
||||
memcpy(ind, prms, 8 * sizeof(Word16));
|
||||
prms += 8;
|
||||
D_ACELP_decode_4t(ind, 64, code);
|
||||
}
|
||||
else if(mode <= MODE_20k)
|
||||
{
|
||||
memcpy(ind, prms, 8 * sizeof(Word16));
|
||||
prms += 8;
|
||||
D_ACELP_decode_4t(ind, 72, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ind, prms, 8 * sizeof(Word16));
|
||||
prms += 8;
|
||||
D_ACELP_decode_4t(ind, 88, code);
|
||||
}
|
||||
|
||||
tmp = 0;
|
||||
D_UTIL_preemph(code, st->mem_tilt_code, L_SUBFR, &tmp);
|
||||
|
||||
L_tmp = T0;
|
||||
|
||||
if(T0_frac > 2)
|
||||
{
|
||||
L_tmp = L_tmp + 1;
|
||||
}
|
||||
|
||||
D_GAIN_pitch_sharpening(code, L_tmp, PIT_SHARP);
|
||||
|
||||
/*
|
||||
* Decode codebooks gains.
|
||||
*/
|
||||
index = *prms++; /* codebook gain index */
|
||||
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
D_GAIN_decode(index, 6, code, &gain_pit, &L_gain_code, bfi,
|
||||
st->mem_bfi, st->mem_state, unusable_frame, st->mem_vad_hist,
|
||||
st->mem_gain);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_GAIN_decode(index, 7, code, &gain_pit, &L_gain_code, bfi,
|
||||
st->mem_bfi, st->mem_state, unusable_frame, st->mem_vad_hist,
|
||||
st->mem_gain);
|
||||
}
|
||||
|
||||
/* find best scaling to perform on excitation (Q_new) */
|
||||
tmp = st->mem_subfr_q[0];
|
||||
|
||||
for(i = 1; i < 4; i++)
|
||||
{
|
||||
if(st->mem_subfr_q[i] < tmp)
|
||||
{
|
||||
tmp = st->mem_subfr_q[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* limit scaling (Q_new) to Q_MAX */
|
||||
if(tmp > Q_MAX)
|
||||
{
|
||||
tmp = Q_MAX;
|
||||
}
|
||||
|
||||
Q_new = 0;
|
||||
L_tmp = L_gain_code; /* L_gain_code in Q16 */
|
||||
|
||||
while((L_tmp < 0x08000000L) && (Q_new < tmp))
|
||||
{
|
||||
L_tmp = (L_tmp << 1);
|
||||
Q_new = (Word16)((Q_new + 1));
|
||||
}
|
||||
|
||||
if(L_tmp < 0x7FFF7FFF)
|
||||
{
|
||||
gain_code = (Word16)((L_tmp + 0x8000) >> 16);
|
||||
/* scaled gain_code with Qnew */
|
||||
}
|
||||
else
|
||||
{
|
||||
gain_code = 32767;
|
||||
}
|
||||
|
||||
if(Q_new > st->mem_q)
|
||||
{
|
||||
D_UTIL_signal_up_scale(exc + i_subfr - (PIT_MAX + L_INTERPOL),
|
||||
PIT_MAX + L_INTERPOL + L_SUBFR, (Word16)(Q_new - st->mem_q));
|
||||
}
|
||||
else
|
||||
{
|
||||
D_UTIL_signal_down_scale(exc + i_subfr - (PIT_MAX + L_INTERPOL),
|
||||
PIT_MAX + L_INTERPOL + L_SUBFR, (Word16)(st->mem_q - Q_new));
|
||||
}
|
||||
|
||||
st->mem_q = Q_new;
|
||||
|
||||
/*
|
||||
* Update parameters for the next subframe.
|
||||
* - tilt of code: 0.0 (unvoiced) to 0.5 (voiced)
|
||||
*/
|
||||
if(bfi == 0)
|
||||
{
|
||||
/* LTP-Lag history update */
|
||||
for(i = 4; i > 0; i--)
|
||||
{
|
||||
st->mem_lag[i] = st->mem_lag[i - 1];
|
||||
}
|
||||
st->mem_lag[0] = (Word16)T0;
|
||||
st->mem_T0 = (Word16)T0;
|
||||
st->mem_T0_frac = 0; /* Remove fraction in case of BFI */
|
||||
}
|
||||
|
||||
/* find voice factor in Q15 (1=voiced, -1=unvoiced) */
|
||||
memcpy(exc2, &exc[i_subfr], L_SUBFR * sizeof(Word16));
|
||||
D_UTIL_signal_down_scale(exc2, L_SUBFR, 3);
|
||||
|
||||
/* post processing of excitation elements */
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
pit_sharp = (Word16)(gain_pit << 1);
|
||||
|
||||
if(pit_sharp > 16384)
|
||||
{
|
||||
if(pit_sharp > 32767)
|
||||
{
|
||||
pit_sharp = 32767;
|
||||
}
|
||||
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
L_tmp = (exc2[i] * pit_sharp) >> 15;
|
||||
L_tmp = L_tmp * gain_pit;
|
||||
excp[i] = (Word16)((L_tmp + 0x8000) >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voice_fac = D_GAIN_find_voice_factor(exc2, -3, gain_pit, code, gain_code,
|
||||
L_SUBFR);
|
||||
|
||||
/* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
|
||||
st->mem_tilt_code = (Word16)((voice_fac >> 2) + 8192);
|
||||
|
||||
/*
|
||||
* Find the total excitation.
|
||||
* Find synthesis speech corresponding to exc[].
|
||||
* Find maximum value of excitation for next scaling
|
||||
*/
|
||||
memcpy(exc2, &exc[i_subfr], L_SUBFR * sizeof(Word16));
|
||||
max = 1;
|
||||
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
L_tmp = (code[i] * gain_code) << 5;
|
||||
L_tmp = L_tmp + (exc[i + i_subfr] * gain_pit);
|
||||
L_tmp = (L_tmp + 0x2000) >> 14;
|
||||
|
||||
if((L_tmp > MIN_16) & (L_tmp < 32768))
|
||||
{
|
||||
exc[i + i_subfr] = (Word16)L_tmp;
|
||||
tmp = (Word16)(abs(L_tmp));
|
||||
|
||||
if(tmp > max)
|
||||
{
|
||||
max = tmp;
|
||||
}
|
||||
}
|
||||
else if(L_tmp > MAX_16)
|
||||
{
|
||||
exc[i + i_subfr] = MAX_16;
|
||||
max = MAX_16;
|
||||
}
|
||||
else
|
||||
{
|
||||
exc[i + i_subfr] = MIN_16;
|
||||
max = MAX_16;
|
||||
}
|
||||
}
|
||||
|
||||
/* tmp = scaling possible according to max value of excitation */
|
||||
tmp = (Word16)((D_UTIL_norm_s(max) + Q_new) - 1);
|
||||
st->mem_subfr_q[3] = st->mem_subfr_q[2];
|
||||
st->mem_subfr_q[2] = st->mem_subfr_q[1];
|
||||
st->mem_subfr_q[1] = st->mem_subfr_q[0];
|
||||
st->mem_subfr_q[0] = tmp;
|
||||
|
||||
/*
|
||||
* phase dispersion to enhance noise in low bit rate
|
||||
*/
|
||||
|
||||
/* L_gain_code in Q16 */
|
||||
D_UTIL_l_extract(L_gain_code, &gain_code, &gain_code_lo);
|
||||
|
||||
if(mode <= MODE_7k)
|
||||
{
|
||||
j = 0; /* high dispersion for rate <= 7.5 kbit/s */
|
||||
}
|
||||
else if(mode <= MODE_9k)
|
||||
{
|
||||
j = 1; /* low dispersion for rate <= 9.6 kbit/s */
|
||||
}
|
||||
else
|
||||
{
|
||||
j = 2; /* no dispersion for rate > 9.6 kbit/s */
|
||||
}
|
||||
|
||||
D_ACELP_phase_dispersion(gain_code, gain_pit, code, (Word16)j,
|
||||
st->mem_ph_disp);
|
||||
|
||||
/*
|
||||
* noise enhancer
|
||||
* - Enhance excitation on noise. (modify gain of code)
|
||||
* If signal is noisy and LPC filter is stable, move gain
|
||||
* of code 1.5 dB toward gain of code threshold.
|
||||
* This decrease by 3 dB noise energy variation.
|
||||
*/
|
||||
L_tmp = 16384 - (voice_fac >> 1); /* 1=unvoiced, 0=voiced */
|
||||
fac = (Word16)((L_stab_fac * L_tmp) >> 15);
|
||||
L_tmp = L_gain_code;
|
||||
|
||||
if(L_tmp < st->mem_gc_thres)
|
||||
{
|
||||
L_tmp = (L_tmp + D_UTIL_mpy_32_16(gain_code, gain_code_lo, 6226));
|
||||
|
||||
if(L_tmp > st->mem_gc_thres)
|
||||
{
|
||||
L_tmp = st->mem_gc_thres;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
L_tmp = D_UTIL_mpy_32_16(gain_code, gain_code_lo, 27536);
|
||||
|
||||
if(L_tmp < st->mem_gc_thres)
|
||||
{
|
||||
L_tmp = st->mem_gc_thres;
|
||||
}
|
||||
}
|
||||
st->mem_gc_thres = L_tmp;
|
||||
L_gain_code =
|
||||
D_UTIL_mpy_32_16(gain_code, gain_code_lo, (Word16)(32767 - fac));
|
||||
D_UTIL_l_extract(L_tmp, &gain_code, &gain_code_lo);
|
||||
L_gain_code =
|
||||
L_gain_code + D_UTIL_mpy_32_16(gain_code, gain_code_lo, fac);
|
||||
|
||||
/*
|
||||
* pitch enhancer
|
||||
* - Enhance excitation on voice. (HP filtering of code)
|
||||
* On voiced signal, filtering of code by a smooth fir HP
|
||||
* filter to decrease energy of code in low frequency.
|
||||
*/
|
||||
|
||||
L_tmp2 = (voice_fac >> 3) + 4096; /* 0.25=voiced, 0=unvoiced */
|
||||
L_tmp = (code[0] << 15) - (code[1] * L_tmp2);
|
||||
code2[0] = (L_tmp + 0x4000) >> 15;
|
||||
|
||||
for(i = 1; i < L_SUBFR - 1; i++)
|
||||
{
|
||||
L_tmp = code[i] << 15;
|
||||
L_tmp = L_tmp - (code[i + 1] * L_tmp2);
|
||||
L_tmp = L_tmp - (code[i - 1] * L_tmp2);
|
||||
code2[i] = (L_tmp + 0x4000) >> 15;
|
||||
}
|
||||
|
||||
L_tmp = code[L_SUBFR - 1] << 15;
|
||||
L_tmp = L_tmp - (code[L_SUBFR - 2] * L_tmp2);
|
||||
code2[L_SUBFR - 1] = (L_tmp + 0x4000) >> 15;
|
||||
|
||||
/* build excitation */
|
||||
gain_code = (Word16)(((L_gain_code << Q_new) + 0x8000) >> 16);
|
||||
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
L_tmp = (code2[i] * gain_code) << 5;
|
||||
L_tmp = L_tmp + (exc2[i] * gain_pit);
|
||||
L_tmp = (L_tmp + 0x2000) >> 14;
|
||||
|
||||
exc2[i] = D_UTIL_saturate(L_tmp);
|
||||
}
|
||||
|
||||
if(mode <= MODE_9k)
|
||||
{
|
||||
if(pit_sharp > 16384)
|
||||
{
|
||||
for(i = 0; i < L_SUBFR; i++)
|
||||
{
|
||||
L_tmp = (excp[i] + exc2[i]);
|
||||
excp[i] = D_UTIL_saturate(L_tmp);
|
||||
}
|
||||
|
||||
D_GAIN_adaptive_control(exc2, excp, L_SUBFR);
|
||||
memcpy(exc2, excp, L_SUBFR * sizeof(Word16));
|
||||
}
|
||||
}
|
||||
|
||||
if(mode <= MODE_7k)
|
||||
{
|
||||
j = (i_subfr >> 6);
|
||||
|
||||
for(i = 0; i < M; i++)
|
||||
{
|
||||
L_tmp = isf_tmp[i] * (32767 - D_ROM_interpol_frac[j]);
|
||||
L_tmp = L_tmp + (isf[i] * D_ROM_interpol_frac[j]);
|
||||
HfIsf[i] = (Word16)((L_tmp + 0x4000) >> 15);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(st->mem_syn_hf, 0, (M16k - M) * sizeof(Word16));
|
||||
}
|
||||
|
||||
if(mode >= MODE_24k)
|
||||
{
|
||||
corr_gain = *prms++;
|
||||
D_UTIL_dec_synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4],
|
||||
corr_gain, HfIsf, mode, newDTXState, bfi, st);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_UTIL_dec_synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4], 0,
|
||||
HfIsf, mode, newDTXState, bfi, st);
|
||||
}
|
||||
|
||||
p_Aq += (M + 1); /* interpolated LPC parameters for next subframe */
|
||||
}
|
||||
|
||||
/*
|
||||
* Update signal for next frame
|
||||
* -> save past of exc[]
|
||||
* -> save pitch parameters.
|
||||
*/
|
||||
|
||||
memmove(st->mem_exc, &st->mem_exc[L_FRAME], (PIT_MAX + L_INTERPOL) * sizeof(Word16));
|
||||
D_UTIL_signal_down_scale(exc, L_FRAME, Q_new);
|
||||
D_DTX_activity_update(st->dtx_decSt, isf, exc);
|
||||
st->dtx_decSt->mem_dtx_global_state = (UWord8)newDTXState;
|
||||
st->mem_bfi = bfi;
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_MAIN_H
|
||||
#define DEC_MAIN_H
|
||||
|
||||
#include "typedef.h"
|
||||
#include "dec_dtx.h"
|
||||
|
||||
#define L_FRAME 256 /* Frame size */
|
||||
#define PIT_MAX 231 /* Maximum pitch lag */
|
||||
#define L_INTERPOL (16 + 1) /* Length of filter for interpolation */
|
||||
#define L_MEANBUF 3
|
||||
#define L_FILT 12 /* Delay of up-sampling filter */
|
||||
#define L_FILT16k 15 /* Delay of down-sampling filter */
|
||||
#define M16k 20 /* Order of LP filter */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Word32 mem_gc_thres; /* threshold for noise enhancer */
|
||||
Word16 mem_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];/* old excitation vector */
|
||||
Word16 mem_isf_buf[L_MEANBUF * M];/* isf buffer(frequency domain) */
|
||||
Word16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */
|
||||
Word16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */
|
||||
Word16 mem_hf3[2 * L_FILT16k]; /* HF band-pass filter memory */
|
||||
Word16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */
|
||||
Word16 mem_gain[23]; /* gain decoder memory */
|
||||
Word16 mem_syn_hf[M16k]; /* HF synthesis memory */
|
||||
Word16 mem_isp[M]; /* old isp (immittance spectral pairs) */
|
||||
Word16 mem_isf[M]; /* old isf (frequency domain) */
|
||||
Word16 mem_isf_q[M]; /* past isf quantizer */
|
||||
Word16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */
|
||||
Word16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */
|
||||
Word16 mem_ph_disp[8]; /* phase dispersion memory */
|
||||
Word16 mem_sig_out[6]; /* hp50 filter memory for synthesis */
|
||||
Word16 mem_hp400[6]; /* hp400 filter memory for synthesis */
|
||||
Word16 mem_lag[5]; /* LTP lag history */
|
||||
Word16 mem_subfr_q[4]; /* old maximum scaling factor */
|
||||
Word16 mem_tilt_code; /* tilt of code */
|
||||
Word16 mem_q; /* old scaling factor */
|
||||
Word16 mem_deemph; /* speech deemph filter memory */
|
||||
Word16 mem_seed; /* random memory for frame erasure */
|
||||
Word16 mem_seed2; /* random memory for HF generation */
|
||||
Word16 mem_seed3; /* random memory for lag concealment */
|
||||
Word16 mem_T0; /* old pitch lag */
|
||||
Word16 mem_T0_frac; /* old pitch fraction lag */
|
||||
UWord16 mem_vad_hist; /* VAD history */
|
||||
D_DTX_State *dtx_decSt;
|
||||
UWord8 mem_bfi; /* Previous BFI */
|
||||
UWord8 mem_state; /* BGH state machine memory */
|
||||
UWord8 mem_first_frame; /* First frame indicator */
|
||||
|
||||
} Decoder_State;
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef DEC_UTIL_H
|
||||
#define DEC_UTIL_H
|
||||
|
||||
#include "typedef.h"
|
||||
#include "dec_main.h"
|
||||
|
||||
Word16 D_UTIL_random(Word16 *seed);
|
||||
|
||||
Word32 D_UTIL_pow2(Word16 exponant, Word16 fraction);
|
||||
Word16 D_UTIL_norm_l (Word32 L_var1);
|
||||
Word16 D_UTIL_norm_s (Word16 var1);
|
||||
Word32 D_UTIL_dot_product12(Word16 x[], Word16 y[], Word16 lg, Word16 *exp);
|
||||
void D_UTIL_normalised_inverse_sqrt(Word32 *frac, Word16 *exp);
|
||||
Word32 D_UTIL_inverse_sqrt(Word32 L_x);
|
||||
void D_UTIL_log2(Word32 L_x, Word16 *exponent, Word16 *fraction);
|
||||
void D_UTIL_l_extract(Word32 L_32, Word16 *hi, Word16 *lo);
|
||||
Word32 D_UTIL_mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
|
||||
Word32 D_UTIL_mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
|
||||
Word16 D_UTIL_saturate(Word32 inp);
|
||||
void D_UTIL_signal_up_scale(Word16 x[], Word16 lg, Word16 exp);
|
||||
void D_UTIL_signal_down_scale(Word16 x[], Word16 lg, Word16 exp);
|
||||
void D_UTIL_dec_synthesis(Word16 Aq[], Word16 exc[], Word16 Q_new,
|
||||
Word16 synth16k[], Word16 prms, Word16 HfIsf[],
|
||||
Word16 mode, Word16 newDTXState, Word16 bfi,
|
||||
Decoder_State *st);
|
||||
void D_UTIL_preemph(Word16 x[], Word16 mu, Word16 lg, Word16 *mem);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef IF_ROM_H
|
||||
#define IF_ROM_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
/*
|
||||
* definition of constants
|
||||
*/
|
||||
#define NUM_OF_SPMODES 9
|
||||
|
||||
/* number of parameters */
|
||||
#define PRMNO_7k 18
|
||||
#define PRMNO_9k 32
|
||||
#define PRMNO_12k 36
|
||||
#define PRMNO_14k 36
|
||||
#define PRMNO_16k 36
|
||||
#define PRMNO_18k 52
|
||||
#define PRMNO_20k 52
|
||||
#define PRMNO_23k 52
|
||||
#define PRMNO_24k 56
|
||||
#define PRMNO_SID 7
|
||||
#define NB_PARM_MAX PRMNO_24k
|
||||
|
||||
/* number of bits */
|
||||
#ifndef NBBITS_7k
|
||||
#define NBBITS_7k 132
|
||||
#define NBBITS_9k 177
|
||||
#define NBBITS_12k 253
|
||||
#define NBBITS_14k 285
|
||||
#define NBBITS_16k 317
|
||||
#define NBBITS_18k 365
|
||||
#define NBBITS_20k 397
|
||||
#define NBBITS_23k 461
|
||||
#define NBBITS_24k 477
|
||||
#define NBBITS_SID 35
|
||||
#endif
|
||||
|
||||
/* number of total bits */
|
||||
#define HEADER_SIZE 6 /* real size + 1 */
|
||||
#define T_NBBITS_7k (NBBITS_7k + HEADER_SIZE)
|
||||
#define T_NBBITS_9k (NBBITS_9k + HEADER_SIZE)
|
||||
#define T_NBBITS_12k (NBBITS_12k + HEADER_SIZE)
|
||||
#define T_NBBITS_14k (NBBITS_14k + HEADER_SIZE)
|
||||
#define T_NBBITS_16k (NBBITS_16k + HEADER_SIZE)
|
||||
#define T_NBBITS_18k (NBBITS_18k + HEADER_SIZE)
|
||||
#define T_NBBITS_20k (NBBITS_20k + HEADER_SIZE)
|
||||
#define T_NBBITS_23k (NBBITS_23k + HEADER_SIZE)
|
||||
#define T_NBBITS_24k (NBBITS_24k + HEADER_SIZE)
|
||||
#define T_NBBITS_SID (NBBITS_SID + HEADER_SIZE)
|
||||
|
||||
#define TX_SPEECH 0
|
||||
#define TX_SID_FIRST 1
|
||||
#define TX_SID_UPDATE 2
|
||||
#define TX_NO_DATA 3
|
||||
|
||||
#define RX_SPEECH_GOOD 0
|
||||
#define RX_SPEECH_PROBABLY_DEGRADED 1
|
||||
#define RX_SPEECH_LOST 2
|
||||
#define RX_SPEECH_BAD 3
|
||||
#define RX_SID_FIRST 4
|
||||
#define RX_SID_UPDATE 5
|
||||
#define RX_SID_BAD 6
|
||||
#define RX_NO_DATA 7
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
*===================================================================
|
||||
* 3GPP AMR Wideband Floating-point Speech Codec
|
||||
*===================================================================
|
||||
*/
|
||||
#ifndef typedef_h
|
||||
#define typedef_h
|
||||
|
||||
/* change these typedef declarations to correspond with your platform */
|
||||
typedef char Word8;
|
||||
typedef unsigned char UWord8;
|
||||
typedef short Word16;
|
||||
typedef unsigned short UWord16;
|
||||
typedef long Word32;
|
||||
typedef double Float64;
|
||||
typedef float Float32;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user