| /* | |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| /* | |
| * decode_B.c | |
| * | |
| * This file contains definition of funtions for decoding. | |
| * Decoding of lower-band, including normal-decoding and RCU decoding. | |
| * Decoding of upper-band, including 8-12 kHz, when the bandwidth is | |
| * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz. | |
| * | |
| */ | |
| #include "codec.h" | |
| #include "entropy_coding.h" | |
| #include "pitch_estimator.h" | |
| #include "bandwidth_estimator.h" | |
| #include "structs.h" | |
| #include "settings.h" | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| /* | |
| * 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; | |
| } | |
| /* | |
| * This decode function is called when the codec is operating in 16 kHz | |
| * bandwidth to decode the upperband, i.e. 8-16 kHz. | |
| * | |
| * Contrary to lower-band, the upper-band (8-16 kHz) is not split in | |
| * frequency, but split to 12 sub-frames, i.e. twice as lower-band. | |
| */ | |
| int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables, | |
| float* signal_out, ISACUBDecStruct* ISACdecUB_obj, | |
| int16_t isRCUPayload) { | |
| int len, err; | |
| double halfFrameFirst[FRAMESAMPLES_HALF]; | |
| double halfFrameSecond[FRAMESAMPLES_HALF]; | |
| double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) + | |
| (UB_LPC_ORDER + 1)]; | |
| double real_f[FRAMESAMPLES_HALF]; | |
| double imag_f[FRAMESAMPLES_HALF]; | |
| const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */ | |
| len = 0; | |
| /* Decode & de-quantize filter coefficients. */ | |
| memset(percepFilterParam, 0, sizeof(percepFilterParam)); | |
| err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj, | |
| percepFilterParam, isac16kHz); | |
| if (err < 0) { | |
| return err; | |
| } | |
| /* Decode & de-quantize spectrum. */ | |
| len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain, | |
| kIsacUpperBand16, real_f, imag_f); | |
| if (len < 0) { | |
| return len; | |
| } | |
| if (isRCUPayload) { | |
| int n; | |
| for (n = 0; n < 240; n++) { | |
| real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE; | |
| imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE; | |
| } | |
| } | |
| /* Inverse transform. */ | |
| WebRtcIsac_Spec2time(transform_tables, | |
| real_f, imag_f, halfFrameFirst, halfFrameSecond, | |
| &ISACdecUB_obj->fftstr_obj); | |
| /* Perceptual post-filtering (using normalized lattice filter). */ | |
| WebRtcIsac_NormLatticeFilterAr( | |
| UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF, | |
| (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst, | |
| &percepFilterParam[(UB_LPC_ORDER + 1)], signal_out); | |
| WebRtcIsac_NormLatticeFilterAr( | |
| UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF, | |
| (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond, | |
| &percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)], | |
| &signal_out[FRAMESAMPLES_HALF]); | |
| return len; | |
| } | |
| /* | |
| * This decode function is called when the codec operates at 0-12 kHz | |
| * bandwidth to decode the upperband, i.e. 8-12 kHz. | |
| * | |
| * At the encoder the upper-band is split into two band, 8-12 kHz & 12-16 | |
| * kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is | |
| * reconstructed and 12-16 kHz replaced with zeros. Then two bands | |
| * are combined, to reconstruct the upperband 8-16 kHz. | |
| */ | |
| int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables, | |
| float* signal_out, ISACUBDecStruct* ISACdecUB_obj, | |
| int16_t isRCUPayload) { | |
| int len, err; | |
| float LP_dec_float[FRAMESAMPLES_HALF]; | |
| float HP_dec_float[FRAMESAMPLES_HALF]; | |
| double LPw[FRAMESAMPLES_HALF]; | |
| double HPw[FRAMESAMPLES_HALF]; | |
| double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES]; | |
| double real_f[FRAMESAMPLES_HALF]; | |
| double imag_f[FRAMESAMPLES_HALF]; | |
| const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */ | |
| len = 0; | |
| /* Decode & dequantize filter coefficients. */ | |
| err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj, | |
| percepFilterParam, isac12kHz); | |
| if (err < 0) { | |
| return err; | |
| } | |
| /* Decode & de-quantize spectrum. */ | |
| len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain, | |
| kIsacUpperBand12, real_f, imag_f); | |
| if (len < 0) { | |
| return len; | |
| } | |
| if (isRCUPayload) { | |
| int n; | |
| for (n = 0; n < 240; n++) { | |
| real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE; | |
| imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE; | |
| } | |
| } | |
| /* Inverse transform. */ | |
| WebRtcIsac_Spec2time(transform_tables, | |
| real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj); | |
| /* perceptual post-filtering (using normalized lattice filter) */ | |
| WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER, | |
| ISACdecUB_obj->maskfiltstr_obj.PostStateLoF, | |
| (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, | |
| LPw, percepFilterParam, LP_dec_float); | |
| /* Zero for 12-16 kHz. */ | |
| memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF)); | |
| /* Recombine the 2 bands. */ | |
| WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out, | |
| &ISACdecUB_obj->postfiltbankstr_obj); | |
| return len; | |
| } |