blob: 3f1912b6d374f2c7b7b39a0fdf38ebdb97dd190f [file] [log] [blame]
/*
* 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.
*/
/*
* encode.c
*
* This file contains definition of funtions for encoding.
* 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "structs.h"
#include "codec.h"
#include "pitch_estimator.h"
#include "entropy_coding.h"
#include "arith_routines.h"
#include "pitch_gain_tables.h"
#include "pitch_lag_tables.h"
#include "spectrum_ar_model_tables.h"
#include "lpc_tables.h"
#include "lpc_analysis.h"
#include "bandwidth_estimator.h"
#include "lpc_shape_swb12_tables.h"
#include "lpc_shape_swb16_tables.h"
#include "lpc_gain_swb_tables.h"
#define UB_LOOKAHEAD 24
/*
Rate allocation tables of lower and upper-band bottleneck for
12kHz & 16kHz bandwidth.
12 kHz bandwidth
-----------------
The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
considered 7 enteries, uniformly distributed in this interval, i.e. 38,
39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
and the upper-band bottlenecks are specified in
'kLowerBandBitRate12' and 'kUpperBandBitRate12'
tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
overall bottleneck of the codec, we use linear interpolation to get
lower-band and upper-band bottlenecks.
16 kHz bandwidth
-----------------
The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
bottlenecks are specified in 'kLowerBandBitRate16' and
'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
kbps for upper-band. Given an overall bottleneck of the codec, we use linear
interpolation to get lower-band and upper-band bottlenecks.
*/
/* 38 39.17 40.33 41.5 42.67 43.83 45 */
static const int16_t kLowerBandBitRate12[7] = {
29000, 30000, 30000, 31000, 31000, 32000, 32000 };
static const int16_t kUpperBandBitRate12[7] = {
25000, 25000, 27000, 27000, 29000, 29000, 32000 };
/* 50 51.2 52.4 53.6 54.8 56 */
static const int16_t kLowerBandBitRate16[6] = {
31000, 31000, 32000, 32000, 32000, 32000 };
static const int16_t kUpperBandBitRate16[6] = {
28000, 29000, 29000, 30000, 31000, 32000 };
/******************************************************************************
* WebRtcIsac_RateAllocation()
* Internal function to perform a rate-allocation for upper and lower-band,
* given a total rate.
*
* Input:
* - inRateBitPerSec : a total bottleneck in bits/sec.
*
* Output:
* - rateLBBitPerSec : a bottleneck allocated to the lower-band
* in bits/sec.
* - rateUBBitPerSec : a bottleneck allocated to the upper-band
* in bits/sec.
*
* Return value : 0 if rate allocation has been successful.
* -1 if failed to allocate rates.
*/
int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
double* rateLBBitPerSec,
double* rateUBBitPerSec,
enum ISACBandwidth* bandwidthKHz) {
int16_t idx;
double idxD;
double idxErr;
if (inRateBitPerSec < 38000) {
/* If the given overall bottleneck is less than 38000 then
* then codec has to operate in wideband mode, i.e. 8 kHz
* bandwidth. */
*rateLBBitPerSec = (int16_t)((inRateBitPerSec > 32000) ?
32000 : inRateBitPerSec);
*rateUBBitPerSec = 0;
*bandwidthKHz = isac8kHz;
} else if ((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000)) {
/* At a bottleneck between 38 and 50 kbps the codec is operating
* at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
* upper/lower bottleneck */
/* Find the bottlenecks by linear interpolation,
* step is (45000 - 38000)/6.0 we use the inverse of it. */
const double stepSizeInv = 8.5714286e-4;
idxD = (inRateBitPerSec - 38000) * stepSizeInv;
idx = (idxD >= 6) ? 6 : ((int16_t)idxD);
idxErr = idxD - idx;
*rateLBBitPerSec = kLowerBandBitRate12[idx];
*rateUBBitPerSec = kUpperBandBitRate12[idx];
if (idx < 6) {
*rateLBBitPerSec += (int16_t)(
idxErr * (kLowerBandBitRate12[idx + 1] - kLowerBandBitRate12[idx]));
*rateUBBitPerSec += (int16_t)(
idxErr * (kUpperBandBitRate12[idx + 1] - kUpperBandBitRate12[idx]));
}
*bandwidthKHz = isac12kHz;
} else if ((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000)) {
/* A bottleneck between 50 and 56 kbps corresponds to bandwidth
* of 16 kHz. Using xxxBandBitRate16[] to calculates
* upper/lower bottleneck. */
/* Find the bottlenecks by linear interpolation
* step is (56000 - 50000)/5 we use the inverse of it. */
const double stepSizeInv = 8.3333333e-4;
idxD = (inRateBitPerSec - 50000) * stepSizeInv;
idx = (idxD >= 5) ? 5 : ((int16_t)idxD);
idxErr = idxD - idx;
*rateLBBitPerSec = kLowerBandBitRate16[idx];
*rateUBBitPerSec = kUpperBandBitRate16[idx];
if (idx < 5) {
*rateLBBitPerSec += (int16_t)(idxErr *
(kLowerBandBitRate16[idx + 1] -
kLowerBandBitRate16[idx]));
*rateUBBitPerSec += (int16_t)(idxErr *
(kUpperBandBitRate16[idx + 1] -
kUpperBandBitRate16[idx]));
}
*bandwidthKHz = isac16kHz;
} else {
/* Out-of-range botlteneck value. */
return -1;
}
/* limit the values. */
*rateLBBitPerSec = (*rateLBBitPerSec > 32000) ? 32000 : *rateLBBitPerSec;
*rateUBBitPerSec = (*rateUBBitPerSec > 32000) ? 32000 : *rateUBBitPerSec;
return 0;
}
void WebRtcIsac_ResetBitstream(Bitstr* bit_stream) {
bit_stream->W_upper = 0xFFFFFFFF;
bit_stream->stream_index = 0;
bit_stream->streamval = 0;
}
int WebRtcIsac_EncodeLb(const TransformTables* transform_tables,
float* in, ISACLBEncStruct* ISACencLB_obj,
int16_t codingMode,
int16_t 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];
int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
double PitchLags[4];
double PitchGains[4];
int16_t PitchGains_Q12[4];
int16_t AvgPitchGain_Q12;
int frame_mode; /* 0 for 30ms, 1 for 60ms */
int status = 0;
int my_index;
transcode_obj transcodingParam;
double bytesLeftSpecCoding;
uint16_t 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] = (int16_t)(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) {
/* It is a 30ms frame */
/* Subract 3 because termination process may add 3 bytes. */
payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
} else {
/* This is the second half of a 60ms frame. */
/* Subract 3 because termination process may add 3 bytes. */
payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
}
bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
/* Perceptual pre-filtering (using normalized lattice filter). */
/* Low-band filtering. */
WebRtcIsac_NormLatticeFilterMa(ORDERLO,
ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
ISACencLB_obj->maskfiltstr_obj.PreStateLoG,
LP, lofilt_coef, LPw);
/* High-band filtering. */
WebRtcIsac_NormLatticeFilterMa(ORDERHI,
ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
ISACencLB_obj->maskfiltstr_obj.PreStateHiG,
HP, hifilt_coef, HPw);
/* Pitch filter. */
WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
PitchLags, PitchGains);
/* Transform */
WebRtcIsac_Time2Spec(transform_tables,
LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj);
/* Save data for multiple packets memory. */
my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
ISACencLB_obj->SaveEnc_obj.AvgPitchGain[ISACencLB_obj->SaveEnc_obj.startIdx] =
AvgPitchGain_Q12;
/* Quantization and loss-less coding. */
err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
&ISACencLB_obj->bitstr_obj);
if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
/* There has been an error but it was not too large payload
(we can cure too large payload). */
if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
/* If this is the second 30ms of a 60ms frame reset
this such that in the next call encoder starts fresh. */
ISACencLB_obj->frame_nb = 0;
}
return err;
}
iterCntr = 0;
while ((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
(err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
double bytesSpecCoderUsed;
double transcodeScale;
if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
/* We were not able to limit the payload size */
if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
/* This was the first 30ms of a 60ms frame. Although
the payload is larger than it should be but we let
the second 30ms be encoded. Maybe together we
won't exceed the limit. */
ISACencLB_obj->frame_nb = 1;
return 0;
} else if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
ISACencLB_obj->frame_nb = 0;
}
if (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
} else {
return status;
}
}
if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
bytesSpecCoderUsed = STREAM_SIZE_MAX;
/* Being conservative */
transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
} else {
bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
transcodingParam.stream_index;
transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
}
/* To be safe, we reduce the scale depending on
the number of iterations. */
transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
(double)MAX_PAYLOAD_LIMIT_ITERATION));
/* Scale the LPC Gains. */
for (k = 0; k < SUBFRAMES; k++) {
lofilt_coef[(LPC_LOBAND_ORDER + 1) * k] =
transcodingParam.loFiltGain[k] * transcodeScale;
hifilt_coef[(LPC_HIBAND_ORDER + 1) * k] =
transcodingParam.hiFiltGain[k] * transcodeScale;
transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
}
/* Scale DFT coefficients. */
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
fre[k] = (int16_t)(fre[k] * transcodeScale);
fim[k] = (int16_t)(fim[k] * transcodeScale);
}
/* Save data for multiple packets memory. */
my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
/* Re-store the state of arithmetic coder before coding LPC gains. */
ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
transcodingParam.stream[0];
ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
transcodingParam.stream[1];
ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
transcodingParam.stream[2];
/* Code gains. */
WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
&ISACencLB_obj->bitstr_obj,
&ISACencLB_obj->SaveEnc_obj);
/* Update the number of bytes left for encoding the spectrum. */
bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
/* Encode the spectrum. */
err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
&ISACencLB_obj->bitstr_obj);
if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
/* There has been an error but it was not too large
payload (we can cure too large payload). */
if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
/* If this is the second 30 ms of a 60 ms frame reset
this such that in the next call encoder starts fresh. */
ISACencLB_obj->frame_nb = 0;
}
return err;
}
iterCntr++;
}
/* If 60 ms frame-size and just processed the first 30 ms, */
/* go back to main function to buffer the other 30 ms speech frame. */
if (frame_mode == 1) {
if (ISACencLB_obj->frame_nb == 0) {
ISACencLB_obj->frame_nb = 1;
return 0;
} else if (ISACencLB_obj->frame_nb == 1) {
ISACencLB_obj->frame_nb = 0;
/* Also update the frame-length for next packet,
in Adaptive mode only. */
if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0)) {
ISACencLB_obj->new_framelength =
WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
ISACencLB_obj->current_framesamples);
}
}
} else {
ISACencLB_obj->frame_nb = 0;
}
/* Complete arithmetic coding. */
stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
return stream_length;
}
static int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj,
uint16_t payloadLimitBytes,
double bytesLeftSpecCoding,
transcode_obj* transcodingParam,
int16_t* fre, int16_t* fim,
double* lpcGains, enum ISACBand band, int status) {
int iterCntr = 0;
int k;
double bytesSpecCoderUsed;
double transcodeScale;
const int16_t kAveragePitchGain = 0.0;
do {
if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
/* We were not able to limit the payload size. */
return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
}
if (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
bytesSpecCoderUsed = STREAM_SIZE_MAX;
/* Being conservative. */
transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
} else {
bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
transcodingParam->stream_index;
transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
}
/* To be safe, we reduce the scale depending on the
number of iterations. */
transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
(double)MAX_PAYLOAD_LIMIT_ITERATION));
/* Scale the LPC Gains. */
if (band == kIsacUpperBand16) {
/* Two sets of coefficients if 16 kHz. */
for (k = 0; k < SUBFRAMES; k++) {
transcodingParam->loFiltGain[k] *= transcodeScale;
transcodingParam->hiFiltGain[k] *= transcodeScale;
}
} else {
/* One sets of coefficients if 12 kHz. */
for (k = 0; k < SUBFRAMES; k++) {
transcodingParam->loFiltGain[k] *= transcodeScale;
}
}
/* Scale DFT coefficients. */
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
fre[k] = (int16_t)(fre[k] * transcodeScale + 0.5);
fim[k] = (int16_t)(fim[k] * transcodeScale + 0.5);
}
/* Store FFT coefficients for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
/* Store the state of arithmetic coder before coding LPC gains */
ISACencUB_obj->bitstr_obj.W_upper = transcodingParam->W_upper;
ISACencUB_obj->bitstr_obj.stream_index = transcodingParam->stream_index;
ISACencUB_obj->bitstr_obj.streamval = transcodingParam->streamval;
ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 2] =
transcodingParam->stream[0];
ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 1] =
transcodingParam->stream[1];
ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index] =
transcodingParam->stream[2];
/* Store the gains for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
SUBFRAMES * sizeof(double));
/* Entropy Code lpc-gains, indices are stored for a later use.*/
WebRtcIsac_EncodeLpcGainUb(transcodingParam->loFiltGain,
&ISACencUB_obj->bitstr_obj,
ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
/* If 16kHz should do one more set. */
if (band == kIsacUpperBand16) {
/* Store the gains for multiple encoding. */
memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain[SUBFRAMES],
&lpcGains[SUBFRAMES], SUBFRAMES * sizeof(double));
/* Entropy Code lpc-gains, indices are stored for a later use.*/
WebRtcIsac_EncodeLpcGainUb(
transcodingParam->hiFiltGain, &ISACencUB_obj->bitstr_obj,
&ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
}
/* Update the number of bytes left for encoding the spectrum. */
bytesLeftSpecCoding = payloadLimitBytes -
ISACencUB_obj->bitstr_obj.stream_index;
/* Save the bit-stream object at this point for FEC. */
memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
&ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
/* Encode the spectrum. */
status = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain,
band, &ISACencUB_obj->bitstr_obj);
if ((status < 0) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
/* There has been an error but it was not too large payload
(we can cure too large payload). */
return status;
}
iterCntr++;
} while ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
(status == -ISAC_DISALLOWED_BITSTREAM_LENGTH));
return 0;
}
int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables,
float* in, ISACUBEncStruct* ISACencUB_obj,
int32_t jitterInfo) {
int err;
int k;
double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES << 1) +
(1 + UB_LPC_ORDER)];
double LP_lookahead[FRAMESAMPLES];
int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
int status = 0;
double varscale[2];
double corr[SUBFRAMES << 1][UB_LPC_ORDER + 1];
double lpcGains[SUBFRAMES << 1];
transcode_obj transcodingParam;
uint16_t payloadLimitBytes;
double s2nr;
const int16_t kAveragePitchGain = 0.0;
int bytesLeftSpecCoding;
/* Buffer speech samples (by 10ms packet) until the frame-length is */
/* reached (30 ms). */
/*********************************************************************/
/* fill the buffer with 10ms input data */
memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
FRAMESAMPLES_10ms * sizeof(float));
/* If buffer size is not equal to current frame-size, and end of file is
* not reached yet, we don't do encoding unless we have the whole frame. */
if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
return 0;
}
/* End of buffer function. */
/**************************/
/* Encoding */
/************/
/* Reset bit-stream */
WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
/* Encoding of bandwidth information. */
WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
status = WebRtcIsac_EncodeBandwidth(isac16kHz, &ISACencUB_obj->bitstr_obj);
if (status < 0) {
return status;
}
s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
for (k = 0; k < FRAMESAMPLES; k++) {
LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
}
/* Find coefficients for perceptual pre-filters. */
WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
&lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
memcpy(ISACencUB_obj->lastLPCVec,
&lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
sizeof(double) * UB_LPC_ORDER);
/* Code LPC model and shape - gains not quantized yet. */
WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
percepFilterParams, isac16kHz,
&ISACencUB_obj->SaveEnc_obj);
/* the first set of lpc parameters are from the last sub-frame of
* the previous frame. so we don't care about them. */
WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
(SUBFRAMES << 1), lpcGains, corr, varscale);
/* Store the state of arithmetic coder before coding LPC gains */
transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
transcodingParam.stream[0] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
2];
transcodingParam.stream[1] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
1];
transcodingParam.stream[2] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
/* Store LPC Gains before encoding them. */
for (k = 0; k < SUBFRAMES; k++) {
transcodingParam.loFiltGain[k] = lpcGains[k];
transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
}
/* Store the gains for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
(SUBFRAMES << 1) * sizeof(double));
WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
WebRtcIsac_EncodeLpcGainUb(
&lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
&ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
/* Get the correct value for the payload limit and calculate the number of
bytes left for coding the spectrum. It is a 30ms frame
Subract 3 because termination process may add 3 bytes */
payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
ISACencUB_obj->numBytesUsed - 3;
bytesLeftSpecCoding = payloadLimitBytes -
ISACencUB_obj->bitstr_obj.stream_index;
for (k = 0; k < (SUBFRAMES << 1); k++) {
percepFilterParams[k * (UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
lpcGains[k];
}
/* LPC filtering (using normalized lattice filter), */
/* first half-frame. */
WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
&ISACencUB_obj->data_buffer_float[0],
&percepFilterParams[UB_LPC_ORDER + 1],
&LP_lookahead[0]);
/* Second half-frame filtering. */
WebRtcIsac_NormLatticeFilterMa(
UB_LPC_ORDER, ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
&ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
&percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)],
&LP_lookahead[FRAMESAMPLES_HALF]);
WebRtcIsac_Time2Spec(transform_tables,
&LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF],
fre, fim, &ISACencUB_obj->fftstr_obj);
/* Store FFT coefficients for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, sizeof(fre));
memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim, sizeof(fim));
/* Prepare the audio buffer for the next packet
* move the last 3 ms to the beginning of the buffer. */
memcpy(ISACencUB_obj->data_buffer_float,
&ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
LB_TOTAL_DELAY_SAMPLES * sizeof(float));
/* start writing with 3 ms delay to compensate for the delay
* of the lower-band. */
ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
/* Save the bit-stream object at this point for FEC. */
memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj, &ISACencUB_obj->bitstr_obj,
sizeof(Bitstr));
/* Qantization and lossless coding */
/* Note that there is no pitch-gain for this band so kAveragePitchGain = 0
* is passed to the function. In fact, the function ignores the 3rd parameter
* for this band. */
err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand16,
&ISACencUB_obj->bitstr_obj);
if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
return err;
}
if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
(err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
&transcodingParam, fre, fim, lpcGains,
kIsacUpperBand16, err);
}
if (err < 0) {
return err;
}
/* Complete arithmetic coding. */
return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
}
int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables,
float* in, ISACUBEncStruct* ISACencUB_obj,
int32_t jitterInfo) {
int err;
int k;
double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
float LP[FRAMESAMPLES_HALF];
float HP[FRAMESAMPLES_HALF];
double LP_lookahead[FRAMESAMPLES_HALF];
double HP_lookahead[FRAMESAMPLES_HALF];
double LPw[FRAMESAMPLES_HALF];
double HPw[FRAMESAMPLES_HALF];
int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
int status = 0;
double varscale[1];
double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
double lpcGains[SUBFRAMES];
transcode_obj transcodingParam;
uint16_t payloadLimitBytes;
double s2nr;
const int16_t kAveragePitchGain = 0.0;
double bytesLeftSpecCoding;
/* Buffer speech samples (by 10ms packet) until the framelength is */
/* reached (30 ms). */
/********************************************************************/
/* Fill the buffer with 10ms input data. */
memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
FRAMESAMPLES_10ms * sizeof(float));
/* if buffer-size is not equal to current frame-size then increase the
index and return. We do the encoding when we have enough audio. */
if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
return 0;
}
/* If buffer reached the right size, reset index and continue
with encoding the frame */
ISACencUB_obj->buffer_index = 0;
/* End of buffer function */
/**************************/
/* Encoding */
/************/
/* Reset bit-stream. */
WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
/* Encoding bandwidth information. */
WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
status = WebRtcIsac_EncodeBandwidth(isac12kHz, &ISACencUB_obj->bitstr_obj);
if (status < 0) {
return status;
}
s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
/* Split signal in two bands. */
WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
HP_lookahead, LP_lookahead,
&ISACencUB_obj->prefiltbankstr_obj);
/* Find coefficients for perceptual pre-filters. */
WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
lpcVecs, corr, varscale, isac12kHz);
/* Code LPC model and shape - gains not quantized yet. */
WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
percepFilterParams, isac12kHz,
&ISACencUB_obj->SaveEnc_obj);
WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains, corr,
varscale);
/* Store the state of arithmetic coder before coding LPC gains. */
transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
transcodingParam.stream[0] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
2];
transcodingParam.stream[1] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
1];
transcodingParam.stream[2] =
ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
/* Store LPC Gains before encoding them. */
for (k = 0; k < SUBFRAMES; k++) {
transcodingParam.loFiltGain[k] = lpcGains[k];
}
/* Store the gains for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
sizeof(double));
WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
for (k = 0; k < SUBFRAMES; k++) {
percepFilterParams[k * (UB_LPC_ORDER + 1)] = lpcGains[k];
}
/* perceptual pre-filtering (using normalized lattice filter) */
/* low-band filtering */
WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP,
percepFilterParams, LPw);
/* Get the correct value for the payload limit and calculate the number
of bytes left for coding the spectrum. It is a 30ms frame Subract 3
because termination process may add 3 bytes */
payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
ISACencUB_obj->numBytesUsed - 3;
bytesLeftSpecCoding = payloadLimitBytes -
ISACencUB_obj->bitstr_obj.stream_index;
memset(HPw, 0, sizeof(HPw));
/* Transform */
WebRtcIsac_Time2Spec(transform_tables,
LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj);
/* Store FFT coefficients for multiple encoding. */
memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
/* Save the bit-stream object at this point for FEC. */
memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
&ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
/* Quantization and loss-less coding */
/* The 4th parameter to this function is pitch-gain, which is only used
* when encoding 0-8 kHz band, and irrelevant in this function, therefore,
* we insert zero here. */
err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand12,
&ISACencUB_obj->bitstr_obj);
if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
/* There has been an error but it was not too large
payload (we can cure too large payload) */
return err;
}
if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
(err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
&transcodingParam, fre, fim, lpcGains,
kIsacUpperBand12, err);
}
if (err < 0) {
return err;
}
/* Complete arithmetic coding. */
return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
}
/* This function is used to create a new bit-stream with new BWE.
The same data as previously encoded with the function WebRtcIsac_Encoder().
The data needed is taken from the structure, where it was stored
when calling the encoder. */
int WebRtcIsac_EncodeStoredDataLb(const IsacSaveEncoderData* ISACSavedEnc_obj,
Bitstr* ISACBitStr_obj, int BWnumber,
float scale) {
int ii;
int status;
int BWno = BWnumber;
const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
const uint16_t** cdf;
double tmpLPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * 2];
double tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * 2];
int tmpLPCindex_g[12 * 2];
int16_t tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
const int kModel = 0;
/* Sanity Check - possible values for BWnumber is 0 - 23. */
if ((BWnumber < 0) || (BWnumber > 23)) {
return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
}
/* Reset bit-stream. */
WebRtcIsac_ResetBitstream(ISACBitStr_obj);
/* Encode frame length */
status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
ISACBitStr_obj);
if (status < 0) {
/* Wrong frame size. */
return status;
}
/* Transcoding */
if ((scale > 0.0) && (scale < 1.0)) {
/* Compensate LPC gain. */
for (ii = 0;
ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
ii++) {
tmpLPCcoeffs_lo[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_lo[ii];
}
for (ii = 0;
ii < ((ORDERHI + 1) * SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
ii++) {
tmpLPCcoeffs_hi[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_hi[ii];
}
/* Scale DFT. */
for (ii = 0;
ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
ii++) {
tmp_fre[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fre[ii]);
tmp_fim[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fim[ii]);
}
} else {
for (ii = 0;
ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
ii++) {
tmpLPCindex_g[ii] = ISACSavedEnc_obj->LPCindex_g[ii];
}
for (ii = 0;
ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
ii++) {
tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
}
}
/* Encode bandwidth estimate. */
WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
/* Loop over number of 30 msec */
for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
/* Encode pitch gains. */
*WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
WebRtcIsac_EncHistMulti(ISACBitStr_obj,
&ISACSavedEnc_obj->pitchGain_index[ii],
WebRtcIsac_kQPitchGainCdf_ptr, 1);
/* Entropy coding of quantization pitch lags */
/* Voicing classification. */
if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
} else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
} else {
cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
}
WebRtcIsac_EncHistMulti(ISACBitStr_obj,
&ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES * ii],
cdf, PITCH_SUBFRAMES);
/* LPC */
/* Only one model exists. The entropy coding is done only for backward
* compatibility. */
WebRtcIsac_EncHistMulti(ISACBitStr_obj, &kModel,
WebRtcIsac_kQKltModelCdfPtr, 1);
/* Entropy coding of quantization indices - LPC shape only. */
WebRtcIsac_EncHistMulti(ISACBitStr_obj,
&ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE * ii],
WebRtcIsac_kQKltCdfPtrShape,
KLT_ORDER_SHAPE);
/* If transcoding, get new LPC gain indices */
if (scale < 1.0) {
WebRtcIsac_TranscodeLPCCoef(
&tmpLPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * ii],
&tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * ii],
&tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
}
/* Entropy coding of quantization indices - LPC gain. */
WebRtcIsac_EncHistMulti(ISACBitStr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN * ii],
WebRtcIsac_kQKltCdfPtrGain, KLT_ORDER_GAIN);
/* Quantization and loss-less coding. */
status = WebRtcIsac_EncodeSpec(&tmp_fre[ii * FRAMESAMPLES_HALF],
&tmp_fim[ii * FRAMESAMPLES_HALF],
ISACSavedEnc_obj->AvgPitchGain[ii],
kIsacLowerBand, ISACBitStr_obj);
if (status < 0) {
return status;
}
}
/* Complete arithmetic coding. */
return WebRtcIsac_EncTerminate(ISACBitStr_obj);
}
int WebRtcIsac_EncodeStoredDataUb(
const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
Bitstr* bitStream,
int32_t jitterInfo,
float scale,
enum ISACBandwidth bandwidth) {
int n;
int err;
double lpcGain[SUBFRAMES];
int16_t realFFT[FRAMESAMPLES_HALF];
int16_t imagFFT[FRAMESAMPLES_HALF];
const uint16_t** shape_cdf;
int shape_len;
const int16_t kAveragePitchGain = 0.0;
enum ISACBand band;
/* Reset bitstream. */
WebRtcIsac_ResetBitstream(bitStream);
/* Encode jitter index. */
WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
err = WebRtcIsac_EncodeBandwidth(bandwidth, bitStream);
if (err < 0) {
return err;
}
/* Encode LPC-shape. */
if (bandwidth == isac12kHz) {
shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb12;
shape_len = UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME;
band = kIsacUpperBand12;
} else {
shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb16;
shape_len = UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME;
band = kIsacUpperBand16;
}
WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
shape_cdf, shape_len);
if ((scale <= 0.0) || (scale >= 1.0)) {
/* We only consider scales between zero and one. */
WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
if (bandwidth == isac16kHz) {
/* Store gain indices of the second half. */
WebRtcIsac_EncHistMulti(bitStream,
&ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
}
/* Store FFT coefficients. */
err = WebRtcIsac_EncodeSpec(ISACSavedEnc_obj->realFFT,
ISACSavedEnc_obj->imagFFT, kAveragePitchGain,
band, bitStream);
} else {
/* Scale LPC gain and FFT coefficients. */
for (n = 0; n < SUBFRAMES; n++) {
lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
}
/* Store LPC gains. */
WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
if (bandwidth == isac16kHz) {
/* Scale and code the gains of the second half of the frame, if 16kHz. */
for (n = 0; n < SUBFRAMES; n++) {
lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
}
WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
}
for (n = 0; n < FRAMESAMPLES_HALF; n++) {
realFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->realFFT[n] +
0.5f);
imagFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->imagFFT[n] +
0.5f);
}
/* Store FFT coefficients. */
err = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain,
band, bitStream);
}
if (err < 0) {
/* Error happened while encoding FFT coefficients. */
return err;
}
/* Complete arithmetic coding. */
return WebRtcIsac_EncTerminate(bitStream);
}
int16_t WebRtcIsac_GetRedPayloadUb(
const ISACUBSaveEncDataStruct* ISACSavedEncObj,
Bitstr* bitStreamObj,
enum ISACBandwidth bandwidth) {
int n;
int16_t status;
int16_t realFFT[FRAMESAMPLES_HALF];
int16_t imagFFT[FRAMESAMPLES_HALF];
enum ISACBand band;
const int16_t kAveragePitchGain = 0.0;
/* Store bit-stream object. */
memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
/* Scale FFT coefficients. */
for (n = 0; n < FRAMESAMPLES_HALF; n++) {
realFFT[n] = (int16_t)((float)ISACSavedEncObj->realFFT[n] *
RCU_TRANSCODING_SCALE_UB + 0.5);
imagFFT[n] = (int16_t)((float)ISACSavedEncObj->imagFFT[n] *
RCU_TRANSCODING_SCALE_UB + 0.5);
}
band = (bandwidth == isac12kHz) ? kIsacUpperBand12 : kIsacUpperBand16;
status = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain, band,
bitStreamObj);
if (status < 0) {
return status;
} else {
/* Terminate entropy coding */
return WebRtcIsac_EncTerminate(bitStreamObj);
}
}