/* * function to decode the bitstream * returns the total number of bytes in the stream */ int WebRtcIsac_DecodeLb(const TransformTables* transform_tables, float* signal_out, ISACLBDecStruct* ISACdecLB_obj, int16_t* current_framesamples, int16_t isRCUPayload) { int k; int len, err; int16_t bandwidthInd; float LP_dec_float[FRAMESAMPLES_HALF]; float HP_dec_float[FRAMESAMPLES_HALF]; double LPw[FRAMESAMPLES_HALF]; double HPw[FRAMESAMPLES_HALF]; double LPw_pf[FRAMESAMPLES_HALF]; double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES]; double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES]; double real_f[FRAMESAMPLES_HALF]; double imag_f[FRAMESAMPLES_HALF]; double PitchLags[4]; double PitchGains[4]; double AvgPitchGain; int16_t PitchGains_Q12[4]; int16_t AvgPitchGain_Q12; float gain; int frame_nb; /* counter */ int frame_mode; /* 0 30ms, 1 for 60ms */ /* Processed_samples: 480 (30, 60 ms). Cannot take other values. */ WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj)); len = 0; /* Decode framelength and BW estimation - not used, only for stream pointer*/ err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj, current_framesamples); if (err < 0) { return err; } /* Frame_mode: * 0: indicates 30 ms frame (480 samples) * 1: indicates 60 ms frame (960 samples) */ frame_mode = *current_framesamples / MAX_FRAMESAMPLES; err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd); if (err < 0) { return err; } /* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames bundled together (60ms). */ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) { /* Decode & de-quantize pitch parameters */ err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12); if (err < 0) { return err; } err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12, PitchLags); if (err < 0) { return err; } AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2; /* Decode & de-quantize filter coefficients. */ err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef, hi_filt_coef); if (err < 0) { return err; } /* Decode & de-quantize spectrum. */ len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12, kIsacLowerBand, real_f, imag_f); if (len < 0) { return len; } /* Inverse transform. */ WebRtcIsac_Spec2time(transform_tables, real_f, imag_f, LPw, HPw, &ISACdecLB_obj->fftstr_obj); /* Convert PitchGains back to float for pitchfilter_post */ for (k = 0; k < 4; k++) { PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096; } if (isRCUPayload) { for (k = 0; k < 240; k++) { LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE; HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE; } } /* Inverse pitch filter. */ WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj, PitchLags, PitchGains); /* Convert AvgPitchGain back to float for computation of gain. */ AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096; gain = 1.0f - 0.45f * (float)AvgPitchGain; for (k = 0; k < FRAMESAMPLES_HALF; k++) { /* Reduce gain to compensate for pitch enhancer. */ LPw_pf[k] *= gain; } if (isRCUPayload) { for (k = 0; k < FRAMESAMPLES_HALF; k++) { /* Compensation for transcoding gain changes. */ LPw_pf[k] *= RCU_TRANSCODING_SCALE; HPw[k] *= RCU_TRANSCODING_SCALE; } } /* Perceptual post-filtering (using normalized lattice filter). */ WebRtcIsac_NormLatticeFilterAr( ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF, (ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef, LP_dec_float); WebRtcIsac_NormLatticeFilterAr( ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF, (ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef, HP_dec_float); /* Recombine the 2 bands. */ WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float, signal_out + frame_nb * FRAMESAMPLES, &ISACdecLB_obj->postfiltbankstr_obj); } return len; }
int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj, WebRtc_Word16 codingMode, WebRtc_Word16 bottleneckIndex) { int stream_length = 0; int err; int k; int iterCntr; double lofilt_coef[(ORDERLO + 1)*SUBFRAMES]; double hifilt_coef[(ORDERHI + 1)*SUBFRAMES]; float LP[FRAMESAMPLES_HALF]; float HP[FRAMESAMPLES_HALF]; double LP_lookahead[FRAMESAMPLES_HALF]; double HP_lookahead[FRAMESAMPLES_HALF]; double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD]; double LPw[FRAMESAMPLES_HALF]; double HPw[FRAMESAMPLES_HALF]; double LPw_pf[FRAMESAMPLES_HALF]; WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */ double PitchLags[4]; double PitchGains[4]; WebRtc_Word16 PitchGains_Q12[4]; WebRtc_Word16 AvgPitchGain_Q12; int frame_mode; /* 0 for 30ms, 1 for 60ms */ int status = 0; int my_index; transcode_obj transcodingParam; double bytesLeftSpecCoding; WebRtc_UWord16 payloadLimitBytes; /* Copy new frame-length and bottleneck rate only for the first 10 ms data */ if (ISACencLB_obj->buffer_index == 0) { /* Set the framelength for the next packet. */ ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength; } /* 'frame_mode' is 0 (30 ms) or 1 (60 ms). */ frame_mode = ISACencLB_obj->current_framesamples / MAX_FRAMESAMPLES; /* buffer speech samples (by 10ms packet) until the frame-length */ /* is reached (30 or 60 ms). */ /*****************************************************************/ /* fill the buffer with 10ms input data */ for (k = 0; k < FRAMESAMPLES_10ms; k++) { ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] = in[k]; } /* If buffersize is not equal to current framesize then increase index * and return. We do no encoding untill we have enough audio. */ if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != FRAMESAMPLES) { ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms; return 0; } /* If buffer reached the right size, reset index and continue with * encoding the frame. */ ISACencLB_obj->buffer_index = 0; /* End of buffer function. */ /**************************/ /* Encoding */ /************/ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) { /* This is to avoid Linux warnings until we change 'int' to 'Word32' * at all places. */ int intVar; /* reset bitstream */ WebRtcIsac_ResetBitstream(&(ISACencLB_obj->bitstr_obj)); if ((codingMode == 0) && (frame_mode == 0) && (ISACencLB_obj->enforceFrameSize == 0)) { ISACencLB_obj->new_framelength = WebRtcIsac_GetNewFrameLength( ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples); } ISACencLB_obj->s2nr = WebRtcIsac_GetSnr( ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples); /* Encode frame length. */ status = WebRtcIsac_EncodeFrameLen( ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj); if (status < 0) { /* Wrong frame size. */ return status; } /* Save framelength for multiple packets memory. */ ISACencLB_obj->SaveEnc_obj.framelength = ISACencLB_obj->current_framesamples; /* To be used for Redundant Coding. */ ISACencLB_obj->lastBWIdx = bottleneckIndex; intVar = (int)bottleneckIndex; WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj); } /* Split signal in two bands. */ WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP, LP_lookahead, HP_lookahead, &ISACencLB_obj->prefiltbankstr_obj); /* estimate pitch parameters and pitch-filter lookahead signal */ WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf, &ISACencLB_obj->pitchanalysisstr_obj, PitchLags, PitchGains); /* Encode in FIX Q12. */ /* Convert PitchGain to Fixed point. */ for (k = 0; k < PITCH_SUBFRAMES; k++) { PitchGains_Q12[k] = (WebRtc_Word16)(PitchGains[k] * 4096.0); } /* Set where to store data in multiple packets memory. */ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) { ISACencLB_obj->SaveEnc_obj.startIdx = 0; } else { ISACencLB_obj->SaveEnc_obj.startIdx = 1; } /* Quantize & encode pitch parameters. */ WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj); WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12, &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj); AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2; /* Find coefficients for perceptual pre-filters. */ WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead, &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr, PitchGains_Q12, lofilt_coef, hifilt_coef); /* Code LPC model and shape - gains not quantized yet. */ WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj); /* Convert PitchGains back to FLOAT for pitchfilter_pre. */ for (k = 0; k < 4; k++) { PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096; } /* Store the state of arithmetic coder before coding LPC gains. */ transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper; transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index; transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval; transcodingParam.stream[0] = ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index - 2]; transcodingParam.stream[1] = ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index - 1]; transcodingParam.stream[2] = ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index]; /* Store LPC Gains before encoding them. */ for (k = 0; k < SUBFRAMES; k++) { transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k]; transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k]; } /* Code gains */ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj); /* Get the correct value for the payload limit and calculate the * number of bytes left for coding the spectrum. */ if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) { /* It is a 60ms and we are in the first 30ms then the limit at * this point should be half of the assigned value. */ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1; } else if (frame_mode == 0) {