mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-24 18:41:57 +00:00
331 lines
10 KiB
C
331 lines
10 KiB
C
|
/*
|
||
|
* Copyright (c) 2011 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(
|
||
|
float* signal_out,
|
||
|
ISACLBDecStruct* ISACdecLB_obj,
|
||
|
WebRtc_Word16* current_framesamples,
|
||
|
WebRtc_Word16 isRCUPayload)
|
||
|
{
|
||
|
int k, model;
|
||
|
int len, err;
|
||
|
WebRtc_Word16 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;
|
||
|
WebRtc_Word16 PitchGains_Q12[4];
|
||
|
WebRtc_Word16 AvgPitchGain_Q12;
|
||
|
|
||
|
float gain;
|
||
|
|
||
|
int frame_nb; /* counter */
|
||
|
int frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */
|
||
|
int processed_samples;
|
||
|
|
||
|
(ISACdecLB_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
|
||
|
(ISACdecLB_obj->bitstr_obj).streamval = 0;
|
||
|
(ISACdecLB_obj->bitstr_obj).stream_index = 0;
|
||
|
|
||
|
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) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
/* frame_mode: 0, or 1 */
|
||
|
frame_mode = *current_framesamples/MAX_FRAMESAMPLES;
|
||
|
/* processed_samples: either 320 (20ms) or 480 (30, 60 ms) */
|
||
|
processed_samples = *current_framesamples/(frame_mode+1);
|
||
|
|
||
|
err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
|
||
|
if (err < 0) { // error check
|
||
|
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 & dequantize pitch parameters */
|
||
|
err = WebRtcIsac_DecodePitchGain(&(ISACdecLB_obj->bitstr_obj),
|
||
|
PitchGains_Q12);
|
||
|
if (err < 0) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj,
|
||
|
PitchGains_Q12, PitchLags);
|
||
|
if (err < 0) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
|
||
|
PitchGains_Q12[2] + PitchGains_Q12[3])>>2;
|
||
|
|
||
|
/* decode & dequantize FiltCoef */
|
||
|
err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj,
|
||
|
lo_filt_coef,hi_filt_coef, &model);
|
||
|
if (err < 0) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
/* decode & dequantize spectrum */
|
||
|
len = WebRtcIsac_DecodeSpecLb(&ISACdecLB_obj->bitstr_obj,
|
||
|
real_f, imag_f, AvgPitchGain_Q12);
|
||
|
if (len < 0) { // error check
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
/* inverse transform */
|
||
|
WebRtcIsac_Spec2time(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 * processed_samples,
|
||
|
&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(
|
||
|
float* signal_out,
|
||
|
ISACUBDecStruct* ISACdecUB_obj,
|
||
|
WebRtc_Word16 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];
|
||
|
|
||
|
len = 0;
|
||
|
|
||
|
/* decode & dequantize FiltCoef */
|
||
|
memset(percepFilterParam, 0, sizeof(percepFilterParam));
|
||
|
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
|
||
|
percepFilterParam, isac16kHz);
|
||
|
if (err < 0) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
/* decode & dequantize spectrum */
|
||
|
len = WebRtcIsac_DecodeSpecUB16(&ISACdecUB_obj->bitstr_obj, real_f,
|
||
|
imag_f);
|
||
|
if (len < 0) { // error check
|
||
|
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(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(
|
||
|
float* signal_out,
|
||
|
ISACUBDecStruct* ISACdecUB_obj,
|
||
|
WebRtc_Word16 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];
|
||
|
|
||
|
len = 0;
|
||
|
|
||
|
/* decode & dequantize FiltCoef */
|
||
|
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
|
||
|
percepFilterParam, isac12kHz);
|
||
|
if(err < 0) { // error check
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
/* decode & dequantize spectrum */
|
||
|
len = WebRtcIsac_DecodeSpecUB12(&ISACdecUB_obj->bitstr_obj,
|
||
|
real_f, imag_f);
|
||
|
if(len < 0) { // error check
|
||
|
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(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);
|
||
|
|
||
|
/* Zerro for upper-band */
|
||
|
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;
|
||
|
}
|