/* *=================================================================== * 3GPP AMR Wideband Floating-point Speech Codec *=================================================================== */ #include #include #include "typedef.h" #include "dec_if.h" #include "if_rom.h" #include "dec.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; /* SID indication IF2 corresponds to mode 10 */ if (mode == 9) { mode ++; } *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); /* SID indication IF2 corresponds to mode 10 */ if (mode == 9) { mode ++; } 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; }