This new lib contains the bare minimum to implement an iSAC encoder and decoder. The webrtc files have been copied from the revision as the existing imported files (c8b569e0a7ad0b369e15f0197b3a558699ec8efa).
305 lines
10 KiB
C
305 lines
10 KiB
C
/*
|
|
* 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;
|
|
}
|