pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
+18
View File
@@ -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
+692
View File
@@ -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;
}
+17
View File
@@ -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
+758
View File
@@ -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;
}
+50
View File
@@ -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
+964
View File
@@ -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);
}
+28
View File
@@ -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
+959
View File
@@ -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;
}
+23
View File
@@ -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
+874
View File
@@ -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;
}
+25
View File
@@ -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
+981
View File
@@ -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);
}
+58
View File
@@ -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
+33
View File
@@ -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
+70
View File
@@ -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
+18
View File
@@ -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