Example #1
0
/*
 * 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;
}
Example #2
0
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) {