void WebRtcIlbcfix_AbsQuant( iLBC_Enc_Inst_t *iLBCenc_inst, /* (i) Encoder instance */ iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax and idxVec, uses state_first as input) */ int16_t *in, /* (i) vector to encode */ int16_t *weightDenum /* (i) denominator of synthesis filter */ ) { int16_t *syntOut; int16_t quantLen[2]; /* Stack based */ int16_t syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS]; int16_t in_weightedVec[STATE_SHORT_LEN_30MS+LPC_FILTERORDER]; int16_t *in_weighted = &in_weightedVec[LPC_FILTERORDER]; /* Initialize the buffers */ WebRtcSpl_MemSetW16(syntOutBuf, 0, LPC_FILTERORDER+STATE_SHORT_LEN_30MS); syntOut = &syntOutBuf[LPC_FILTERORDER]; /* Start with zero state */ WebRtcSpl_MemSetW16(in_weightedVec, 0, LPC_FILTERORDER); /* Perform the quantization loop in two sections of length quantLen[i], where the perceptual weighting filter is updated at the subframe border */ if (iLBC_encbits->state_first) { quantLen[0]=SUBL; quantLen[1]=iLBCenc_inst->state_short_len-SUBL; } else { quantLen[0]=iLBCenc_inst->state_short_len-SUBL; quantLen[1]=SUBL; } /* Calculate the weighted residual, switch perceptual weighting filter at the subframe border */ WebRtcSpl_FilterARFastQ12( in, in_weighted, weightDenum, LPC_FILTERORDER+1, quantLen[0]); WebRtcSpl_FilterARFastQ12( &in[quantLen[0]], &in_weighted[quantLen[0]], &weightDenum[LPC_FILTERORDER+1], LPC_FILTERORDER+1, quantLen[1]); WebRtcIlbcfix_AbsQuantLoop( syntOut, in_weighted, weightDenum, quantLen, iLBC_encbits->idxVec); }
int16_t WebRtcIlbcfix_InitEncode( /* (o) Number of bytes encoded */ iLBC_Enc_Inst_t * iLBCenc_inst, /* (i/o) Encoder instance */ int16_t mode /* (i) frame size mode */ ) { iLBCenc_inst->mode = mode; /* Set all the variables that are dependent on the frame size mode */ if (mode == 30) { iLBCenc_inst->blockl = BLOCKL_30MS; iLBCenc_inst->nsub = NSUB_30MS; iLBCenc_inst->nasub = NASUB_30MS; iLBCenc_inst->lpc_n = LPC_N_30MS; iLBCenc_inst->no_of_bytes = NO_OF_BYTES_30MS; iLBCenc_inst->no_of_words = NO_OF_WORDS_30MS; iLBCenc_inst->state_short_len = STATE_SHORT_LEN_30MS; } else if (mode == 20) { iLBCenc_inst->blockl = BLOCKL_20MS; iLBCenc_inst->nsub = NSUB_20MS; iLBCenc_inst->nasub = NASUB_20MS; iLBCenc_inst->lpc_n = LPC_N_20MS; iLBCenc_inst->no_of_bytes = NO_OF_BYTES_20MS; iLBCenc_inst->no_of_words = NO_OF_WORDS_20MS; iLBCenc_inst->state_short_len = STATE_SHORT_LEN_20MS; } else { return (-1); } /* Clear the buffers and set the previous LSF and LSP to the mean value */ WebRtcSpl_MemSetW16(iLBCenc_inst->anaMem, 0, LPC_FILTERORDER); WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lsfold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER); WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lsfdeqold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER); WebRtcSpl_MemSetW16(iLBCenc_inst->lpc_buffer, 0, LPC_LOOKBACK + BLOCKL_MAX); /* Set the filter state of the HP filter to 0 */ WebRtcSpl_MemSetW16(iLBCenc_inst->hpimemx, 0, 2); WebRtcSpl_MemSetW16(iLBCenc_inst->hpimemy, 0, 4); #ifdef SPLIT_10MS /*Zeroing the past samples for 10msec Split */ WebRtcSpl_MemSetW16(iLBCenc_inst->past_samples, 0, 160); iLBCenc_inst->section = 0; #endif return (iLBCenc_inst->no_of_bytes); }
int WebRtcNetEQ_DbGetPtrs(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec, CodecFuncInst_t *ptr_inst) { int pos = inst->position[codec]; if ((codec <= kDecoderReservedStart) || (codec >= kDecoderReservedEnd) || (codec > NUM_TOTAL_CODECS)) { /* ERROR */ pos = -1; } if (pos >= 0) { ptr_inst->codec_state = inst->codec_state[pos]; ptr_inst->funcAddLatePkt = inst->funcAddLatePkt[pos]; ptr_inst->funcDecode = inst->funcDecode[pos]; ptr_inst->funcDecodeRCU = inst->funcDecodeRCU[pos]; ptr_inst->funcDecodeInit = inst->funcDecodeInit[pos]; ptr_inst->funcDecodePLC = inst->funcDecodePLC[pos]; ptr_inst->funcGetMDinfo = inst->funcGetMDinfo[pos]; ptr_inst->funcUpdBWEst = inst->funcUpdBWEst[pos]; ptr_inst->funcGetErrorCode = inst->funcGetErrorCode[pos]; ptr_inst->codec_fs = inst->codec_fs[pos]; return 0; } else { WebRtcSpl_MemSetW16((WebRtc_Word16*) ptr_inst, 0, sizeof(CodecFuncInst_t) / sizeof(WebRtc_Word16)); return CODEC_DB_NOT_EXIST1; } }
int WebRtcNetEQ_RTCPInit(WebRtcNetEQ_RTCP_t *RTCP_inst, uint16_t uw16_seqNo) { /* * Initialize everything to zero and then set the start values for the RTP packet stream. */ WebRtcSpl_MemSetW16((int16_t*) RTCP_inst, 0, sizeof(WebRtcNetEQ_RTCP_t) / sizeof(int16_t)); RTCP_inst->base_seq = uw16_seqNo; RTCP_inst->max_seq = uw16_seqNo; return 0; }
WebRtc_Word16 WebRtcIlbcfix_NetEqPlc(iLBC_decinst_t *iLBCdec_inst, WebRtc_Word16 *decoded, WebRtc_Word16 noOfLostFrames) { /* Two input parameters not used, but needed for function pointers in NetEQ */ (void)(decoded = NULL); (void)(noOfLostFrames = 0); WebRtcSpl_MemSetW16(((iLBC_Dec_Inst_t*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL); ((iLBC_Dec_Inst_t*)iLBCdec_inst)->prev_enh_pl = 2; return (0); }
int16_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst, int16_t* decoded, int16_t noOfLostFrames) { /* Two input parameters not used, but needed for function pointers in NetEQ */ (void)(decoded = NULL); (void)(noOfLostFrames = 0); WebRtcSpl_MemSetW16(((IlbcDecoder*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL); ((IlbcDecoder*)iLBCdec_inst)->prev_enh_pl = 2; return (0); }
void WebRtcIlbcfix_Enhancer(int16_t * odata, /* (o) smoothed block, dimension blockl */ int16_t * idata, /* (i) data buffer used for enhancing */ int16_t idatal, /* (i) dimension idata */ int16_t centerStartPos, /* (i) first sample current block within idata */ int16_t * period, /* (i) pitch period array (pitch bward-in time) */ int16_t * plocs, /* (i) locations where period array values valid */ int16_t periodl /* (i) dimension of period and plocs */ ) { /* Stack based */ int16_t surround[ENH_BLOCKL]; WebRtcSpl_MemSetW16(surround, 0, ENH_BLOCKL); /* get said second sequence of segments */ WebRtcIlbcfix_GetSyncSeq(idata, idatal, centerStartPos, period, plocs, periodl, ENH_HL, surround); /* compute the smoothed output from said second sequence */ WebRtcIlbcfix_Smooth(odata, idata + centerStartPos, surround); }
int WebRtcNetEQ_DbReset(CodecDbInst_t *inst) { int i; WebRtcSpl_MemSetW16((WebRtc_Word16*) inst, 0, sizeof(CodecDbInst_t) / sizeof(WebRtc_Word16)); for (i = 0; i < NUM_TOTAL_CODECS; i++) { inst->position[i] = -1; } for (i = 0; i < NUM_CODECS; i++) { inst->payloadType[i] = -1; } for (i = 0; i < NUM_CNG_CODECS; i++) { inst->CNGpayloadType[i] = -1; } return 0; }
WebRtc_Word16 WebRtcIlbcfix_InitDecode( /* (o) Number of decoded samples */ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */ WebRtc_Word16 mode, /* (i) frame size mode */ int use_enhancer) { /* (i) 1: use enhancer, 0: no enhancer */ int i; iLBCdec_inst->mode = mode; /* Set all the variables that are dependent on the frame size mode */ if (mode==30) { iLBCdec_inst->blockl = BLOCKL_30MS; iLBCdec_inst->nsub = NSUB_30MS; iLBCdec_inst->nasub = NASUB_30MS; iLBCdec_inst->lpc_n = LPC_N_30MS; iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS; iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS; iLBCdec_inst->state_short_len=STATE_SHORT_LEN_30MS; } else if (mode==20) { iLBCdec_inst->blockl = BLOCKL_20MS; iLBCdec_inst->nsub = NSUB_20MS; iLBCdec_inst->nasub = NASUB_20MS; iLBCdec_inst->lpc_n = LPC_N_20MS; iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS; iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS; iLBCdec_inst->state_short_len=STATE_SHORT_LEN_20MS; } else { return(-1); } /* Reset all the previous LSF to mean LSF */ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER); /* Clear the synthesis filter memory */ WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER); /* Set the old synthesis filter to {1.0 0.0 ... 0.0} */ WebRtcSpl_MemSetW16(iLBCdec_inst->old_syntdenum, 0, ((LPC_FILTERORDER + 1)*NSUB_MAX)); for (i=0; i<NSUB_MAX; i++) { iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)] = 4096; } /* Clear the variables that are used for the PLC */ iLBCdec_inst->last_lag = 20; iLBCdec_inst->consPLICount = 0; iLBCdec_inst->prevPLI = 0; iLBCdec_inst->perSquare = 0; iLBCdec_inst->prevLag = 120; iLBCdec_inst->prevLpc[0] = 4096; WebRtcSpl_MemSetW16(iLBCdec_inst->prevLpc+1, 0, LPC_FILTERORDER); WebRtcSpl_MemSetW16(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX); /* Initialize the seed for the random number generator */ iLBCdec_inst->seed = 777; /* Set the filter state of the HP filter to 0 */ WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2); WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4); /* Set the variables that are used in the ehnahcer */ iLBCdec_inst->use_enhancer = use_enhancer; WebRtcSpl_MemSetW16(iLBCdec_inst->enh_buf, 0, (ENH_BUFL+ENH_BUFL_FILTEROVERHEAD)); for (i=0;i<ENH_NBLOCKS_TOT;i++) { iLBCdec_inst->enh_period[i]=160; /* Q(-4) */ } iLBCdec_inst->prev_enh_pl = 0; return (iLBCdec_inst->blockl); }
void WebRtcIlbcfix_EncodeImpl( WebRtc_UWord16 *bytes, /* (o) encoded data bits iLBC */ const WebRtc_Word16 *block, /* (i) speech vector to encode */ iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder state */ ){ int n, meml_gotten, Nfor, Nback; WebRtc_Word16 diff, start_pos; int index; int subcount, subframe; WebRtc_Word16 start_count, end_count; WebRtc_Word16 *residual; WebRtc_Word32 en1, en2; WebRtc_Word16 scale, max; WebRtc_Word16 *syntdenum; WebRtc_Word16 *decresidual; WebRtc_Word16 *reverseResidual; WebRtc_Word16 *reverseDecresidual; /* Stack based */ WebRtc_Word16 weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX]; WebRtc_Word16 dataVec[BLOCKL_MAX + LPC_FILTERORDER]; WebRtc_Word16 memVec[CB_MEML+CB_FILTERLEN]; WebRtc_Word16 bitsMemory[sizeof(iLBC_bits)/sizeof(WebRtc_Word16)]; iLBC_bits *iLBCbits_inst = (iLBC_bits*)bitsMemory; #ifdef SPLIT_10MS WebRtc_Word16 *weightdenumbuf = iLBCenc_inst->weightdenumbuf; WebRtc_Word16 last_bit; #endif WebRtc_Word16 *data = &dataVec[LPC_FILTERORDER]; WebRtc_Word16 *mem = &memVec[CB_HALFFILTERLEN]; /* Reuse som buffers to save stack memory */ residual = &iLBCenc_inst->lpc_buffer[LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl]; syntdenum = mem; /* syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX] and mem are used non overlapping in the code */ decresidual = residual; /* Already encoded residual is overwritten by the decoded version */ reverseResidual = data; /* data and reverseResidual are used non overlapping in the code */ reverseDecresidual = reverseResidual; /* Already encoded residual is overwritten by the decoded version */ #ifdef SPLIT_10MS WebRtcSpl_MemSetW16 ( (WebRtc_Word16 *) iLBCbits_inst, 0, (WebRtc_Word16) (sizeof(iLBC_bits) / sizeof(WebRtc_Word16)) ); start_pos = iLBCenc_inst->start_pos; diff = iLBCenc_inst->diff; if (iLBCenc_inst->section != 0){ WEBRTC_SPL_MEMCPY_W16 (weightdenum, weightdenumbuf, SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM); /* Un-Packetize the frame into parameters */ last_bit = WebRtcIlbcfix_UnpackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode); if (last_bit) return; /* adjust index */ WebRtcIlbcfix_IndexConvDec (iLBCbits_inst->cb_index); if (iLBCenc_inst->section == 1){ /* Save first 80 samples of a 160/240 sample frame for 20/30msec */ WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples, block, 80); } else{ // iLBCenc_inst->section == 2 AND mode = 30ms /* Save second 80 samples of a 240 sample frame for 30msec */ WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples + 80, block, 80); } } else{ // iLBCenc_inst->section == 0 /* form a complete frame of 160/240 for 20msec/30msec mode */ WEBRTC_SPL_MEMCPY_W16 (data + (iLBCenc_inst->mode * 8) - 80, block, 80); WEBRTC_SPL_MEMCPY_W16 (data, iLBCenc_inst->past_samples, (iLBCenc_inst->mode * 8) - 80); iLBCenc_inst->Nfor_flag = 0; iLBCenc_inst->Nback_flag = 0; #else /* copy input block to data*/ WEBRTC_SPL_MEMCPY_W16(data,block,iLBCenc_inst->blockl); #endif /* high pass filtering of input signal and scale down the residual (*0.5) */ WebRtcIlbcfix_HpInput(data, (WebRtc_Word16*)WebRtcIlbcfix_kHpInCoefs, iLBCenc_inst->hpimemy, iLBCenc_inst->hpimemx, iLBCenc_inst->blockl); /* LPC of hp filtered input data */ WebRtcIlbcfix_LpcEncode(syntdenum, weightdenum, iLBCbits_inst->lsf, data, iLBCenc_inst); /* Set up state */ WEBRTC_SPL_MEMCPY_W16(dataVec, iLBCenc_inst->anaMem, LPC_FILTERORDER); /* inverse filter to get residual */ for (n=0; n<iLBCenc_inst->nsub; n++ ) { WebRtcSpl_FilterMAFastQ12( &data[n*SUBL], &residual[n*SUBL], &syntdenum[n*(LPC_FILTERORDER+1)], LPC_FILTERORDER+1, SUBL); } /* Copy the state for next frame */ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->anaMem, &data[iLBCenc_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER); /* find state location */ iLBCbits_inst->startIdx = WebRtcIlbcfix_FrameClassify(iLBCenc_inst,residual); /* check if state should be in first or last part of the two subframes */ index = (iLBCbits_inst->startIdx-1)*SUBL; max=WebRtcSpl_MaxAbsValueW16(&residual[index], 2*SUBL); scale=WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(max,max)); /* Scale to maximum 25 bits so that the MAC won't cause overflow */ scale = scale - 25; if(scale < 0) { scale = 0; } diff = STATE_LEN - iLBCenc_inst->state_short_len; en1=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index], iLBCenc_inst->state_short_len, scale); index += diff; en2=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index], iLBCenc_inst->state_short_len, scale); if (en1 > en2) { iLBCbits_inst->state_first = 1; start_pos = (iLBCbits_inst->startIdx-1)*SUBL; } else { iLBCbits_inst->state_first = 0; start_pos = (iLBCbits_inst->startIdx-1)*SUBL + diff; } /* scalar quantization of state */ WebRtcIlbcfix_StateSearch(iLBCenc_inst, iLBCbits_inst, &residual[start_pos], &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)], &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)]); WebRtcIlbcfix_StateConstruct(iLBCbits_inst->idxForMax, iLBCbits_inst->idxVec, &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)], &decresidual[start_pos], iLBCenc_inst->state_short_len ); /* predictive quantization in state */ if (iLBCbits_inst->state_first) { /* put adaptive part in the end */ /* setup memory */ WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-iLBCenc_inst->state_short_len)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCenc_inst->state_short_len, decresidual+start_pos, iLBCenc_inst->state_short_len); /* encode subframes */ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index, &residual[start_pos+iLBCenc_inst->state_short_len], mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff, &weightdenum[iLBCbits_inst->startIdx*(LPC_FILTERORDER+1)], 0); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct(&decresidual[start_pos+iLBCenc_inst->state_short_len], iLBCbits_inst->cb_index, iLBCbits_inst->gain_index, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff ); } else { /* put adaptive part in the beginning */ /* create reversed vectors for prediction */ WebRtcSpl_MemCpyReversedOrder(&reverseResidual[diff-1], &residual[(iLBCbits_inst->startIdx+1)*SUBL-STATE_LEN], diff); /* setup memory */ meml_gotten = iLBCenc_inst->state_short_len; WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[start_pos], meml_gotten); WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-iLBCenc_inst->state_short_len)); /* encode subframes */ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index, reverseResidual, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff, &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)], 0); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct(reverseDecresidual, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff ); /* get decoded residual from reversed vector */ WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff); } #ifdef SPLIT_10MS iLBCenc_inst->start_pos = start_pos; iLBCenc_inst->diff = diff; iLBCenc_inst->section++; /* adjust index */ WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index); /* Packetize the parameters into the frame */ WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode); WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum, SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM); return; } #endif /* forward prediction of subframes */ Nfor = iLBCenc_inst->nsub-iLBCbits_inst->startIdx-1; /* counter for predicted subframes */ #ifdef SPLIT_10MS if (iLBCenc_inst->mode == 20) { subcount = 1; } if (iLBCenc_inst->mode == 30) { if (iLBCenc_inst->section == 1) { subcount = 1; } if (iLBCenc_inst->section == 2) { subcount = 3; } } #else subcount=1; #endif if( Nfor > 0 ){ /* setup memory */ WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN, decresidual+(iLBCbits_inst->startIdx-1)*SUBL, STATE_LEN); #ifdef SPLIT_10MS if (iLBCenc_inst->Nfor_flag > 0) { for (subframe = 0; subframe < WEBRTC_SPL_MIN (Nfor, 2); subframe++) { /* update memory */ WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL)); WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL, &decresidual[(iLBCbits_inst->startIdx + 1 + subframe) * SUBL], SUBL); } } iLBCenc_inst->Nfor_flag++; if (iLBCenc_inst->mode == 20) { start_count = 0; end_count = Nfor; } if (iLBCenc_inst->mode == 30) { if (iLBCenc_inst->section == 1) { start_count = 0; end_count = WEBRTC_SPL_MIN (Nfor, 2); } if (iLBCenc_inst->section == 2) { start_count = WEBRTC_SPL_MIN (Nfor, 2); end_count = Nfor; } } #else start_count = 0; end_count = (WebRtc_Word16)Nfor; #endif /* loop over subframes to encode */ for (subframe = start_count; subframe < end_count; subframe++){ /* encode subframe */ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES, iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &residual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], mem, MEM_LF_TBL, SUBL, &weightdenum[(iLBCbits_inst->startIdx+1+subframe)*(LPC_FILTERORDER+1)], (WebRtc_Word16)subcount); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct(&decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], iLBCbits_inst->cb_index+subcount*CB_NSTAGES, iLBCbits_inst->gain_index+subcount*CB_NSTAGES, mem, MEM_LF_TBL, SUBL ); /* update memory */ WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, (CB_MEML-SUBL)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL, &decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], SUBL); subcount++; } } #ifdef SPLIT_10MS if ((iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 30) && (Nfor > 0) && (end_count == 2)) { iLBCenc_inst->section++; /* adjust index */ WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index); /* Packetize the parameters into the frame */ WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode); WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum, SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM); return; } #endif /* backward prediction of subframes */ Nback = iLBCbits_inst->startIdx-1; if( Nback > 0 ){ /* create reverse order vectors (The decresidual does not need to be copied since it is contained in the same vector as the residual) */ WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL); /* setup memory */ meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx); if( meml_gotten > CB_MEML ) { meml_gotten=CB_MEML; } WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten); WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-meml_gotten)); #ifdef SPLIT_10MS if (iLBCenc_inst->Nback_flag > 0) { for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++) { /* update memory */ WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL)); WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL, &reverseDecresidual[subframe * SUBL], SUBL); } } iLBCenc_inst->Nback_flag++; if (iLBCenc_inst->mode == 20) { start_count = 0; end_count = Nback; } if (iLBCenc_inst->mode == 30) { if (iLBCenc_inst->section == 1) { start_count = 0; end_count = WEBRTC_SPL_MAX (2 - Nfor, 0); } if (iLBCenc_inst->section == 2) { start_count = WEBRTC_SPL_MAX (2 - Nfor, 0); end_count = Nback; } } #else start_count = 0; end_count = (WebRtc_Word16)Nback; #endif /* loop over subframes to encode */ for (subframe = start_count; subframe < end_count; subframe++){ /* encode subframe */ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES, iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL], mem, MEM_LF_TBL, SUBL, &weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)], (WebRtc_Word16)subcount); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct(&reverseDecresidual[subframe*SUBL], iLBCbits_inst->cb_index+subcount*CB_NSTAGES, iLBCbits_inst->gain_index+subcount*CB_NSTAGES, mem, MEM_LF_TBL, SUBL ); /* update memory */ WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, (CB_MEML-SUBL)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL, &reverseDecresidual[subframe*SUBL], SUBL); subcount++; } /* get decoded residual from reversed vector */ WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback); } /* end encoding part */ /* adjust index */ WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index); /* Packetize the parameters into the frame */ #ifdef SPLIT_10MS if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){ WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode); } else{ WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode); } #else WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode); #endif #ifndef WEBRTC_BIG_ENDIAN /* Swap bytes for LITTLE ENDIAN since the packbits() function assumes BIG_ENDIAN machine */ #ifdef SPLIT_10MS if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) || ( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){ WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes); } #else WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes); #endif #endif #ifdef SPLIT_10MS if (subcount == (iLBCenc_inst->nsub - 1)) { iLBCenc_inst->section = 0; } else { iLBCenc_inst->section++; WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum, SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM); } #endif }
void WebRtcIlbcfix_CbSearch( IlbcEncoder *iLBCenc_inst, /* (i) the encoder state structure */ int16_t *index, /* (o) Codebook indices */ int16_t *gain_index, /* (o) Gain quantization indices */ int16_t *intarget, /* (i) Target vector for encoding */ int16_t *decResidual,/* (i) Decoded residual for codebook construction */ int16_t lMem, /* (i) Length of buffer */ int16_t lTarget, /* (i) Length of vector */ int16_t *weightDenum,/* (i) weighting filter coefficients in Q12 */ int16_t block /* (i) the subblock number */ ) { int16_t i, j, stage, range; int16_t *pp, scale, tmp; int16_t bits, temp1, temp2; int16_t base_size; int32_t codedEner, targetEner; int16_t gains[CB_NSTAGES+1]; int16_t *cb_vecPtr; int16_t indexOffset, sInd, eInd; int32_t CritMax=0; int16_t shTotMax=WEBRTC_SPL_WORD16_MIN; int16_t bestIndex=0; int16_t bestGain=0; int16_t indexNew, CritNewSh; int32_t CritNew; int32_t *cDotPtr; int16_t noOfZeros; int16_t *gainPtr; int32_t t32, tmpW32; int16_t *WebRtcIlbcfix_kGainSq5_ptr; /* Stack based */ int16_t CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN]; int32_t cDot[128]; int32_t Crit[128]; int16_t targetVec[SUBL+LPC_FILTERORDER]; int16_t cbvectors[CB_MEML + 1]; /* Adding one extra position for Coverity warnings. */ int16_t codedVec[SUBL]; int16_t interpSamples[20*4]; int16_t interpSamplesFilt[20*4]; int16_t energyW16[CB_EXPAND*128]; int16_t energyShifts[CB_EXPAND*128]; int16_t *inverseEnergy=energyW16; /* Reuse memory */ int16_t *inverseEnergyShifts=energyShifts; /* Reuse memory */ int16_t *buf = &CBbuf[LPC_FILTERORDER]; int16_t *target = &targetVec[LPC_FILTERORDER]; int16_t *aug_vec = (int16_t*)cDot; /* length [SUBL], reuse memory */ /* Determine size of codebook sections */ base_size=lMem-lTarget+1; if (lTarget==SUBL) { base_size=lMem-19; } /* weighting of the CB memory */ noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block]; WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER); WebRtcSpl_FilterARFastQ12( decResidual+noOfZeros, buf+noOfZeros, weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]); /* weighting of the target vector */ WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER); WebRtcSpl_FilterARFastQ12( intarget, target, weightDenum, LPC_FILTERORDER+1, lTarget); /* Store target, towards the end codedVec is calculated as the initial target minus the remaining target */ WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget); /* Find the highest absolute value to calculate proper vector scale factor (so that it uses 12 bits) */ temp1 = WebRtcSpl_MaxAbsValueW16(buf, (int16_t)lMem); temp2 = WebRtcSpl_MaxAbsValueW16(target, (int16_t)lTarget); if ((temp1>0)&&(temp2>0)) { temp1 = WEBRTC_SPL_MAX(temp1, temp2); scale = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(temp1, temp1)); } else { /* temp1 or temp2 is negative (maximum was -32768) */ scale = 30; } /* Scale to so that a mul-add 40 times does not overflow */ scale = scale - 25; scale = WEBRTC_SPL_MAX(0, scale); /* Compute energy of the original target */ targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale); /* Prepare search over one more codebook section. This section is created by filtering the original buffer with a filter. */ WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]); range = WebRtcIlbcfix_kSearchRange[block][0]; if(lTarget == SUBL) { /* Create the interpolated samples and store them for use in all stages */ /* First section, non-filtered half of the cb */ WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem); /* Second section, filtered half of the cb */ WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem); /* Compute the CB vectors' energies for the first cb section (non-filtered) */ WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf, scale, 20, energyW16, energyShifts); /* Compute the CB vectors' energies for the second cb section (filtered cb) */ WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors, scale, (int16_t)(base_size+20), energyW16, energyShifts); /* Compute the CB vectors' energies and store them in the vector * energyW16. Also the corresponding shift values are stored. The * energy values are used in all three stages. */ WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem, lTarget, energyW16+20, energyShifts+20, scale, base_size); } else { /* Compute the CB vectors' energies and store them in the vector * energyW16. Also the corresponding shift values are stored. The * energy values are used in all three stages. */ WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem, lTarget, energyW16, energyShifts, scale, base_size); /* Set the energy positions 58-63 and 122-127 to zero (otherwise they are uninitialized) */ WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range)); WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range)); } /* Calculate Inverse Energy (energyW16 is already normalized and will contain the inverse energy in Q29 after this call */ WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND); /* The gain value computed in the previous stage is used * as an upper limit to what the next stage gain value * is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as * the upper limit. */ gains[0] = 16384; for (stage=0; stage<CB_NSTAGES; stage++) { /* Set up memories */ range = WebRtcIlbcfix_kSearchRange[block][stage]; /* initialize search measures */ CritMax=0; shTotMax=-100; bestIndex=0; bestGain=0; /* loop over lags 40+ in the first codebook section, full search */ cb_vecPtr = buf+lMem-lTarget; /* Calculate all the cross correlations (augmented part of CB) */ if (lTarget==SUBL) { WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem, interpSamples, cDot, 20, 39, scale); cDotPtr=&cDot[20]; } else { cDotPtr=cDot; } /* Calculate all the cross correlations (main part of CB) */ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1); /* Adjust the search range for the augmented vectors */ if (lTarget==SUBL) { range=WebRtcIlbcfix_kSearchRange[block][stage]+20; } else { range=WebRtcIlbcfix_kSearchRange[block][stage]; } indexOffset=0; /* Search for best index in this part of the vector */ WebRtcIlbcfix_CbSearchCore( cDot, range, stage, inverseEnergy, inverseEnergyShifts, Crit, &indexNew, &CritNew, &CritNewSh); /* Update the global best index and the corresponding gain */ WebRtcIlbcfix_CbUpdateBestIndex( CritNew, CritNewSh, (int16_t)(indexNew+indexOffset), cDot[indexNew+indexOffset], inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], &CritMax, &shTotMax, &bestIndex, &bestGain); sInd=bestIndex-(int16_t)(CB_RESRANGE>>1); eInd=sInd+CB_RESRANGE; if (sInd<0) { eInd-=sInd; sInd=0; } if (eInd>=range) { eInd=range-1; sInd=eInd-CB_RESRANGE; } range = WebRtcIlbcfix_kSearchRange[block][stage]; if (lTarget==SUBL) { i=sInd; if (sInd<20) { WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors+lMem, interpSamplesFilt, cDot, (int16_t)(sInd+20), (int16_t)(WEBRTC_SPL_MIN(39, (eInd+20))), scale); i=20; } cDotPtr=&cDot[WEBRTC_SPL_MAX(0,(20-sInd))]; cb_vecPtr = cbvectors+lMem-20-i; /* Calculate the cross correlations (main part of the filtered CB) */ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (int16_t)(eInd-i+1), scale, -1); } else { cDotPtr = cDot; cb_vecPtr = cbvectors+lMem-lTarget-sInd; /* Calculate the cross correlations (main part of the filtered CB) */ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (int16_t)(eInd-sInd+1), scale, -1); } /* Adjust the search range for the augmented vectors */ indexOffset=base_size+sInd; /* Search for best index in this part of the vector */ WebRtcIlbcfix_CbSearchCore( cDot, (int16_t)(eInd-sInd+1), stage, inverseEnergy+indexOffset, inverseEnergyShifts+indexOffset, Crit, &indexNew, &CritNew, &CritNewSh); /* Update the global best index and the corresponding gain */ WebRtcIlbcfix_CbUpdateBestIndex( CritNew, CritNewSh, (int16_t)(indexNew+indexOffset), cDot[indexNew], inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], &CritMax, &shTotMax, &bestIndex, &bestGain); index[stage] = bestIndex; bestGain = WebRtcIlbcfix_GainQuant(bestGain, (int16_t)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]); /* Extract the best (according to measure) codebook vector Also adjust the index, so that the augmented vectors are last. Above these vectors were first... */ if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) { if(index[stage]<base_size) { pp=buf+lMem-lTarget-index[stage]; } else { pp=cbvectors+lMem-lTarget- index[stage]+base_size; } } else { if (index[stage]<base_size) { if (index[stage]>=20) { /* Adjust index and extract vector */ index[stage]-=20; pp=buf+lMem-lTarget-index[stage]; } else { /* Adjust index and extract vector */ index[stage]+=(base_size-20); WebRtcIlbcfix_CreateAugmentedVec((int16_t)(index[stage]-base_size+40), buf+lMem, aug_vec); pp = aug_vec; } } else { if ((index[stage] - base_size) >= 20) { /* Adjust index and extract vector */ index[stage]-=20; pp=cbvectors+lMem-lTarget- index[stage]+base_size; } else { /* Adjust index and extract vector */ index[stage]+=(base_size-20); WebRtcIlbcfix_CreateAugmentedVec((int16_t)(index[stage]-2*base_size+40), cbvectors+lMem, aug_vec); pp = aug_vec; } } } /* Subtract the best codebook vector, according to measure, from the target vector */ WebRtcSpl_AddAffineVectorToVector(target, pp, (int16_t)(-bestGain), (int32_t)8192, (int16_t)14, (int)lTarget); /* record quantized gain */ gains[stage+1] = bestGain; } /* end of Main Loop. for (stage=0;... */ /* Calculte the coded vector (original target - what's left) */ for (i=0;i<lTarget;i++) { codedVec[i]-=target[i]; } /* Gain adjustment for energy matching */ codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale); j=gain_index[0]; temp1 = (int16_t)WebRtcSpl_NormW32(codedEner); temp2 = (int16_t)WebRtcSpl_NormW32(targetEner); if(temp1 < temp2) { bits = 16 - temp1; } else { bits = 16 - temp2; } tmp = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(gains[1],gains[1], 14); targetEner = WEBRTC_SPL_MUL_16_16( WEBRTC_SPL_SHIFT_W32(targetEner, -bits), tmp); tmpW32 = ((int32_t)(gains[1]-1))<<1; /* Pointer to the table that contains gain_sq5TblFIX * gain_sq5TblFIX in Q14 */ gainPtr=(int16_t*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0]; temp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(codedEner, -bits); WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[j]; /* targetEner and codedEner are in Q(-2*scale) */ for (i=gain_index[0];i<32;i++) { /* Change the index if (codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND gainTbl[i] < 2*gain[0] */ t32 = WEBRTC_SPL_MUL_16_16(temp1, (*gainPtr)); t32 = t32 - targetEner; if (t32 < 0) { if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) { j=i; WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[i]; } } gainPtr++; } gain_index[0]=j; return; }
void WebRtcSpl_ZerosArrayW16(int16_t *vector, size_t length) { WebRtcSpl_MemSetW16(vector, 0, length); }
void WebRtcIlbcfix_GetCbVec( int16_t *cbvec, /* (o) Constructed codebook vector */ int16_t *mem, /* (i) Codebook buffer */ int16_t index, /* (i) Codebook index */ int16_t lMem, /* (i) Length of codebook buffer */ int16_t cbveclen /* (i) Codebook vector length */ ){ int16_t k, base_size; int16_t lag; /* Stack based */ int16_t tempbuff2[SUBL+5]; /* Determine size of codebook sections */ base_size=lMem-cbveclen+1; if (cbveclen==SUBL) { base_size+=WEBRTC_SPL_RSHIFT_W16(cbveclen,1); } /* No filter -> First codebook section */ if (index<lMem-cbveclen+1) { /* first non-interpolated vectors */ k=index+cbveclen; /* get vector */ WEBRTC_SPL_MEMCPY_W16(cbvec, mem+lMem-k, cbveclen); } else if (index < base_size) { /* Calculate lag */ k=(int16_t)WEBRTC_SPL_MUL_16_16(2, (index-(lMem-cbveclen+1)))+cbveclen; lag=WEBRTC_SPL_RSHIFT_W16(k, 1); WebRtcIlbcfix_CreateAugmentedVec(lag, mem+lMem, cbvec); } /* Higher codebbok section based on filtering */ else { int16_t memIndTest; /* first non-interpolated vectors */ if (index-base_size<lMem-cbveclen+1) { /* Set up filter memory, stuff zeros outside memory buffer */ memIndTest = lMem-(index-base_size+cbveclen); WebRtcSpl_MemSetW16(mem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN); WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN); /* do filtering to get the codebook vector */ WebRtcSpl_FilterMAFastQ12( &mem[memIndTest+4], cbvec, (int16_t*)WebRtcIlbcfix_kCbFiltersRev, CB_FILTERLEN, cbveclen); } /* interpolated vectors */ else { /* Stuff zeros outside memory buffer */ memIndTest = lMem-cbveclen-CB_FILTERLEN; WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN); /* do filtering */ WebRtcSpl_FilterMAFastQ12( &mem[memIndTest+7], tempbuff2, (int16_t*)WebRtcIlbcfix_kCbFiltersRev, CB_FILTERLEN, (int16_t)(cbveclen+5)); /* Calculate lag index */ lag = (cbveclen<<1)-20+index-base_size-lMem-1; WebRtcIlbcfix_CreateAugmentedVec(lag, tempbuff2+SUBL+5, cbvec); } } }
void WebRtcIlbcfix_DecodeResidual( IlbcDecoder *iLBCdec_inst, /* (i/o) the decoder state structure */ iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used for the decoding */ int16_t *decresidual, /* (o) decoded residual frame */ int16_t *syntdenum /* (i) the decoded synthesis filter coefficients */ ) { int16_t meml_gotten, Nfor, Nback, diff, start_pos; int16_t subcount, subframe; int16_t *reverseDecresidual = iLBCdec_inst->enh_buf; /* Reversed decoded data, used for decoding backwards in time (reuse memory in state) */ int16_t *memVec = iLBCdec_inst->prevResidual; /* Memory for codebook and filter state (reuse memory in state) */ int16_t *mem = &memVec[CB_HALFFILTERLEN]; /* Memory for codebook */ diff = STATE_LEN - iLBCdec_inst->state_short_len; if (iLBC_encbits->state_first == 1) { start_pos = (iLBC_encbits->startIdx-1)*SUBL; } else { start_pos = (iLBC_encbits->startIdx-1)*SUBL + diff; } /* decode scalar part of start state */ WebRtcIlbcfix_StateConstruct(iLBC_encbits->idxForMax, iLBC_encbits->idxVec, &syntdenum[(iLBC_encbits->startIdx-1)*(LPC_FILTERORDER+1)], &decresidual[start_pos], iLBCdec_inst->state_short_len ); if (iLBC_encbits->state_first) { /* put adaptive part in the end */ /* setup memory */ WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-iLBCdec_inst->state_short_len)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCdec_inst->state_short_len, decresidual+start_pos, iLBCdec_inst->state_short_len); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct( &decresidual[start_pos+iLBCdec_inst->state_short_len], iLBC_encbits->cb_index, iLBC_encbits->gain_index, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, (int16_t)diff ); } else {/* put adaptive part in the beginning */ /* setup memory */ meml_gotten = iLBCdec_inst->state_short_len; WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1, decresidual+start_pos, meml_gotten); WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-meml_gotten)); /* construct decoded vector */ WebRtcIlbcfix_CbConstruct( reverseDecresidual, iLBC_encbits->cb_index, iLBC_encbits->gain_index, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff ); /* get decoded residual from reversed vector */ WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff); } /* counter for predicted subframes */ subcount=1; /* forward prediction of subframes */ Nfor = iLBCdec_inst->nsub-iLBC_encbits->startIdx-1; if( Nfor > 0 ) { /* setup memory */ WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN, decresidual+(iLBC_encbits->startIdx-1)*SUBL, STATE_LEN); /* loop over subframes to encode */ for (subframe=0; subframe<Nfor; subframe++) { /* construct decoded vector */ WebRtcIlbcfix_CbConstruct( &decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], iLBC_encbits->cb_index+subcount*CB_NSTAGES, iLBC_encbits->gain_index+subcount*CB_NSTAGES, mem, MEM_LF_TBL, SUBL ); /* update memory */ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL, &decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], SUBL); subcount++; } } /* backward prediction of subframes */ Nback = iLBC_encbits->startIdx-1; if( Nback > 0 ){ /* setup memory */ meml_gotten = SUBL*(iLBCdec_inst->nsub+1-iLBC_encbits->startIdx); if( meml_gotten > CB_MEML ) { meml_gotten=CB_MEML; } WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1, decresidual+(iLBC_encbits->startIdx-1)*SUBL, meml_gotten); WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-meml_gotten)); /* loop over subframes to decode */ for (subframe=0; subframe<Nback; subframe++) { /* construct decoded vector */ WebRtcIlbcfix_CbConstruct( &reverseDecresidual[subframe*SUBL], iLBC_encbits->cb_index+subcount*CB_NSTAGES, iLBC_encbits->gain_index+subcount*CB_NSTAGES, mem, MEM_LF_TBL, SUBL ); /* update memory */ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem)); WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL, &reverseDecresidual[subframe*SUBL], SUBL); subcount++; } /* get decoded residual from reversed vector */ WebRtcSpl_MemCpyReversedOrder(decresidual+SUBL*Nback-1, reverseDecresidual, SUBL*Nback); } }
void WebRtcIlbcfix_Refiner( WebRtc_Word16 *updStartPos, /* (o) updated start point (Q-2) */ WebRtc_Word16 *idata, /* (i) original data buffer */ WebRtc_Word16 idatal, /* (i) dimension of idata */ WebRtc_Word16 centerStartPos, /* (i) beginning center segment */ WebRtc_Word16 estSegPos, /* (i) estimated beginning other segment (Q-2) */ WebRtc_Word16 *surround, /* (i/o) The contribution from this sequence summed with earlier contributions */ WebRtc_Word16 gain /* (i) Gain to use for this sequence */ ){ WebRtc_Word16 estSegPosRounded,searchSegStartPos,searchSegEndPos,corrdim; WebRtc_Word16 tloc,tloc2,i,st,en,fraction; WebRtc_Word32 maxtemp, scalefact; WebRtc_Word16 *filtStatePtr, *polyPtr; /* Stack based */ WebRtc_Word16 filt[7]; WebRtc_Word32 corrVecUps[ENH_CORRDIM*ENH_UPS0]; WebRtc_Word32 corrVecTemp[ENH_CORRDIM]; WebRtc_Word16 vect[ENH_VECTL]; WebRtc_Word16 corrVec[ENH_CORRDIM]; /* defining array bounds */ estSegPosRounded=WEBRTC_SPL_RSHIFT_W16((estSegPos - 2),2); searchSegStartPos=estSegPosRounded-ENH_SLOP; if (searchSegStartPos<0) { searchSegStartPos=0; } searchSegEndPos=estSegPosRounded+ENH_SLOP; if(searchSegEndPos+ENH_BLOCKL >= idatal) { searchSegEndPos=idatal-ENH_BLOCKL-1; } corrdim=searchSegEndPos-searchSegStartPos+1; /* compute upsampled correlation and find location of max */ WebRtcIlbcfix_MyCorr(corrVecTemp,idata+searchSegStartPos, (WebRtc_Word16)(corrdim+ENH_BLOCKL-1),idata+centerStartPos,ENH_BLOCKL); /* Calculate the rescaling factor for the correlation in order to put the correlation in a WebRtc_Word16 vector instead */ maxtemp=WebRtcSpl_MaxAbsValueW32(corrVecTemp, (WebRtc_Word16)corrdim); scalefact=WebRtcSpl_GetSizeInBits(maxtemp)-15; if (scalefact>0) { for (i=0;i<corrdim;i++) { corrVec[i]=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(corrVecTemp[i], scalefact); } } else { for (i=0;i<corrdim;i++) { corrVec[i]=(WebRtc_Word16)corrVecTemp[i]; } } /* In order to guarantee that all values are initialized */ for (i=corrdim;i<ENH_CORRDIM;i++) { corrVec[i]=0; } /* Upsample the correlation */ WebRtcIlbcfix_EnhUpsample(corrVecUps,corrVec); /* Find maximum */ tloc=WebRtcSpl_MaxIndexW32(corrVecUps, (WebRtc_Word16) (ENH_UPS0*corrdim)); /* make vector can be upsampled without ever running outside bounds */ *updStartPos = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(searchSegStartPos,4) + tloc + 4; tloc2 = WEBRTC_SPL_RSHIFT_W16((tloc+3), 2); st=searchSegStartPos+tloc2-ENH_FL0; /* initialize the vector to be filtered, stuff with zeros when data is outside idata buffer */ if(st<0){ WebRtcSpl_MemSetW16(vect, 0, (WebRtc_Word16)(-st)); WEBRTC_SPL_MEMCPY_W16(&vect[-st], idata, (ENH_VECTL+st)); } else{ en=st+ENH_VECTL; if(en>idatal){ WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], (ENH_VECTL-(en-idatal))); WebRtcSpl_MemSetW16(&vect[ENH_VECTL-(en-idatal)], 0, (WebRtc_Word16)(en-idatal)); } else { WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], ENH_VECTL); } } /* Calculate which of the 4 fractions to use */ fraction=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(tloc2,ENH_UPS0)-tloc; /* compute the segment (this is actually a convolution) */ filtStatePtr = filt + 6; polyPtr = (WebRtc_Word16*)WebRtcIlbcfix_kEnhPolyPhaser[fraction]; for (i=0;i<7;i++) { *filtStatePtr-- = *polyPtr++; } WebRtcSpl_FilterMAFastQ12( &vect[6], vect, filt, ENH_FLO_MULT2_PLUS1, ENH_BLOCKL); /* Add the contribution from this vector (scaled with gain) to the total surround vector */ WebRtcSpl_AddAffineVectorToVector( surround, vect, gain, (WebRtc_Word32)32768, 16, ENH_BLOCKL); return; }
void WebRtcIlbcfix_SimpleLpcAnalysis( WebRtc_Word16 *lsf, /* (o) lsf coefficients */ WebRtc_Word16 *data, /* (i) new block of speech */ iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the encoder state structure */ ) { int k; int scale; WebRtc_Word16 is; WebRtc_Word16 stability; /* Stack based */ WebRtc_Word16 A[LPC_FILTERORDER + 1]; WebRtc_Word32 R[LPC_FILTERORDER + 1]; WebRtc_Word16 windowedData[BLOCKL_MAX]; WebRtc_Word16 rc[LPC_FILTERORDER]; is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl; WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lpc_buffer+is,data,iLBCenc_inst->blockl); /* No lookahead, last window is asymmetric */ for (k = 0; k < iLBCenc_inst->lpc_n; k++) { is = LPC_LOOKBACK; if (k < (iLBCenc_inst->lpc_n - 1)) { /* Hanning table WebRtcIlbcfix_kLpcWin[] is in Q15-domain so the output is right-shifted 15 */ WebRtcSpl_ElementwiseVectorMult(windowedData, iLBCenc_inst->lpc_buffer, WebRtcIlbcfix_kLpcWin, BLOCKL_MAX, 15); } else { /* Hanning table WebRtcIlbcfix_kLpcAsymWin[] is in Q15-domain so the output is right-shifted 15 */ WebRtcSpl_ElementwiseVectorMult(windowedData, iLBCenc_inst->lpc_buffer+is, WebRtcIlbcfix_kLpcAsymWin, BLOCKL_MAX, 15); } /* Compute autocorrelation */ WebRtcSpl_AutoCorrelation(windowedData, BLOCKL_MAX, LPC_FILTERORDER, R, &scale); /* Window autocorrelation vector */ WebRtcIlbcfix_Window32W32(R, R, WebRtcIlbcfix_kLpcLagWin, LPC_FILTERORDER + 1 ); /* Calculate the A coefficients from the Autocorrelation using Levinson Durbin algorithm */ stability=WebRtcSpl_LevinsonDurbin(R, A, rc, LPC_FILTERORDER); /* Set the filter to {1.0, 0.0, 0.0,...} if filter from Levinson Durbin algorithm is unstable This should basically never happen... */ if (stability!=1) { A[0]=4096; WebRtcSpl_MemSetW16(&A[1], 0, LPC_FILTERORDER); } /* Bandwidth expand the filter coefficients */ WebRtcIlbcfix_BwExpand(A, A, (WebRtc_Word16*)WebRtcIlbcfix_kLpcChirpSyntDenum, LPC_FILTERORDER+1); /* Convert from A to LSF representation */ WebRtcIlbcfix_Poly2Lsf(lsf + k*LPC_FILTERORDER, A); } is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl; WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lpc_buffer, iLBCenc_inst->lpc_buffer+LPC_LOOKBACK+BLOCKL_MAX-is, is); return; }