|  | /* | 
|  | *  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. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * isac.c | 
|  | * | 
|  | * This C file contains the functions for the ISAC API | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include "isac.h" | 
|  | #include "bandwidth_estimator.h" | 
|  | #include "crc.h" | 
|  | #include "entropy_coding.h" | 
|  | #include "codec.h" | 
|  | #include "structs.h" | 
|  | #include "signal_processing_library.h" | 
|  | #include "lpc_shape_swb16_tables.h" | 
|  | #include "os_specific_inline.h" | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <stdlib.h> | 
|  | #include <math.h> | 
|  |  | 
|  | #define BIT_MASK_DEC_INIT 0x0001 | 
|  | #define BIT_MASK_ENC_INIT 0x0002 | 
|  |  | 
|  | #define LEN_CHECK_SUM_WORD8     4 | 
|  | #define MAX_NUM_LAYERS         10 | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * UpdatePayloadSizeLimit(...) | 
|  | * | 
|  | * Call this function to update the limit on the payload size. The limit on | 
|  | * payload size might change i) if a user ''directly changes the limit by | 
|  | * calling xxx_setMaxPayloadSize() or xxx_setMaxRate(), or ii) indirectly | 
|  | * when bandwidth is changing. The latter might be the result of bandwidth | 
|  | * adaptation, or direct change of the bottleneck in instantaneous mode. | 
|  | * | 
|  | * This function takes the current overall limit on payload, and translates it | 
|  | * to the limits on lower and upper-band. If the codec is in wideband mode, | 
|  | * then the overall limit and the limit on the lower-band is the same. | 
|  | * Otherwise, a fraction of the limit should be allocated to lower-band | 
|  | * leaving some room for the upper-band bit-stream. That is why an update | 
|  | * of limit is required every time that the bandwidth is changing. | 
|  | * | 
|  | */ | 
|  | static void UpdatePayloadSizeLimit(ISACMainStruct* instISAC) { | 
|  | WebRtc_Word16 lim30MsPayloadBytes = WEBRTC_SPL_MIN( | 
|  | (instISAC->maxPayloadSizeBytes), | 
|  | (instISAC->maxRateBytesPer30Ms)); | 
|  | WebRtc_Word16 lim60MsPayloadBytes = WEBRTC_SPL_MIN( | 
|  | (instISAC->maxPayloadSizeBytes), | 
|  | (instISAC->maxRateBytesPer30Ms << 1)); | 
|  |  | 
|  | /* The only time that iSAC will have 60 ms | 
|  | * frame-size is when operating in wideband, so | 
|  | * there is no upper-band bit-stream. */ | 
|  |  | 
|  | if (instISAC->bandwidthKHz == isac8kHz) { | 
|  | /* At 8 kHz there is no upper-band bit-stream, | 
|  | * therefore, the lower-band limit is the overall limit. */ | 
|  | instISAC->instLB.ISACencLB_obj.payloadLimitBytes60 = | 
|  | lim60MsPayloadBytes; | 
|  | instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 = | 
|  | lim30MsPayloadBytes; | 
|  | } else { | 
|  | /* When in super-wideband, we only have 30 ms frames. | 
|  | * Do a rate allocation for the given limit. */ | 
|  | if (lim30MsPayloadBytes > 250) { | 
|  | /* 4/5 to lower-band the rest for upper-band. */ | 
|  | instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 = | 
|  | (lim30MsPayloadBytes << 2) / 5; | 
|  | } else if (lim30MsPayloadBytes > 200) { | 
|  | /* For the interval of 200 to 250 the share of | 
|  | * upper-band linearly grows from 20 to 50. */ | 
|  | instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 = | 
|  | (lim30MsPayloadBytes << 1) / 5 + 100; | 
|  | } else { | 
|  | /* Allocate only 20 for upper-band. */ | 
|  | instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 = | 
|  | lim30MsPayloadBytes - 20; | 
|  | } | 
|  | instISAC->instUB.ISACencUB_obj.maxPayloadSizeBytes = | 
|  | lim30MsPayloadBytes; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * UpdateBottleneck(...) | 
|  | * | 
|  | * This function updates the bottleneck only if the codec is operating in | 
|  | * channel-adaptive mode. Furthermore, as the update of bottleneck might | 
|  | * result in an update of bandwidth, therefore, the bottlenech should be | 
|  | * updated just right before the first 10ms of a frame is pushed into encoder. | 
|  | * | 
|  | */ | 
|  | static void UpdateBottleneck(ISACMainStruct* instISAC) { | 
|  | /* Read the bottleneck from bandwidth estimator for the | 
|  | * first 10 ms audio. This way, if there is a change | 
|  | * in bandwidth, upper and lower-band will be in sync. */ | 
|  | if ((instISAC->codingMode == 0) && | 
|  | (instISAC->instLB.ISACencLB_obj.buffer_index == 0) && | 
|  | (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) { | 
|  | WebRtc_Word32 bottleneck; | 
|  | WebRtcIsac_GetUplinkBandwidth(&(instISAC->bwestimator_obj), | 
|  | &bottleneck); | 
|  |  | 
|  | /* Adding hysteresis when increasing signal bandwidth. */ | 
|  | if ((instISAC->bandwidthKHz == isac8kHz) | 
|  | && (bottleneck > 37000) | 
|  | && (bottleneck < 41000)) { | 
|  | bottleneck = 37000; | 
|  | } | 
|  |  | 
|  | /* Switching from 12 kHz to 16 kHz is not allowed at this revision. | 
|  | * If we let this happen, we have to take care of buffer_index and | 
|  | * the last LPC vector. */ | 
|  | if ((instISAC->bandwidthKHz != isac16kHz) && | 
|  | (bottleneck > 46000)) { | 
|  | bottleneck = 46000; | 
|  | } | 
|  |  | 
|  | /* We might need a rate allocation. */ | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacWideband) { | 
|  | /* Wideband is the only choice we have here. */ | 
|  | instISAC->instLB.ISACencLB_obj.bottleneck = | 
|  | (bottleneck > 32000) ? 32000 : bottleneck; | 
|  | instISAC->bandwidthKHz = isac8kHz; | 
|  | } else { | 
|  | /* Do the rate-allocation and get the new bandwidth. */ | 
|  | enum ISACBandwidth bandwidth; | 
|  | WebRtcIsac_RateAllocation(bottleneck, | 
|  | &(instISAC->instLB.ISACencLB_obj.bottleneck), | 
|  | &(instISAC->instUB.ISACencUB_obj.bottleneck), | 
|  | &bandwidth); | 
|  | if (bandwidth != isac8kHz) { | 
|  | instISAC->instLB.ISACencLB_obj.new_framelength = 480; | 
|  | } | 
|  | if (bandwidth != instISAC->bandwidthKHz) { | 
|  | /* Bandwidth is changing. */ | 
|  | instISAC->bandwidthKHz = bandwidth; | 
|  | UpdatePayloadSizeLimit(instISAC); | 
|  | if (bandwidth == isac12kHz) { | 
|  | instISAC->instLB.ISACencLB_obj.buffer_index = 0; | 
|  | } | 
|  | /* Currently we don't let the bandwidth to switch to 16 kHz | 
|  | * if in adaptive mode. If we let this happen, we have to take | 
|  | * care of buffer_index and the last LPC vector. */ | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * GetSendBandwidthInfo(...) | 
|  | * | 
|  | * This is called to get the bandwidth info. This info is the bandwidth and | 
|  | * the jitter of 'there-to-here' channel, estimated 'here.' These info | 
|  | * is signaled in an in-band fashion to the other side. | 
|  | * | 
|  | * The call to the bandwidth estimator triggers a recursive averaging which | 
|  | * has to be synchronized between encoder & decoder, therefore, the call to | 
|  | * BWE should be once per packet. As the BWE info is inserted into bit-stream | 
|  | * We need a valid info right before the encodeLB function is going to | 
|  | * generate a bit-stream. That is when lower-band buffer has already 20ms | 
|  | * of audio, and the 3rd block of 10ms is going to be injected into encoder. | 
|  | * | 
|  | * Inputs: | 
|  | *         - instISAC          : iSAC instance. | 
|  | * | 
|  | * Outputs: | 
|  | *         - bandwidthIndex    : an index which has to be encoded in | 
|  | *                               lower-band bit-stream, indicating the | 
|  | *                               bandwidth of there-to-here channel. | 
|  | *         - jitterInfo        : this indicates if the jitter is high | 
|  | *                               or low and it is encoded in upper-band | 
|  | *                               bit-stream. | 
|  | * | 
|  | */ | 
|  | static void GetSendBandwidthInfo(ISACMainStruct* instISAC, | 
|  | WebRtc_Word16* bandwidthIndex, | 
|  | WebRtc_Word16* jitterInfo) { | 
|  | if ((instISAC->instLB.ISACencLB_obj.buffer_index == | 
|  | (FRAMESAMPLES_10ms << 1)) && | 
|  | (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) { | 
|  | /* Bandwidth estimation and coding. */ | 
|  | WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj), | 
|  | bandwidthIndex, jitterInfo, | 
|  | instISAC->decoderSamplingRateKHz); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_AssignSize(...) | 
|  | * | 
|  | * This function returns the size of the ISAC instance, so that the instance | 
|  | * can be created out side iSAC. | 
|  | * | 
|  | * Output: | 
|  | *        - sizeinbytes       : number of bytes needed to allocate for the | 
|  | *                              instance. | 
|  | * | 
|  | * Return value               : 0 - Ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_AssignSize(int* sizeInBytes) { | 
|  | *sizeInBytes = sizeof(ISACMainStruct) * 2 / sizeof(WebRtc_Word16); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_Assign(...) | 
|  | * | 
|  | * This function assigns the memory already created to the ISAC instance. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : address of the pointer to the coder instance. | 
|  | *        - instISAC_Addr     : the already allocated memory, where we put the | 
|  | *                              iSAC structure. | 
|  | * | 
|  | * Return value               : 0 - Ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_Assign(ISACStruct** ISAC_main_inst, | 
|  | void* instISAC_Addr) { | 
|  | if (instISAC_Addr != NULL) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)instISAC_Addr; | 
|  | instISAC->errorCode = 0; | 
|  | instISAC->initFlag = 0; | 
|  |  | 
|  | /* Assign the address. */ | 
|  | *ISAC_main_inst = (ISACStruct*)instISAC_Addr; | 
|  |  | 
|  | /* Default is wideband. */ | 
|  | instISAC->encoderSamplingRateKHz = kIsacWideband; | 
|  | instISAC->decoderSamplingRateKHz = kIsacWideband; | 
|  | instISAC->bandwidthKHz           = isac8kHz; | 
|  | instISAC->in_sample_rate_hz = 16000; | 
|  | return 0; | 
|  | } else { | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_Create(...) | 
|  | * | 
|  | * This function creates an ISAC instance, which will contain the state | 
|  | * information for one coding/decoding channel. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : address of the pointer to the coder instance. | 
|  | * | 
|  | * Return value               : 0 - Ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_Create(ISACStruct** ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC; | 
|  |  | 
|  | instISAC = (ISACMainStruct*)WEBRTC_SPL_VNEW(ISACMainStruct, 1); | 
|  | *ISAC_main_inst = (ISACStruct*)instISAC; | 
|  | if (*ISAC_main_inst != NULL) { | 
|  | instISAC->errorCode = 0; | 
|  | instISAC->initFlag = 0; | 
|  | /* Default is wideband. */ | 
|  | instISAC->bandwidthKHz = isac8kHz; | 
|  | instISAC->encoderSamplingRateKHz = kIsacWideband; | 
|  | instISAC->decoderSamplingRateKHz = kIsacWideband; | 
|  | instISAC->in_sample_rate_hz = 16000; | 
|  | return 0; | 
|  | } else { | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_Free(...) | 
|  | * | 
|  | * This function frees the ISAC instance created at the beginning. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : a ISAC instance. | 
|  | * | 
|  | * Return value               : 0 - Ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_Free(ISACStruct* ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WEBRTC_SPL_FREE(instISAC); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * EncoderInitLb(...) - internal function for initialization of | 
|  | *                                Lower Band | 
|  | * EncoderInitUb(...) - internal function for initialization of | 
|  | *                                Upper Band | 
|  | * WebRtcIsac_EncoderInit(...) - API function | 
|  | * | 
|  | * This function initializes a ISAC instance prior to the encoder calls. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - CodingMode        : 0 -> Bit rate and frame length are automatically | 
|  | *                                 adjusted to available bandwidth on | 
|  | *                                 transmission channel, applicable just to | 
|  | *                                 wideband mode. | 
|  | *                              1 -> User sets a frame length and a target bit | 
|  | *                                 rate which is taken as the maximum | 
|  | *                                 short-term average bit rate. | 
|  | * | 
|  | * Return value               :  0 - Ok | 
|  | *                              -1 - Error | 
|  | */ | 
|  | static WebRtc_Word16 EncoderInitLb(ISACLBStruct* instLB, | 
|  | WebRtc_Word16 codingMode, | 
|  | enum IsacSamplingRate sampRate) { | 
|  | WebRtc_Word16 statusInit = 0; | 
|  | int k; | 
|  |  | 
|  | /* Init stream vector to zero */ | 
|  | for (k = 0; k < STREAM_SIZE_MAX_60; k++) { | 
|  | instLB->ISACencLB_obj.bitstr_obj.stream[k] = 0; | 
|  | } | 
|  |  | 
|  | if ((codingMode == 1) || (sampRate == kIsacSuperWideband)) { | 
|  | /* 30 ms frame-size if either in super-wideband or | 
|  | * instantaneous mode (I-mode). */ | 
|  | instLB->ISACencLB_obj.new_framelength = 480; | 
|  | } else { | 
|  | instLB->ISACencLB_obj.new_framelength = INITIAL_FRAMESAMPLES; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_InitMasking(&instLB->ISACencLB_obj.maskfiltstr_obj); | 
|  | WebRtcIsac_InitPreFilterbank(&instLB->ISACencLB_obj.prefiltbankstr_obj); | 
|  | WebRtcIsac_InitPitchFilter(&instLB->ISACencLB_obj.pitchfiltstr_obj); | 
|  | WebRtcIsac_InitPitchAnalysis( | 
|  | &instLB->ISACencLB_obj.pitchanalysisstr_obj); | 
|  |  | 
|  | instLB->ISACencLB_obj.buffer_index = 0; | 
|  | instLB->ISACencLB_obj.frame_nb = 0; | 
|  | /* Default for I-mode. */ | 
|  | instLB->ISACencLB_obj.bottleneck = 32000; | 
|  | instLB->ISACencLB_obj.current_framesamples = 0; | 
|  | instLB->ISACencLB_obj.s2nr = 0; | 
|  | instLB->ISACencLB_obj.payloadLimitBytes30 = STREAM_SIZE_MAX_30; | 
|  | instLB->ISACencLB_obj.payloadLimitBytes60 = STREAM_SIZE_MAX_60; | 
|  | instLB->ISACencLB_obj.maxPayloadBytes = STREAM_SIZE_MAX_60; | 
|  | instLB->ISACencLB_obj.maxRateInBytes = STREAM_SIZE_MAX_30; | 
|  | instLB->ISACencLB_obj.enforceFrameSize = 0; | 
|  | /* Invalid value prevents getRedPayload to | 
|  | run before encoder is called. */ | 
|  | instLB->ISACencLB_obj.lastBWIdx            = -1; | 
|  | return statusInit; | 
|  | } | 
|  |  | 
|  | static WebRtc_Word16 EncoderInitUb(ISACUBStruct* instUB, | 
|  | WebRtc_Word16 bandwidth) { | 
|  | WebRtc_Word16 statusInit = 0; | 
|  | int k; | 
|  |  | 
|  | /* Init stream vector to zero. */ | 
|  | for (k = 0; k < STREAM_SIZE_MAX_60; k++) { | 
|  | instUB->ISACencUB_obj.bitstr_obj.stream[k] = 0; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_InitMasking(&instUB->ISACencUB_obj.maskfiltstr_obj); | 
|  | WebRtcIsac_InitPreFilterbank(&instUB->ISACencUB_obj.prefiltbankstr_obj); | 
|  |  | 
|  | if (bandwidth == isac16kHz) { | 
|  | instUB->ISACencUB_obj.buffer_index = LB_TOTAL_DELAY_SAMPLES; | 
|  | } else { | 
|  | instUB->ISACencUB_obj.buffer_index = 0; | 
|  | } | 
|  | /* Default for I-mode. */ | 
|  | instUB->ISACencUB_obj.bottleneck = 32000; | 
|  | /* These store the limits for the wideband + super-wideband bit-stream. */ | 
|  | instUB->ISACencUB_obj.maxPayloadSizeBytes = STREAM_SIZE_MAX_30 << 1; | 
|  | /* This has to be updated after each lower-band encoding to guarantee | 
|  | * a correct payload-limitation. */ | 
|  | instUB->ISACencUB_obj.numBytesUsed = 0; | 
|  | memset(instUB->ISACencUB_obj.data_buffer_float, 0, | 
|  | (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES) * sizeof(float)); | 
|  |  | 
|  | memcpy(&(instUB->ISACencUB_obj.lastLPCVec), | 
|  | WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER); | 
|  |  | 
|  | return statusInit; | 
|  | } | 
|  |  | 
|  |  | 
|  | WebRtc_Word16 WebRtcIsac_EncoderInit(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16 codingMode) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WebRtc_Word16 status; | 
|  |  | 
|  | if ((codingMode != 0) && (codingMode != 1)) { | 
|  | instISAC->errorCode = ISAC_DISALLOWED_CODING_MODE; | 
|  | return -1; | 
|  | } | 
|  | /* Default bottleneck. */ | 
|  | instISAC->bottleneck = MAX_ISAC_BW; | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacWideband) { | 
|  | instISAC->bandwidthKHz = isac8kHz; | 
|  | instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60; | 
|  | instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30; | 
|  | } else { | 
|  | instISAC->bandwidthKHz = isac16kHz; | 
|  | instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX; | 
|  | instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX; | 
|  | } | 
|  |  | 
|  | /* Channel-adaptive = 0; Instantaneous (Channel-independent) = 1. */ | 
|  | instISAC->codingMode = codingMode; | 
|  |  | 
|  | WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj, | 
|  | instISAC->encoderSamplingRateKHz, | 
|  | instISAC->decoderSamplingRateKHz); | 
|  |  | 
|  | WebRtcIsac_InitRateModel(&instISAC->rate_data_obj); | 
|  | /* Default for I-mode. */ | 
|  | instISAC->MaxDelay = 10.0; | 
|  |  | 
|  | status = EncoderInitLb(&instISAC->instLB, codingMode, | 
|  | instISAC->encoderSamplingRateKHz); | 
|  | if (status < 0) { | 
|  | instISAC->errorCode = -status; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | /* Initialize encoder filter-bank. */ | 
|  | memset(instISAC->analysisFBState1, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  | memset(instISAC->analysisFBState2, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  |  | 
|  | status = EncoderInitUb(&(instISAC->instUB), | 
|  | instISAC->bandwidthKHz); | 
|  | if (status < 0) { | 
|  | instISAC->errorCode = -status; | 
|  | return -1; | 
|  | } | 
|  | } | 
|  | memset(instISAC->state_in_resampler, 0, sizeof(instISAC->state_in_resampler)); | 
|  | /* Initialization is successful, set the flag. */ | 
|  | instISAC->initFlag |= BIT_MASK_ENC_INIT; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_Encode(...) | 
|  | * | 
|  | * This function encodes 10ms frame(s) and inserts it into a package. | 
|  | * Input speech length has to be 160 samples (10ms). The encoder buffers those | 
|  | * 10ms frames until it reaches the chosen Framesize (480 or 960 samples | 
|  | * corresponding to 30 or 60 ms frames), and then proceeds to the encoding. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - speechIn          : input speech vector. | 
|  | * | 
|  | * Output: | 
|  | *        - encoded           : the encoded data vector | 
|  | * | 
|  | * Return value: | 
|  | *                            : >0 - Length (in bytes) of coded data | 
|  | *                            :  0 - The buffer didn't reach the chosen | 
|  | *                                  frameSize so it keeps buffering speech | 
|  | *                                 samples. | 
|  | *                            : -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_Encode(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_Word16* speechIn, | 
|  | WebRtc_Word16* encoded) { | 
|  | float inFrame[FRAMESAMPLES_10ms]; | 
|  | WebRtc_Word16 speechInLB[FRAMESAMPLES_10ms]; | 
|  | WebRtc_Word16 speechInUB[FRAMESAMPLES_10ms]; | 
|  | WebRtc_Word16 streamLenLB = 0; | 
|  | WebRtc_Word16 streamLenUB = 0; | 
|  | WebRtc_Word16 streamLen = 0; | 
|  | WebRtc_Word16 k = 0; | 
|  | WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded; | 
|  | int garbageLen = 0; | 
|  | WebRtc_Word32 bottleneck = 0; | 
|  | WebRtc_Word16 bottleneckIdx = 0; | 
|  | WebRtc_Word16 jitterInfo = 0; | 
|  |  | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | ISACLBStruct* instLB = &(instISAC->instLB); | 
|  | ISACUBStruct* instUB = &(instISAC->instUB); | 
|  | const int16_t* speech_in_ptr = speechIn; | 
|  | int16_t resampled_buff[FRAMESAMPLES_10ms * 2]; | 
|  |  | 
|  | /* Check if encoder initiated. */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (instISAC->in_sample_rate_hz == 48000) { | 
|  | /* Samples in 10 ms @ 48 kHz. */ | 
|  | const int kNumInputSamples = FRAMESAMPLES_10ms * 3; | 
|  | /* Samples 10 ms @ 32 kHz. */ | 
|  | const int kNumOutputSamples = FRAMESAMPLES_10ms * 2; | 
|  | /* Resampler divide the input into blocks of 3 samples, i.e. | 
|  | * kNumInputSamples / 3. */ | 
|  | const int kNumResamplerBlocks = FRAMESAMPLES_10ms; | 
|  | int32_t buffer32[FRAMESAMPLES_10ms * 3 + SIZE_RESAMPLER_STATE]; | 
|  |  | 
|  | /* Restore last samples from the past to the beginning of the buffer | 
|  | * and store the last samples of current frame for the next resampling. */ | 
|  | for (k = 0; k < SIZE_RESAMPLER_STATE; k++) { | 
|  | buffer32[k] = instISAC->state_in_resampler[k]; | 
|  | instISAC->state_in_resampler[k] = speechIn[kNumInputSamples - | 
|  | SIZE_RESAMPLER_STATE + k]; | 
|  | } | 
|  | for (k = 0; k < kNumInputSamples; k++) { | 
|  | buffer32[SIZE_RESAMPLER_STATE + k] = speechIn[k]; | 
|  | } | 
|  | /* Resampling 3 samples to 2. Function divides the input in | 
|  | * |kNumResamplerBlocks| number of 3-sample groups, and output is | 
|  | * |kNumResamplerBlocks| number of 2-sample groups. */ | 
|  | WebRtcSpl_Resample48khzTo32khz(buffer32, buffer32, kNumResamplerBlocks); | 
|  | WebRtcSpl_VectorBitShiftW32ToW16(resampled_buff, kNumOutputSamples, | 
|  | buffer32, 15); | 
|  | speech_in_ptr = resampled_buff; | 
|  | } | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | WebRtcSpl_AnalysisQMF(speech_in_ptr, speechInLB, speechInUB, | 
|  | instISAC->analysisFBState1, | 
|  | instISAC->analysisFBState2); | 
|  |  | 
|  | /* Convert from fixed to floating point. */ | 
|  | for (k = 0; k < FRAMESAMPLES_10ms; k++) { | 
|  | inFrame[k] = (float)speechInLB[k]; | 
|  | } | 
|  | } else { | 
|  | for (k = 0; k < FRAMESAMPLES_10ms; k++) { | 
|  | inFrame[k] = (float) speechIn[k]; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Add some noise to avoid denormal numbers. */ | 
|  | inFrame[0] += (float)1.23455334e-3; | 
|  | inFrame[1] -= (float)2.04324239e-3; | 
|  | inFrame[2] += (float)1.90854954e-3; | 
|  | inFrame[9] += (float)1.84854878e-3; | 
|  |  | 
|  | /* This function will update the bottleneck if required. */ | 
|  | UpdateBottleneck(instISAC); | 
|  |  | 
|  | /* Get the bandwith information which has to be sent to the other side. */ | 
|  | GetSendBandwidthInfo(instISAC, &bottleneckIdx, &jitterInfo); | 
|  |  | 
|  | /* Encode lower-band. */ | 
|  | streamLenLB = WebRtcIsac_EncodeLb(inFrame, &instLB->ISACencLB_obj, | 
|  | instISAC->codingMode, bottleneckIdx); | 
|  | if (streamLenLB < 0) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | instUB = &(instISAC->instUB); | 
|  |  | 
|  | /* Convert to float. */ | 
|  | for (k = 0; k < FRAMESAMPLES_10ms; k++) { | 
|  | inFrame[k] = (float) speechInUB[k]; | 
|  | } | 
|  |  | 
|  | /* Add some noise to avoid denormal numbers. */ | 
|  | inFrame[0] += (float)1.23455334e-3; | 
|  | inFrame[1] -= (float)2.04324239e-3; | 
|  | inFrame[2] += (float)1.90854954e-3; | 
|  | inFrame[9] += (float)1.84854878e-3; | 
|  |  | 
|  | /* Tell to upper-band the number of bytes used so far. | 
|  | * This is for payload limitation. */ | 
|  | instUB->ISACencUB_obj.numBytesUsed = streamLenLB + 1 + | 
|  | LEN_CHECK_SUM_WORD8; | 
|  | /* Encode upper-band. */ | 
|  | switch (instISAC->bandwidthKHz) { | 
|  | case isac12kHz: { | 
|  | streamLenUB = WebRtcIsac_EncodeUb12(inFrame, &instUB->ISACencUB_obj, | 
|  | jitterInfo); | 
|  | break; | 
|  | } | 
|  | case isac16kHz: { | 
|  | streamLenUB = WebRtcIsac_EncodeUb16(inFrame, &instUB->ISACencUB_obj, | 
|  | jitterInfo); | 
|  | break; | 
|  | } | 
|  | case isac8kHz: { | 
|  | streamLenUB = 0; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((streamLenUB < 0) && (streamLenUB != -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) { | 
|  | /* An error has happened but this is not the error due to a | 
|  | * bit-stream larger than the limit. */ | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (streamLenLB == 0) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* One byte is allocated for the length. According to older decoders | 
|  | so the length bit-stream plus one byte for size and | 
|  | LEN_CHECK_SUM_WORD8 for the checksum should be less than or equal | 
|  | to 255. */ | 
|  | if ((streamLenUB > (255 - (LEN_CHECK_SUM_WORD8 + 1))) || | 
|  | (streamLenUB == -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) { | 
|  | /* We have got a too long bit-stream we skip the upper-band | 
|  | * bit-stream for this frame. */ | 
|  | streamLenUB = 0; | 
|  | } | 
|  |  | 
|  | memcpy(ptrEncodedUW8, instLB->ISACencLB_obj.bitstr_obj.stream, streamLenLB); | 
|  | streamLen = streamLenLB; | 
|  | if (streamLenUB > 0) { | 
|  | ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)(streamLenUB + 1 + | 
|  | LEN_CHECK_SUM_WORD8); | 
|  | memcpy(&ptrEncodedUW8[streamLenLB + 1], | 
|  | instUB->ISACencUB_obj.bitstr_obj.stream, streamLenUB); | 
|  | streamLen += ptrEncodedUW8[streamLenLB]; | 
|  | } else { | 
|  | ptrEncodedUW8[streamLenLB] = 0; | 
|  | } | 
|  | } else { | 
|  | if (streamLenLB == 0) { | 
|  | return 0; | 
|  | } | 
|  | memcpy(ptrEncodedUW8, instLB->ISACencLB_obj.bitstr_obj.stream, | 
|  | streamLenLB); | 
|  | streamLenUB = 0; | 
|  | streamLen = streamLenLB; | 
|  | } | 
|  |  | 
|  | /* Add Garbage if required. */ | 
|  | WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj, &bottleneck); | 
|  | if (instISAC->codingMode == 0) { | 
|  | int minBytes; | 
|  | int limit; | 
|  | WebRtc_UWord8* ptrGarbage; | 
|  |  | 
|  | instISAC->MaxDelay = (double)WebRtcIsac_GetUplinkMaxDelay( | 
|  | &instISAC->bwestimator_obj); | 
|  |  | 
|  | /* Update rate model and get minimum number of bytes in this packet. */ | 
|  | minBytes = WebRtcIsac_GetMinBytes( | 
|  | &(instISAC->rate_data_obj), streamLen, | 
|  | instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck, | 
|  | instISAC->MaxDelay, instISAC->bandwidthKHz); | 
|  |  | 
|  | /* Make sure MinBytes does not exceed packet size limit. */ | 
|  | if (instISAC->bandwidthKHz == isac8kHz) { | 
|  | if (instLB->ISACencLB_obj.current_framesamples == FRAMESAMPLES) { | 
|  | limit = instLB->ISACencLB_obj.payloadLimitBytes30; | 
|  | } else { | 
|  | limit = instLB->ISACencLB_obj.payloadLimitBytes60; | 
|  | } | 
|  | } else { | 
|  | limit = instUB->ISACencUB_obj.maxPayloadSizeBytes; | 
|  | } | 
|  | minBytes = (minBytes > limit) ? limit : minBytes; | 
|  |  | 
|  | /* Make sure we don't allow more than 255 bytes of garbage data. | 
|  | * We store the length of the garbage data in 8 bits in the bitstream, | 
|  | * 255 is the max garbage length we can signal using 8 bits. */ | 
|  | if ((instISAC->bandwidthKHz == isac8kHz) || | 
|  | (streamLenUB == 0)) { | 
|  | ptrGarbage = &ptrEncodedUW8[streamLenLB]; | 
|  | limit = streamLen + 255; | 
|  | } else { | 
|  | ptrGarbage = &ptrEncodedUW8[streamLenLB + 1 + streamLenUB]; | 
|  | limit = streamLen + (255 - ptrEncodedUW8[streamLenLB]); | 
|  | } | 
|  | minBytes = (minBytes > limit) ? limit : minBytes; | 
|  |  | 
|  | garbageLen = (minBytes > streamLen) ? (minBytes - streamLen) : 0; | 
|  |  | 
|  | /* Save data for creation of multiple bit-streams. */ | 
|  | /* If bit-stream too short then add garbage at the end. */ | 
|  | if (garbageLen > 0) { | 
|  | for (k = 0; k < garbageLen; k++) { | 
|  | ptrGarbage[k] = (WebRtc_UWord8)(rand() & 0xFF); | 
|  | } | 
|  | /* For a correct length of the upper-band bit-stream together | 
|  | * with the garbage. Garbage is embeded in upper-band bit-stream. | 
|  | * That is the only way to preserve backward compatibility. */ | 
|  | if ((instISAC->bandwidthKHz == isac8kHz) || | 
|  | (streamLenUB == 0)) { | 
|  | ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)garbageLen; | 
|  | } else { | 
|  | ptrEncodedUW8[streamLenLB] += (WebRtc_UWord8)garbageLen; | 
|  | /* Write the length of the garbage at the end of the upper-band | 
|  | *  bit-stream, if exists. This helps for sanity check. */ | 
|  | ptrEncodedUW8[streamLenLB + 1 + streamLenUB] = | 
|  | (WebRtc_UWord8)garbageLen; | 
|  |  | 
|  | } | 
|  | streamLen += garbageLen; | 
|  | } | 
|  | } else { | 
|  | /* update rate model */ | 
|  | WebRtcIsac_UpdateRateModel( | 
|  | &instISAC->rate_data_obj, streamLen, | 
|  | instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck); | 
|  | garbageLen = 0; | 
|  | } | 
|  |  | 
|  | /* Generate CRC if required. */ | 
|  | if ((instISAC->bandwidthKHz != isac8kHz) && (streamLenUB > 0)) { | 
|  | WebRtc_UWord32 crc; | 
|  |  | 
|  | WebRtcIsac_GetCrc((WebRtc_Word16*)(&(ptrEncodedUW8[streamLenLB + 1])), | 
|  | streamLenUB + garbageLen, &crc); | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) { | 
|  | ptrEncodedUW8[streamLen - LEN_CHECK_SUM_WORD8 + k] = | 
|  | (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(&ptrEncodedUW8[streamLenLB + streamLenUB + 1], &crc, | 
|  | LEN_CHECK_SUM_WORD8); | 
|  | #endif | 
|  | } | 
|  | return streamLen; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_GetNewBitStream(...) | 
|  | * | 
|  | * This function returns encoded data, with the recieved bwe-index in the | 
|  | * stream. If the rate is set to a value less than bottleneck of codec | 
|  | * the new bistream will be re-encoded with the given target rate. | 
|  | * It should always return a complete packet, i.e. only called once | 
|  | * even for 60 msec frames. | 
|  | * | 
|  | * NOTE 1! This function does not write in the ISACStruct, it is not allowed. | 
|  | * NOTE 2! Rates larger than the bottleneck of the codec will be limited | 
|  | *         to the current bottleneck. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - bweIndex          : Index of bandwidth estimate to put in new | 
|  | *                              bitstream | 
|  | *        - rate              : target rate of the transcoder is bits/sec. | 
|  | *                              Valid values are the accepted rate in iSAC, | 
|  | *                              i.e. 10000 to 56000. | 
|  | * | 
|  | * Output: | 
|  | *        - encoded           : The encoded data vector | 
|  | * | 
|  | * Return value               : >0 - Length (in bytes) of coded data | 
|  | *                              -1 - Error  or called in SWB mode | 
|  | *                                 NOTE! No error code is written to | 
|  | *                                 the struct since it is only allowed to read | 
|  | *                                 the struct. | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetNewBitStream(ISACStruct*  ISAC_main_inst, | 
|  | WebRtc_Word16  bweIndex, | 
|  | WebRtc_Word16  jitterInfo, | 
|  | WebRtc_Word32  rate, | 
|  | WebRtc_Word16* encoded, | 
|  | WebRtc_Word16  isRCU) { | 
|  | Bitstr iSACBitStreamInst;   /* Local struct for bitstream handling */ | 
|  | WebRtc_Word16 streamLenLB; | 
|  | WebRtc_Word16 streamLenUB; | 
|  | WebRtc_Word16 totalStreamLen; | 
|  | double gain2; | 
|  | double gain1; | 
|  | float scale; | 
|  | enum ISACBandwidth bandwidthKHz; | 
|  | double rateLB; | 
|  | double rateUB; | 
|  | WebRtc_Word32 currentBN; | 
|  | WebRtc_UWord8* encodedPtrUW8 = (WebRtc_UWord8*)encoded; | 
|  | WebRtc_UWord32 crc; | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | WebRtc_Word16  k; | 
|  | #endif | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Get the bottleneck of this iSAC and limit the | 
|  | * given rate to the current bottleneck. */ | 
|  | WebRtcIsac_GetUplinkBw(ISAC_main_inst, ¤tBN); | 
|  | if (rate > currentBN) { | 
|  | rate = currentBN; | 
|  | } | 
|  |  | 
|  | if (WebRtcIsac_RateAllocation(rate, &rateLB, &rateUB, &bandwidthKHz) < 0) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Cannot transcode from 16 kHz to 12 kHz. */ | 
|  | if ((bandwidthKHz == isac12kHz) && | 
|  | (instISAC->bandwidthKHz == isac16kHz)) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* A gain [dB] for the given rate. */ | 
|  | gain1 = WebRtcIsac_GetSnr( | 
|  | rateLB, instISAC->instLB.ISACencLB_obj.current_framesamples); | 
|  | /* The gain [dB] of this iSAC. */ | 
|  | gain2 = WebRtcIsac_GetSnr( | 
|  | instISAC->instLB.ISACencLB_obj.bottleneck, | 
|  | instISAC->instLB.ISACencLB_obj.current_framesamples); | 
|  |  | 
|  | /* Scale is the ratio of two gains in normal domain. */ | 
|  | scale = (float)pow(10, (gain1 - gain2) / 20.0); | 
|  | /* Change the scale if this is a RCU bit-stream. */ | 
|  | scale = (isRCU) ? (scale * RCU_TRANSCODING_SCALE) : scale; | 
|  |  | 
|  | streamLenLB = WebRtcIsac_EncodeStoredDataLb( | 
|  | &instISAC->instLB.ISACencLB_obj.SaveEnc_obj, | 
|  | &iSACBitStreamInst, bweIndex, scale); | 
|  |  | 
|  | if (streamLenLB < 0) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Convert from bytes to WebRtc_Word16. */ | 
|  | memcpy(encoded, iSACBitStreamInst.stream, streamLenLB); | 
|  |  | 
|  | if (bandwidthKHz == isac8kHz) { | 
|  | return streamLenLB; | 
|  | } | 
|  |  | 
|  | totalStreamLen = streamLenLB; | 
|  | /* super-wideband is always at 30ms. | 
|  | * These gains are in dB. | 
|  | * Gain for the given rate. */ | 
|  | gain1 = WebRtcIsac_GetSnr(rateUB, FRAMESAMPLES); | 
|  | /* Gain of this iSAC */ | 
|  | gain2 = WebRtcIsac_GetSnr(instISAC->instUB.ISACencUB_obj.bottleneck, | 
|  | FRAMESAMPLES); | 
|  |  | 
|  | /* Scale is the ratio of two gains in normal domain. */ | 
|  | scale = (float)pow(10, (gain1 - gain2) / 20.0); | 
|  |  | 
|  | /* Change the scale if this is a RCU bit-stream. */ | 
|  | scale = (isRCU)? (scale * RCU_TRANSCODING_SCALE_UB) : scale; | 
|  |  | 
|  | streamLenUB = WebRtcIsac_EncodeStoredDataUb( | 
|  | &(instISAC->instUB.ISACencUB_obj.SaveEnc_obj), | 
|  | &iSACBitStreamInst, jitterInfo, scale, | 
|  | instISAC->bandwidthKHz); | 
|  |  | 
|  | if (streamLenUB < 0) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (streamLenUB + 1 + LEN_CHECK_SUM_WORD8 > 255) { | 
|  | return streamLenLB; | 
|  | } | 
|  |  | 
|  | totalStreamLen = streamLenLB + streamLenUB + 1 + LEN_CHECK_SUM_WORD8; | 
|  | encodedPtrUW8[streamLenLB] = streamLenUB + 1 + LEN_CHECK_SUM_WORD8; | 
|  |  | 
|  | memcpy(&encodedPtrUW8[streamLenLB + 1], iSACBitStreamInst.stream, | 
|  | streamLenUB); | 
|  |  | 
|  | WebRtcIsac_GetCrc((WebRtc_Word16*)(&(encodedPtrUW8[streamLenLB + 1])), | 
|  | streamLenUB, &crc); | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) { | 
|  | encodedPtrUW8[totalStreamLen - LEN_CHECK_SUM_WORD8 + k] = | 
|  | (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(&encodedPtrUW8[streamLenLB + streamLenUB + 1], &crc, | 
|  | LEN_CHECK_SUM_WORD8); | 
|  | #endif | 
|  | return totalStreamLen; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * DecoderInitLb(...) - internal function for initialization of | 
|  | *                                Lower Band | 
|  | * DecoderInitUb(...) - internal function for initialization of | 
|  | *                                Upper Band | 
|  | * WebRtcIsac_DecoderInit(...) - API function | 
|  | * | 
|  | * This function initializes a ISAC instance prior to the decoder calls. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | * | 
|  | * Return value | 
|  | *                            :  0 - Ok | 
|  | *                              -1 - Error | 
|  | */ | 
|  | static WebRtc_Word16 DecoderInitLb(ISACLBStruct* instISAC) { | 
|  | int i; | 
|  | /* Initialize stream vector to zero. */ | 
|  | for (i = 0; i < STREAM_SIZE_MAX_60; i++) { | 
|  | instISAC->ISACdecLB_obj.bitstr_obj.stream[i] = 0; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_InitMasking(&instISAC->ISACdecLB_obj.maskfiltstr_obj); | 
|  | WebRtcIsac_InitPostFilterbank( | 
|  | &instISAC->ISACdecLB_obj.postfiltbankstr_obj); | 
|  | WebRtcIsac_InitPitchFilter(&instISAC->ISACdecLB_obj.pitchfiltstr_obj); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static WebRtc_Word16 DecoderInitUb(ISACUBStruct* instISAC) { | 
|  | int i; | 
|  | /* Init stream vector to zero */ | 
|  | for (i = 0; i < STREAM_SIZE_MAX_60; i++) { | 
|  | instISAC->ISACdecUB_obj.bitstr_obj.stream[i] = 0; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_InitMasking(&instISAC->ISACdecUB_obj.maskfiltstr_obj); | 
|  | WebRtcIsac_InitPostFilterbank( | 
|  | &instISAC->ISACdecUB_obj.postfiltbankstr_obj); | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | WebRtc_Word16 WebRtcIsac_DecoderInit(ISACStruct* ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | if (DecoderInitLb(&instISAC->instLB) < 0) { | 
|  | return -1; | 
|  | } | 
|  | if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | memset(instISAC->synthesisFBState1, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  | memset(instISAC->synthesisFBState2, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  |  | 
|  | if (DecoderInitUb(&(instISAC->instUB)) < 0) { | 
|  | return -1; | 
|  | } | 
|  | } | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) { | 
|  | WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj, | 
|  | instISAC->encoderSamplingRateKHz, | 
|  | instISAC->decoderSamplingRateKHz); | 
|  | } | 
|  | instISAC->initFlag |= BIT_MASK_DEC_INIT; | 
|  | instISAC->resetFlag_8kHz = 0; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_UpdateBwEstimate(...) | 
|  | * | 
|  | * This function updates the estimate of the bandwidth. | 
|  | * | 
|  | * NOTE: | 
|  | * The estimates of bandwidth is not valid if the sample rate of the far-end | 
|  | * encoder is set to 48 kHz and send timestamps are increamented according to | 
|  | * 48 kHz sampling rate. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - encoded           : encoded ISAC frame(s). | 
|  | *        - packet_size       : size of the packet. | 
|  | *        - rtp_seq_number    : the RTP number of the packet. | 
|  | *        - arr_ts            : the arrival time of the packet (from NetEq) | 
|  | *                              in samples. | 
|  | * | 
|  | * Return value               :  0 - Ok | 
|  | *                              -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_UpdateBwEstimate(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_UWord16* encoded, | 
|  | WebRtc_Word32 packet_size, | 
|  | WebRtc_UWord16 rtp_seq_number, | 
|  | WebRtc_UWord32 send_ts, | 
|  | WebRtc_UWord32 arr_ts) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | Bitstr streamdata; | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | int k; | 
|  | #endif | 
|  | WebRtc_Word16 err; | 
|  |  | 
|  | /* Check if decoder initiated. */ | 
|  | if ((instISAC->initFlag & BIT_MASK_DEC_INIT) != BIT_MASK_DEC_INIT) { | 
|  | instISAC->errorCode = ISAC_DECODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (packet_size <= 0) { | 
|  | /* Return error code if the packet length is null. */ | 
|  | instISAC->errorCode = ISAC_EMPTY_PACKET; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_ResetBitstream(&(streamdata)); | 
|  |  | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < 10; k++) { | 
|  | streamdata.stream[k] = (WebRtc_UWord8)((encoded[k >> 1] >> | 
|  | ((k & 1) << 3)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(streamdata.stream, encoded, 10); | 
|  | #endif | 
|  |  | 
|  | err = WebRtcIsac_EstimateBandwidth(&instISAC->bwestimator_obj, &streamdata, | 
|  | packet_size, rtp_seq_number, send_ts, | 
|  | arr_ts, instISAC->encoderSamplingRateKHz, | 
|  | instISAC->decoderSamplingRateKHz); | 
|  | if (err < 0) { | 
|  | /* Return error code if something went wrong. */ | 
|  | instISAC->errorCode = -err; | 
|  | return -1; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static WebRtc_Word16 Decode(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_UWord16* encoded, | 
|  | WebRtc_Word16 lenEncodedBytes, | 
|  | WebRtc_Word16* decoded, | 
|  | WebRtc_Word16* speechType, | 
|  | WebRtc_Word16 isRCUPayload) { | 
|  | /* Number of samples (480 or 960), output from decoder | 
|  | that were actually used in the encoder/decoder | 
|  | (determined on the fly). */ | 
|  | WebRtc_Word16 numSamplesLB; | 
|  | WebRtc_Word16 numSamplesUB; | 
|  | WebRtc_Word16 speechIdx; | 
|  | float outFrame[MAX_FRAMESAMPLES]; | 
|  | WebRtc_Word16 outFrameLB[MAX_FRAMESAMPLES]; | 
|  | WebRtc_Word16 outFrameUB[MAX_FRAMESAMPLES]; | 
|  | WebRtc_Word16 numDecodedBytesLB; | 
|  | WebRtc_Word16 numDecodedBytesUB; | 
|  | WebRtc_Word16 lenEncodedLBBytes; | 
|  | WebRtc_Word16 validChecksum = 1; | 
|  | WebRtc_Word16 k; | 
|  | WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded; | 
|  | WebRtc_UWord16 numLayer; | 
|  | WebRtc_Word16 totSizeBytes; | 
|  | WebRtc_Word16 err; | 
|  |  | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | ISACUBDecStruct* decInstUB = &(instISAC->instUB.ISACdecUB_obj); | 
|  | ISACLBDecStruct* decInstLB = &(instISAC->instLB.ISACdecLB_obj); | 
|  |  | 
|  | /* Check if decoder initiated. */ | 
|  | if ((instISAC->initFlag & BIT_MASK_DEC_INIT) != | 
|  | BIT_MASK_DEC_INIT) { | 
|  | instISAC->errorCode = ISAC_DECODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (lenEncodedBytes <= 0) { | 
|  | /* return error code if the packet length is null. */ | 
|  | instISAC->errorCode = ISAC_EMPTY_PACKET; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* The size of the encoded lower-band is bounded by | 
|  | * STREAM_SIZE_MAX. If a payload with the size larger than STREAM_SIZE_MAX | 
|  | * is received, it is not considered erroneous. */ | 
|  | lenEncodedLBBytes = (lenEncodedBytes > STREAM_SIZE_MAX) ? | 
|  | STREAM_SIZE_MAX : lenEncodedBytes; | 
|  |  | 
|  | /* Copy to lower-band bit-stream structure. */ | 
|  | memcpy(instISAC->instLB.ISACdecLB_obj.bitstr_obj.stream, ptrEncodedUW8, | 
|  | lenEncodedLBBytes); | 
|  |  | 
|  | /* Regardless of that the current codec is setup to work in | 
|  | * wideband or super-wideband, the decoding of the lower-band | 
|  | * has to be performed. */ | 
|  | numDecodedBytesLB = WebRtcIsac_DecodeLb(outFrame, decInstLB, | 
|  | &numSamplesLB, isRCUPayload); | 
|  |  | 
|  | if ((numDecodedBytesLB < 0) || (numDecodedBytesLB > lenEncodedLBBytes) || | 
|  | (numSamplesLB > MAX_FRAMESAMPLES)) { | 
|  | instISAC->errorCode = ISAC_LENGTH_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Error Check, we accept multi-layer bit-stream This will limit number | 
|  | * of iterations of the while loop. Even without this the number | 
|  | * of iterations is limited. */ | 
|  | numLayer = 1; | 
|  | totSizeBytes = numDecodedBytesLB; | 
|  | while (totSizeBytes != lenEncodedBytes) { | 
|  | if ((totSizeBytes > lenEncodedBytes) || | 
|  | (ptrEncodedUW8[totSizeBytes] == 0) || | 
|  | (numLayer > MAX_NUM_LAYERS)) { | 
|  | instISAC->errorCode = ISAC_LENGTH_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  | totSizeBytes += ptrEncodedUW8[totSizeBytes]; | 
|  | numLayer++; | 
|  | } | 
|  |  | 
|  | if (instISAC->decoderSamplingRateKHz == kIsacWideband) { | 
|  | for (k = 0; k < numSamplesLB; k++) { | 
|  | if (outFrame[k] > 32767) { | 
|  | decoded[k] = 32767; | 
|  | } else if (outFrame[k] < -32768) { | 
|  | decoded[k] = -32768; | 
|  | } else { | 
|  | decoded[k] = (WebRtc_Word16)WebRtcIsac_lrint(outFrame[k]); | 
|  | } | 
|  | } | 
|  | numSamplesUB = 0; | 
|  | } else { | 
|  | WebRtc_UWord32 crc; | 
|  | /* We don't accept larger than 30ms (480 samples at lower-band) | 
|  | * frame-size. */ | 
|  | for (k = 0; k < numSamplesLB; k++) { | 
|  | if (outFrame[k] > 32767) { | 
|  | outFrameLB[k] = 32767; | 
|  | } else if (outFrame[k] < -32768) { | 
|  | outFrameLB[k] = -32768; | 
|  | } else { | 
|  | outFrameLB[k] = (WebRtc_Word16)WebRtcIsac_lrint(outFrame[k]); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Check for possible error, and if upper-band stream exists. */ | 
|  | if (numDecodedBytesLB == lenEncodedBytes) { | 
|  | /* Decoding was successful. No super-wideband bit-stream exists. */ | 
|  | numSamplesUB = numSamplesLB; | 
|  | memset(outFrameUB, 0, sizeof(WebRtc_Word16) *  numSamplesUB); | 
|  |  | 
|  | /* Prepare for the potential increase of signal bandwidth. */ | 
|  | instISAC->resetFlag_8kHz = 2; | 
|  | } else { | 
|  | /* This includes the checksum and the bytes that stores the length. */ | 
|  | WebRtc_Word16 lenNextStream = ptrEncodedUW8[numDecodedBytesLB]; | 
|  |  | 
|  | /* Is this garbage or valid super-wideband bit-stream? | 
|  | * Check if checksum is valid. */ | 
|  | if (lenNextStream <= (LEN_CHECK_SUM_WORD8 + 1)) { | 
|  | /* Such a small second layer cannot be super-wideband layer. | 
|  | * It must be a short garbage. */ | 
|  | validChecksum = 0; | 
|  | } else { | 
|  | /* Run CRC to see if the checksum match. */ | 
|  | WebRtcIsac_GetCrc((WebRtc_Word16*)( | 
|  | &ptrEncodedUW8[numDecodedBytesLB + 1]), | 
|  | lenNextStream - LEN_CHECK_SUM_WORD8 - 1, &crc); | 
|  |  | 
|  | validChecksum = 1; | 
|  | for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) { | 
|  | validChecksum &= (((crc >> (24 - k * 8)) & 0xFF) == | 
|  | ptrEncodedUW8[numDecodedBytesLB + lenNextStream - | 
|  | LEN_CHECK_SUM_WORD8 + k]); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!validChecksum) { | 
|  | /* This is a garbage, we have received a wideband | 
|  | * bit-stream with garbage. */ | 
|  | numSamplesUB = numSamplesLB; | 
|  | memset(outFrameUB, 0, sizeof(WebRtc_Word16) * numSamplesUB); | 
|  | } else { | 
|  | /* A valid super-wideband biststream exists. */ | 
|  | enum ISACBandwidth bandwidthKHz; | 
|  | WebRtc_Word32 maxDelayBit; | 
|  |  | 
|  | /* If we have super-wideband bit-stream, we cannot | 
|  | * have 60 ms frame-size. */ | 
|  | if (numSamplesLB > FRAMESAMPLES) { | 
|  | instISAC->errorCode = ISAC_LENGTH_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* The rest of the bit-stream contains the upper-band | 
|  | * bit-stream curently this is the only thing there, | 
|  | * however, we might add more layers. */ | 
|  |  | 
|  | /* Have to exclude one byte where the length is stored | 
|  | * and last 'LEN_CHECK_SUM_WORD8' bytes where the | 
|  | * checksum is stored. */ | 
|  | lenNextStream -= (LEN_CHECK_SUM_WORD8 + 1); | 
|  |  | 
|  | memcpy(decInstUB->bitstr_obj.stream, | 
|  | &ptrEncodedUW8[numDecodedBytesLB + 1], lenNextStream); | 
|  |  | 
|  | /* Reset bit-stream object, this is the first decoding. */ | 
|  | WebRtcIsac_ResetBitstream(&(decInstUB->bitstr_obj)); | 
|  |  | 
|  | /* Decode jitter information. */ | 
|  | err = WebRtcIsac_DecodeJitterInfo(&decInstUB->bitstr_obj, &maxDelayBit); | 
|  | if (err < 0) { | 
|  | instISAC->errorCode = -err; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Update jitter info which is in the upper-band bit-stream | 
|  | * only if the encoder is in super-wideband. Otherwise, | 
|  | * the jitter info is already embedded in bandwidth index | 
|  | * and has been updated. */ | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | err = WebRtcIsac_UpdateUplinkJitter( | 
|  | &(instISAC->bwestimator_obj), maxDelayBit); | 
|  | if (err < 0) { | 
|  | instISAC->errorCode = -err; | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Decode bandwidth information. */ | 
|  | err = WebRtcIsac_DecodeBandwidth(&decInstUB->bitstr_obj, | 
|  | &bandwidthKHz); | 
|  | if (err < 0) { | 
|  | instISAC->errorCode = -err; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | switch (bandwidthKHz) { | 
|  | case isac12kHz: { | 
|  | numDecodedBytesUB = WebRtcIsac_DecodeUb12(outFrame, decInstUB, | 
|  | isRCUPayload); | 
|  |  | 
|  | /* Hang-over for transient alleviation - | 
|  | * wait two frames to add the upper band going up from 8 kHz. */ | 
|  | if (instISAC->resetFlag_8kHz > 0) { | 
|  | if (instISAC->resetFlag_8kHz == 2) { | 
|  | /* Silence first and a half frame. */ | 
|  | memset(outFrame, 0, MAX_FRAMESAMPLES * | 
|  | sizeof(float)); | 
|  | } else { | 
|  | const float rampStep = 2.0f / MAX_FRAMESAMPLES; | 
|  | float rampVal = 0; | 
|  | memset(outFrame, 0, (MAX_FRAMESAMPLES >> 1) * | 
|  | sizeof(float)); | 
|  |  | 
|  | /* Ramp up second half of second frame. */ | 
|  | for (k = MAX_FRAMESAMPLES / 2; k < MAX_FRAMESAMPLES; k++) { | 
|  | outFrame[k] *= rampVal; | 
|  | rampVal += rampStep; | 
|  | } | 
|  | } | 
|  | instISAC->resetFlag_8kHz -= 1; | 
|  | } | 
|  |  | 
|  | break; | 
|  | } | 
|  | case isac16kHz: { | 
|  | numDecodedBytesUB = WebRtcIsac_DecodeUb16(outFrame, decInstUB, | 
|  | isRCUPayload); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* It might be less due to garbage. */ | 
|  | if ((numDecodedBytesUB != lenNextStream) && | 
|  | (numDecodedBytesUB != (lenNextStream - | 
|  | ptrEncodedUW8[numDecodedBytesLB + 1 + numDecodedBytesUB]))) { | 
|  | instISAC->errorCode = ISAC_LENGTH_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* If there is no error Upper-band always decodes | 
|  | * 30 ms (480 samples). */ | 
|  | numSamplesUB = FRAMESAMPLES; | 
|  |  | 
|  | /* Convert to W16. */ | 
|  | for (k = 0; k < numSamplesUB; k++) { | 
|  | if (outFrame[k] > 32767) { | 
|  | outFrameUB[k] = 32767; | 
|  | } else if (outFrame[k] < -32768) { | 
|  | outFrameUB[k] = -32768; | 
|  | } else { | 
|  | outFrameUB[k] = (WebRtc_Word16)WebRtcIsac_lrint( | 
|  | outFrame[k]); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | speechIdx = 0; | 
|  | while (speechIdx < numSamplesLB) { | 
|  | WebRtcSpl_SynthesisQMF(&outFrameLB[speechIdx], &outFrameUB[speechIdx], | 
|  | &decoded[(speechIdx << 1)], | 
|  | instISAC->synthesisFBState1, | 
|  | instISAC->synthesisFBState2); | 
|  |  | 
|  | speechIdx += FRAMESAMPLES_10ms; | 
|  | } | 
|  | } | 
|  | *speechType = 0; | 
|  | return (numSamplesLB + numSamplesUB); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_Decode(...) | 
|  | * | 
|  | * This function decodes a ISAC frame. Output speech length | 
|  | * will be a multiple of 480 samples: 480 or 960 samples, | 
|  | * depending on the  frameSize (30 or 60 ms). | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - encoded           : encoded ISAC frame(s) | 
|  | *        - len               : bytes in encoded vector | 
|  | * | 
|  | * Output: | 
|  | *        - decoded           : The decoded vector | 
|  | * | 
|  | * Return value               : >0 - number of samples in decoded vector | 
|  | *                              -1 - Error | 
|  | */ | 
|  |  | 
|  | WebRtc_Word16 WebRtcIsac_Decode(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_UWord16* encoded, | 
|  | WebRtc_Word16 lenEncodedBytes, | 
|  | WebRtc_Word16* decoded, | 
|  | WebRtc_Word16* speechType) { | 
|  | WebRtc_Word16 isRCUPayload = 0; | 
|  | return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded, | 
|  | speechType, isRCUPayload); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_DecodeRcu(...) | 
|  | * | 
|  | * This function decodes a redundant (RCU) iSAC frame. Function is called in | 
|  | * NetEq with a stored RCU payload in case of packet loss. Output speech length | 
|  | * will be a multiple of 480 samples: 480 or 960 samples, | 
|  | * depending on the framesize (30 or 60 ms). | 
|  | * | 
|  | * Input: | 
|  | *      - ISAC_main_inst     : ISAC instance. | 
|  | *      - encoded            : encoded ISAC RCU frame(s) | 
|  | *      - len                : bytes in encoded vector | 
|  | * | 
|  | * Output: | 
|  | *      - decoded            : The decoded vector | 
|  | * | 
|  | * Return value              : >0 - number of samples in decoded vector | 
|  | *                             -1 - Error | 
|  | */ | 
|  |  | 
|  |  | 
|  |  | 
|  | WebRtc_Word16 WebRtcIsac_DecodeRcu(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_UWord16* encoded, | 
|  | WebRtc_Word16 lenEncodedBytes, | 
|  | WebRtc_Word16* decoded, | 
|  | WebRtc_Word16* speechType) { | 
|  | WebRtc_Word16 isRCUPayload = 1; | 
|  | return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded, | 
|  | speechType, isRCUPayload); | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_DecodePlc(...) | 
|  | * | 
|  | * This function conducts PLC for ISAC frame(s). Output speech length | 
|  | * will be a multiple of 480 samples: 480 or 960 samples, | 
|  | * depending on the  frameSize (30 or 60 ms). | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - noOfLostFrames    : Number of PLC frames to produce | 
|  | * | 
|  | * Output: | 
|  | *        - decoded           : The decoded vector | 
|  | * | 
|  | * Return value               : >0 - number of samples in decoded PLC vector | 
|  | *                              -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_DecodePlc(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16* decoded, | 
|  | WebRtc_Word16 noOfLostFrames) { | 
|  | WebRtc_Word16 numSamples = 0; | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | /* Limit number of frames to two = 60 millisecond. | 
|  | * Otherwise we exceed data vectors. */ | 
|  | if (noOfLostFrames > 2) { | 
|  | noOfLostFrames = 2; | 
|  | } | 
|  |  | 
|  | /* Get the number of samples per frame */ | 
|  | switch (instISAC->decoderSamplingRateKHz) { | 
|  | case kIsacWideband: { | 
|  | numSamples = 480 * noOfLostFrames; | 
|  | break; | 
|  | } | 
|  | case kIsacSuperWideband: { | 
|  | numSamples = 960 * noOfLostFrames; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Set output samples to zero. */ | 
|  | memset(decoded, 0, numSamples * sizeof(WebRtc_Word16)); | 
|  | return numSamples; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * ControlLb(...) - Internal function for controlling Lower Band | 
|  | * ControlUb(...) - Internal function for controlling Upper Band | 
|  | * WebRtcIsac_Control(...) - API function | 
|  | * | 
|  | * This function sets the limit on the short-term average bit rate and the | 
|  | * frame length. Should be used only in Instantaneous mode. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - rate              : limit on the short-term average bit rate, | 
|  | *                              in bits/second (between 10000 and 32000) | 
|  | *        - frameSize         : number of milliseconds per frame (30 or 60) | 
|  | * | 
|  | * Return value               : 0 - ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | static WebRtc_Word16 ControlLb(ISACLBStruct* instISAC, double rate, | 
|  | WebRtc_Word16 frameSize) { | 
|  | if ((rate >= 10000) && (rate <= 32000)) { | 
|  | instISAC->ISACencLB_obj.bottleneck = rate; | 
|  | } else { | 
|  | return -ISAC_DISALLOWED_BOTTLENECK; | 
|  | } | 
|  |  | 
|  | if ((frameSize == 30) || (frameSize == 60)) { | 
|  | instISAC->ISACencLB_obj.new_framelength = (FS / 1000) *  frameSize; | 
|  | } else { | 
|  | return -ISAC_DISALLOWED_FRAME_LENGTH; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static WebRtc_Word16 ControlUb(ISACUBStruct* instISAC, double rate) { | 
|  | if ((rate >= 10000) && (rate <= 32000)) { | 
|  | instISAC->ISACencUB_obj.bottleneck = rate; | 
|  | } else { | 
|  | return -ISAC_DISALLOWED_BOTTLENECK; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | WebRtc_Word16 WebRtcIsac_Control(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word32 bottleneckBPS, | 
|  | WebRtc_Word16 frameSize) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WebRtc_Word16 status; | 
|  | double rateLB; | 
|  | double rateUB; | 
|  | enum ISACBandwidth bandwidthKHz; | 
|  |  | 
|  | if (instISAC->codingMode == 0) { | 
|  | /* In adaptive mode. */ | 
|  | instISAC->errorCode = ISAC_MODE_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Check if encoder initiated */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacWideband) { | 
|  | /* If the sampling rate is 16kHz then bandwith should be 8kHz, | 
|  | * regardless of bottleneck. */ | 
|  | bandwidthKHz = isac8kHz; | 
|  | rateLB = (bottleneckBPS > 32000) ? 32000 : bottleneckBPS; | 
|  | rateUB = 0; | 
|  | } else { | 
|  | if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB, | 
|  | &bandwidthKHz) < 0) { | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((instISAC->encoderSamplingRateKHz == kIsacSuperWideband) && | 
|  | (frameSize != 30) && | 
|  | (bandwidthKHz != isac8kHz)) { | 
|  | /* Cannot have 60 ms in super-wideband. */ | 
|  | instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | status = ControlLb(&instISAC->instLB, rateLB, frameSize); | 
|  | if (status < 0) { | 
|  | instISAC->errorCode = -status; | 
|  | return -1; | 
|  | } | 
|  | if (bandwidthKHz != isac8kHz) { | 
|  | status = ControlUb(&(instISAC->instUB), rateUB); | 
|  | if (status < 0) { | 
|  | instISAC->errorCode = -status; | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Check if bandwidth is changing from wideband to super-wideband | 
|  | * then we have to synch data buffer of lower & upper-band. Also | 
|  | * clean up the upper-band data buffer. */ | 
|  |  | 
|  | if ((instISAC->bandwidthKHz == isac8kHz) && (bandwidthKHz != isac8kHz)) { | 
|  | memset(instISAC->instUB.ISACencUB_obj.data_buffer_float, 0, | 
|  | sizeof(float) * (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES)); | 
|  |  | 
|  | if (bandwidthKHz == isac12kHz) { | 
|  | instISAC->instUB.ISACencUB_obj.buffer_index = | 
|  | instISAC->instLB.ISACencLB_obj.buffer_index; | 
|  | } else { | 
|  | instISAC->instUB.ISACencUB_obj.buffer_index = | 
|  | LB_TOTAL_DELAY_SAMPLES + instISAC->instLB.ISACencLB_obj.buffer_index; | 
|  |  | 
|  | memcpy(&(instISAC->instUB.ISACencUB_obj.lastLPCVec), | 
|  | WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Update the payload limit if the bandwidth is changing. */ | 
|  | if (instISAC->bandwidthKHz != bandwidthKHz) { | 
|  | instISAC->bandwidthKHz = bandwidthKHz; | 
|  | UpdatePayloadSizeLimit(instISAC); | 
|  | } | 
|  | instISAC->bottleneck = bottleneckBPS; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_ControlBwe(...) | 
|  | * | 
|  | * This function sets the initial values of bottleneck and frame-size if | 
|  | * iSAC is used in channel-adaptive mode. Through this API, users can | 
|  | * enforce a frame-size for all values of bottleneck. Then iSAC will not | 
|  | * automatically change the frame-size. | 
|  | * | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance. | 
|  | *        - rateBPS           : initial value of bottleneck in bits/second | 
|  | *                              10000 <= rateBPS <= 32000 is accepted | 
|  | *                              For default bottleneck set rateBPS = 0 | 
|  | *        - frameSizeMs       : number of milliseconds per frame (30 or 60) | 
|  | *        - enforceFrameSize  : 1 to enforce the given frame-size through out | 
|  | *                              the adaptation process, 0 to let iSAC change | 
|  | *                              the frame-size if required. | 
|  | * | 
|  | * Return value               : 0 - ok | 
|  | *                             -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word32 bottleneckBPS, | 
|  | WebRtc_Word16 frameSizeMs, | 
|  | WebRtc_Word16 enforceFrameSize) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | enum ISACBandwidth bandwidth; | 
|  |  | 
|  | /* Check if encoder initiated */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Check that we are in channel-adaptive mode, otherwise, return (-1) */ | 
|  | if (instISAC->codingMode != 0) { | 
|  | instISAC->errorCode = ISAC_MODE_MISMATCH; | 
|  | return -1; | 
|  | } | 
|  | if ((frameSizeMs != 30) && | 
|  | (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Set structure variable if enforceFrameSize is set. ISAC will then | 
|  | * keep the chosen frame size. */ | 
|  | if (enforceFrameSize != 0) { | 
|  | instISAC->instLB.ISACencLB_obj.enforceFrameSize = 1; | 
|  | } else { | 
|  | instISAC->instLB.ISACencLB_obj.enforceFrameSize = 0; | 
|  | } | 
|  |  | 
|  | /* Set the initial rate. If the input value is zero then the default intial | 
|  | * rate is used. Otehrwise, values between 10 to 32 kbps are accepted. */ | 
|  | if (bottleneckBPS != 0) { | 
|  | double rateLB; | 
|  | double rateUB; | 
|  | if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB, | 
|  | &bandwidth) < 0) { | 
|  | return -1; | 
|  | } | 
|  | instISAC->bwestimator_obj.send_bw_avg = (float)bottleneckBPS; | 
|  | instISAC->bandwidthKHz = bandwidth; | 
|  | } | 
|  |  | 
|  | /* Set the initial frame-size. If 'enforceFrameSize' is set, the frame-size | 
|  | *  will not change */ | 
|  | if (frameSizeMs != 0) { | 
|  | if ((frameSizeMs  == 30) || (frameSizeMs == 60)) { | 
|  | instISAC->instLB.ISACencLB_obj.new_framelength = (FS / 1000) * | 
|  | frameSizeMs; | 
|  | } else { | 
|  | instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH; | 
|  | return -1; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_GetDownLinkBwIndex(...) | 
|  | * | 
|  | * This function returns index representing the Bandwidth estimate from | 
|  | * the other side to this side. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC structure | 
|  | * | 
|  | * Output: | 
|  | *        - bweIndex         : Bandwidth estimate to transmit to other side. | 
|  | * | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetDownLinkBwIndex(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16* bweIndex, | 
|  | WebRtc_Word16* jitterInfo) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | /* Check if encoder initialized. */ | 
|  | if ((instISAC->initFlag & BIT_MASK_DEC_INIT) != | 
|  | BIT_MASK_DEC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Call function to get Bandwidth Estimate. */ | 
|  | WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj), bweIndex, | 
|  | jitterInfo, | 
|  | instISAC->decoderSamplingRateKHz); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_UpdateUplinkBw(...) | 
|  | * | 
|  | * This function takes an index representing the Bandwidth estimate from | 
|  | * this side to other side and updates BWE. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC structure | 
|  | *        - rateIndex         : Bandwidth estimate from other side. | 
|  | * | 
|  | * Return value               : 0 - ok | 
|  | *                             -1 - index out of range | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_UpdateUplinkBw(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16 bweIndex) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WebRtc_Word16 returnVal; | 
|  |  | 
|  | /* Check if encoder initiated. */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Call function to get Bandwidth Estimate. */ | 
|  | returnVal = WebRtcIsac_UpdateUplinkBwImpl( | 
|  | &(instISAC->bwestimator_obj), bweIndex, | 
|  | instISAC->encoderSamplingRateKHz); | 
|  |  | 
|  | if (returnVal < 0) { | 
|  | instISAC->errorCode = -returnVal; | 
|  | return -1; | 
|  | } else { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_ReadBwIndex(...) | 
|  | * | 
|  | * This function returns the index of the Bandwidth estimate from the | 
|  | * bit-stream. | 
|  | * | 
|  | * Input: | 
|  | *        - encoded           : Encoded bit-stream | 
|  | * | 
|  | * Output: | 
|  | *        - frameLength       : Length of frame in packet (in samples) | 
|  | *        - bweIndex          : Bandwidth estimate in bit-stream | 
|  | * | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_ReadBwIndex(const WebRtc_Word16* encoded, | 
|  | WebRtc_Word16* bweIndex) { | 
|  | Bitstr streamdata; | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | int k; | 
|  | #endif | 
|  | WebRtc_Word16 err; | 
|  |  | 
|  | WebRtcIsac_ResetBitstream(&(streamdata)); | 
|  |  | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < 10; k++) { | 
|  | streamdata.stream[k] = (WebRtc_UWord8)((encoded[k >> 1] >> | 
|  | ((k & 1) << 3)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(streamdata.stream, encoded, 10); | 
|  | #endif | 
|  |  | 
|  | /* Decode frame length. */ | 
|  | err = WebRtcIsac_DecodeFrameLen(&streamdata, bweIndex); | 
|  | if (err < 0) { | 
|  | return err; | 
|  | } | 
|  |  | 
|  | /* Decode BW estimation. */ | 
|  | err = WebRtcIsac_DecodeSendBW(&streamdata, bweIndex); | 
|  | if (err < 0) { | 
|  | return err; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_ReadFrameLen(...) | 
|  | * | 
|  | * This function returns the number of samples the decoder will generate if | 
|  | * the given payload is decoded. | 
|  | * | 
|  | * Input: | 
|  | *        - encoded           : Encoded bitstream | 
|  | * | 
|  | * Output: | 
|  | *        - frameLength       : Length of frame in packet (in samples) | 
|  | * | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_ReadFrameLen(ISACStruct* ISAC_main_inst, | 
|  | const WebRtc_Word16* encoded, | 
|  | WebRtc_Word16* frameLength) { | 
|  | Bitstr streamdata; | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | int k; | 
|  | #endif | 
|  | WebRtc_Word16 err; | 
|  | ISACMainStruct* instISAC; | 
|  |  | 
|  | WebRtcIsac_ResetBitstream(&(streamdata)); | 
|  |  | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < 10; k++) { | 
|  | streamdata.stream[k] = (WebRtc_UWord8)((encoded[k >> 1] >> | 
|  | ((k & 1) << 3)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(streamdata.stream, encoded, 10); | 
|  | #endif | 
|  |  | 
|  | /* Decode frame length. */ | 
|  | err = WebRtcIsac_DecodeFrameLen(&streamdata, frameLength); | 
|  | if (err < 0) { | 
|  | return -1; | 
|  | } | 
|  | instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | /* The decoded frame length indicates the number of samples in | 
|  | * lower-band in this case, multiply by 2 to get the total number | 
|  | * of samples. */ | 
|  | *frameLength <<= 1; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /******************************************************************************* | 
|  | * WebRtcIsac_GetNewFrameLen(...) | 
|  | * | 
|  | * This function returns the frame length (in samples) of the next packet. | 
|  | * In the case of channel-adaptive mode, iSAC decides on its frame length based | 
|  | * on the estimated bottleneck, this AOI allows a user to prepare for the next | 
|  | * packet (at the encoder). | 
|  | * | 
|  | * The primary usage is in CE to make the iSAC works in channel-adaptive mode | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst     : iSAC struct | 
|  | * | 
|  | * Return Value                : frame lenght in samples | 
|  | * | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetNewFrameLen(ISACStruct* ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | /* Return new frame length. */ | 
|  | if (instISAC->in_sample_rate_hz == 16000) | 
|  | return (instISAC->instLB.ISACencLB_obj.new_framelength); | 
|  | else if (instISAC->in_sample_rate_hz == 32000) | 
|  | return ((instISAC->instLB.ISACencLB_obj.new_framelength) * 2); | 
|  | else | 
|  | return ((instISAC->instLB.ISACencLB_obj.new_framelength) * 3); | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_GetErrorCode(...) | 
|  | * | 
|  | * This function can be used to check the error code of an iSAC instance. | 
|  | * When a function returns -1 an error code will be set for that instance. | 
|  | * The function below extracts the code of the last error that occurred in | 
|  | * the specified instance. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : ISAC instance | 
|  | * | 
|  | * Return value               : Error code | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetErrorCode(ISACStruct* ISAC_main_inst) { | 
|  | return ((ISACMainStruct*)ISAC_main_inst)->errorCode; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_GetUplinkBw(...) | 
|  | * | 
|  | * This function outputs the target bottleneck of the codec. In | 
|  | * channel-adaptive mode, the target bottleneck is specified through an in-band | 
|  | * signalling retrieved by bandwidth estimator. | 
|  | * In channel-independent, also called instantaneous mode, the target | 
|  | * bottleneck is provided to the encoder by calling xxx_control(...) (if | 
|  | * xxx_control is never called, the default values are used.). | 
|  | * Note that the output is the iSAC internal operating bottleneck which might | 
|  | * differ slightly from the one provided through xxx_control(). | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | * | 
|  | * Output: | 
|  | *        - *bottleneck       : bottleneck in bits/sec | 
|  | * | 
|  | * Return value               : -1 if error happens | 
|  | *                               0 bit-rates computed correctly. | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetUplinkBw(ISACStruct*  ISAC_main_inst, | 
|  | WebRtc_Word32* bottleneck) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  |  | 
|  | if (instISAC->codingMode == 0) { | 
|  | /* We are in adaptive mode then get the bottleneck from BWE. */ | 
|  | *bottleneck = (WebRtc_Word32)instISAC->bwestimator_obj.send_bw_avg; | 
|  | } else { | 
|  | *bottleneck = instISAC->bottleneck; | 
|  | } | 
|  |  | 
|  | if ((*bottleneck > 32000) && (*bottleneck < 38000)) { | 
|  | *bottleneck = 32000; | 
|  | } else if ((*bottleneck > 45000) && (*bottleneck < 50000)) { | 
|  | *bottleneck = 45000; | 
|  | } else if (*bottleneck > 56000) { | 
|  | *bottleneck = 56000; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_SetMaxPayloadSize(...) | 
|  | * | 
|  | * This function sets a limit for the maximum payload size of iSAC. The same | 
|  | * value is used both for 30 and 60 ms packets. If the encoder sampling rate | 
|  | * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the | 
|  | * encoder sampling rate is 32 kHz the maximum payload size is between 120 | 
|  | * and 600 bytes. | 
|  | * | 
|  | * --------------- | 
|  | * IMPORTANT NOTES | 
|  | * --------------- | 
|  | * The size of a packet is limited to the minimum of 'max-payload-size' and | 
|  | * 'max-rate.' For instance, let's assume the max-payload-size is set to | 
|  | * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps | 
|  | * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms | 
|  | * frame-size. Then a packet with a frame-size of 30 ms is limited to 150, | 
|  | * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to | 
|  | * 170 bytes, i.e. min(170, 300). | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | *        - maxPayloadBytes   : maximum size of the payload in bytes | 
|  | *                              valid values are between 100 and 400 bytes | 
|  | *                              if encoder sampling rate is 16 kHz. For | 
|  | *                              32 kHz encoder sampling rate valid values | 
|  | *                              are between 100 and 600 bytes. | 
|  | * | 
|  | * Return value               : 0 if successful | 
|  | *                             -1 if error happens | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_SetMaxPayloadSize(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16 maxPayloadBytes) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WebRtc_Word16 status = 0; | 
|  |  | 
|  | /* Check if encoder initiated */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) { | 
|  | /* Sanity check. */ | 
|  | if (maxPayloadBytes < 120) { | 
|  | /* 'maxRate' is out of valid range | 
|  | * set to the acceptable value and return -1. */ | 
|  | maxPayloadBytes = 120; | 
|  | status = -1; | 
|  | } | 
|  |  | 
|  | /* sanity check */ | 
|  | if (maxPayloadBytes > STREAM_SIZE_MAX) { | 
|  | /* maxRate is out of valid range, | 
|  | * set to the acceptable value and return -1. */ | 
|  | maxPayloadBytes = STREAM_SIZE_MAX; | 
|  | status = -1; | 
|  | } | 
|  | } else { | 
|  | if (maxPayloadBytes < 120) { | 
|  | /* Max payload-size is out of valid range | 
|  | * set to the acceptable value and return -1. */ | 
|  | maxPayloadBytes = 120; | 
|  | status = -1; | 
|  | } | 
|  | if (maxPayloadBytes > STREAM_SIZE_MAX_60) { | 
|  | /* Max payload-size is out of valid range | 
|  | * set to the acceptable value and return -1. */ | 
|  | maxPayloadBytes = STREAM_SIZE_MAX_60; | 
|  | status = -1; | 
|  | } | 
|  | } | 
|  | instISAC->maxPayloadSizeBytes = maxPayloadBytes; | 
|  | UpdatePayloadSizeLimit(instISAC); | 
|  | return status; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_SetMaxRate(...) | 
|  | * | 
|  | * This function sets the maximum rate which the codec may not exceed for | 
|  | * any signal packet. The maximum rate is defined and payload-size per | 
|  | * frame-size in bits per second. | 
|  | * | 
|  | * The codec has a maximum rate of 53400 bits per second (200 bytes per 30 | 
|  | * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms) | 
|  | * if the encoder sampling rate is 32 kHz. | 
|  | * | 
|  | * It is possible to set a maximum rate between 32000 and 53400 bits/sec | 
|  | * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode. | 
|  | * | 
|  | * --------------- | 
|  | * IMPORTANT NOTES | 
|  | * --------------- | 
|  | * The size of a packet is limited to the minimum of 'max-payload-size' and | 
|  | * 'max-rate.' For instance, let's assume the max-payload-size is set to | 
|  | * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps | 
|  | * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms | 
|  | * frame-size. Then a packet with a frame-size of 30 ms is limited to 150, | 
|  | * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to | 
|  | * 170 bytes, min(170, 300). | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | *        - maxRate           : maximum rate in bits per second, | 
|  | *                              valid values are 32000 to 53400 bits/sec in | 
|  | *                              wideband mode, and 32000 to 160000 bits/sec in | 
|  | *                              super-wideband mode. | 
|  | * | 
|  | * Return value               : 0 if successful | 
|  | *                             -1 if error happens | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_SetMaxRate(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word32 maxRate) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | WebRtc_Word16 maxRateInBytesPer30Ms; | 
|  | WebRtc_Word16 status = 0; | 
|  |  | 
|  | /* check if encoder initiated */ | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | return -1; | 
|  | } | 
|  | /* Calculate maximum number of bytes per 30 msec packets for the | 
|  | given maximum rate. Multiply with 30/1000 to get number of | 
|  | bits per 30 ms, divide by 8 to get number of bytes per 30 ms: | 
|  | maxRateInBytes = floor((maxRate * 30/1000) / 8); */ | 
|  | maxRateInBytesPer30Ms = (WebRtc_Word16)(maxRate * 3 / 800); | 
|  |  | 
|  | if (instISAC->encoderSamplingRateKHz == kIsacWideband) { | 
|  | if (maxRate < 32000) { | 
|  | /* 'maxRate' is out of valid range. | 
|  | * Set to the acceptable value and return -1. */ | 
|  | maxRateInBytesPer30Ms = 120; | 
|  | status = -1; | 
|  | } | 
|  |  | 
|  | if (maxRate > 53400) { | 
|  | /* 'maxRate' is out of valid range. | 
|  | * Set to the acceptable value and return -1. */ | 
|  | maxRateInBytesPer30Ms = 200; | 
|  | status = -1; | 
|  | } | 
|  | } else { | 
|  | if (maxRateInBytesPer30Ms < 120) { | 
|  | /* 'maxRate' is out of valid range | 
|  | * Set to the acceptable value and return -1. */ | 
|  | maxRateInBytesPer30Ms = 120; | 
|  | status = -1; | 
|  | } | 
|  |  | 
|  | if (maxRateInBytesPer30Ms > STREAM_SIZE_MAX) { | 
|  | /* 'maxRate' is out of valid range. | 
|  | * Set to the acceptable value and return -1. */ | 
|  | maxRateInBytesPer30Ms = STREAM_SIZE_MAX; | 
|  | status = -1; | 
|  | } | 
|  | } | 
|  | instISAC->maxRateBytesPer30Ms = maxRateInBytesPer30Ms; | 
|  | UpdatePayloadSizeLimit(instISAC); | 
|  | return status; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_GetRedPayload(...) | 
|  | * | 
|  | * This function populates "encoded" with the redundant payload of the recently | 
|  | * encodedframe. This function has to be called once that WebRtcIsac_Encode(...) | 
|  | * returns a positive value. Regardless of the frame-size this function will | 
|  | * be called only once after encoding is completed. The bit-stream is | 
|  | * targeted for 16000 bit/sec. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC struct | 
|  | * | 
|  | * Output: | 
|  | *        - encoded           : the encoded data vector | 
|  | * | 
|  | * | 
|  | * Return value               : >0 - Length (in bytes) of coded data | 
|  | *                            : -1 - Error | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_GetRedPayload(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_Word16* encoded) { | 
|  | Bitstr iSACBitStreamInst; | 
|  | WebRtc_Word16 streamLenLB; | 
|  | WebRtc_Word16 streamLenUB; | 
|  | WebRtc_Word16 streamLen; | 
|  | WebRtc_Word16 totalLenUB; | 
|  | WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded; | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | int k; | 
|  | #endif | 
|  |  | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED; | 
|  | } | 
|  |  | 
|  | WebRtcIsac_ResetBitstream(&(iSACBitStreamInst)); | 
|  |  | 
|  | streamLenLB = WebRtcIsac_EncodeStoredDataLb( | 
|  | &instISAC->instLB.ISACencLB_obj.SaveEnc_obj, | 
|  | &iSACBitStreamInst, | 
|  | instISAC->instLB.ISACencLB_obj.lastBWIdx, | 
|  | RCU_TRANSCODING_SCALE); | 
|  | if (streamLenLB < 0) { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* convert from bytes to WebRtc_Word16. */ | 
|  | memcpy(ptrEncodedUW8, iSACBitStreamInst.stream, streamLenLB); | 
|  | streamLen = streamLenLB; | 
|  | if (instISAC->bandwidthKHz == isac8kHz) { | 
|  | return streamLenLB; | 
|  | } | 
|  |  | 
|  | streamLenUB = WebRtcIsac_GetRedPayloadUb( | 
|  | &instISAC->instUB.ISACencUB_obj.SaveEnc_obj, | 
|  | &iSACBitStreamInst, instISAC->bandwidthKHz); | 
|  | if (streamLenUB < 0) { | 
|  | /* An error has happened but this is not the error due to a | 
|  | * bit-stream larger than the limit. */ | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* We have one byte to write the total length of the upper-band. | 
|  | * The length includes the bit-stream length, check-sum and the | 
|  | * single byte where the length is written to. This is according to | 
|  | * iSAC wideband and how the "garbage" is dealt. */ | 
|  | totalLenUB = streamLenUB + 1 + LEN_CHECK_SUM_WORD8; | 
|  | if (totalLenUB > 255) { | 
|  | streamLenUB = 0; | 
|  | } | 
|  |  | 
|  | /* Generate CRC if required. */ | 
|  | if ((instISAC->bandwidthKHz != isac8kHz) && | 
|  | (streamLenUB > 0)) { | 
|  | WebRtc_UWord32 crc; | 
|  | streamLen += totalLenUB; | 
|  | ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)totalLenUB; | 
|  | memcpy(&ptrEncodedUW8[streamLenLB + 1], iSACBitStreamInst.stream, | 
|  | streamLenUB); | 
|  |  | 
|  | WebRtcIsac_GetCrc((WebRtc_Word16*)(&(ptrEncodedUW8[streamLenLB + 1])), | 
|  | streamLenUB, &crc); | 
|  | #ifndef WEBRTC_BIG_ENDIAN | 
|  | for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) { | 
|  | ptrEncodedUW8[streamLen - LEN_CHECK_SUM_WORD8 + k] = | 
|  | (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF); | 
|  | } | 
|  | #else | 
|  | memcpy(&ptrEncodedUW8[streamLenLB + streamLenUB + 1], &crc, | 
|  | LEN_CHECK_SUM_WORD8); | 
|  | #endif | 
|  | } | 
|  | return streamLen; | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | * WebRtcIsac_version(...) | 
|  | * | 
|  | * This function returns the version number. | 
|  | * | 
|  | * Output: | 
|  | *        - version      : Pointer to character string | 
|  | * | 
|  | */ | 
|  | void WebRtcIsac_version(char* version) { | 
|  | strcpy(version, "4.3.0"); | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_SetEncSampRate() | 
|  | * This function sets the sampling rate of the encoder. Initialization of the | 
|  | * encoder WILL NOT overwrite the sampling rate of the encoder. The default | 
|  | * value is 16 kHz which is set when the instance is created. The encoding-mode | 
|  | * and the bottleneck remain unchanged by this call, however, the maximum rate | 
|  | * and maximum payload-size will be reset to their default values. | 
|  | * | 
|  | * NOTE: | 
|  | * The maximum internal sampling rate is 32 kHz. If the encoder sample rate is | 
|  | * set to 48 kHz the input is expected to be at 48 kHz but will be resampled to | 
|  | * 32 kHz before any further processing. | 
|  | * This mode is created for compatibility with full-band codecs if iSAC is used | 
|  | * in dual-streaming. See SetDecSampleRate() for sampling rates at the decoder. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | *        - sample_rate_hz    : sampling rate in Hertz, valid values are 16000, | 
|  | *                              32000 and 48000. | 
|  | * | 
|  | * Return value               : 0 if successful | 
|  | *                             -1 if failed. | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_UWord16 sample_rate_hz) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | enum IsacSamplingRate encoder_operational_rate; | 
|  |  | 
|  | if ((sample_rate_hz != 16000) && (sample_rate_hz != 32000) && | 
|  | (sample_rate_hz != 48000)) { | 
|  | /* Sampling Frequency is not supported. */ | 
|  | instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY; | 
|  | return -1; | 
|  | } | 
|  | if (sample_rate_hz == 16000) { | 
|  | encoder_operational_rate = kIsacWideband; | 
|  | } else { | 
|  | encoder_operational_rate = kIsacSuperWideband; | 
|  | } | 
|  |  | 
|  | if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != | 
|  | BIT_MASK_ENC_INIT) { | 
|  | if (encoder_operational_rate == kIsacWideband) { | 
|  | instISAC->bandwidthKHz = isac8kHz; | 
|  | } else { | 
|  | instISAC->bandwidthKHz = isac16kHz; | 
|  | } | 
|  | } else { | 
|  | ISACUBStruct* instUB = &(instISAC->instUB); | 
|  | ISACLBStruct* instLB = &(instISAC->instLB); | 
|  | double bottleneckLB; | 
|  | double bottleneckUB; | 
|  | WebRtc_Word32 bottleneck = instISAC->bottleneck; | 
|  | WebRtc_Word16 codingMode = instISAC->codingMode; | 
|  | WebRtc_Word16 frameSizeMs = instLB->ISACencLB_obj.new_framelength / | 
|  | (FS / 1000); | 
|  |  | 
|  | if ((encoder_operational_rate == kIsacWideband) && | 
|  | (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) { | 
|  | /* Changing from super-wideband to wideband. | 
|  | * we don't need to re-initialize the encoder of the lower-band. */ | 
|  | instISAC->bandwidthKHz = isac8kHz; | 
|  | if (codingMode == 1) { | 
|  | ControlLb(instLB, | 
|  | (bottleneck > 32000) ? 32000 : bottleneck, FRAMESIZE); | 
|  | } | 
|  | instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60; | 
|  | instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30; | 
|  | } else if ((encoder_operational_rate == kIsacSuperWideband) && | 
|  | (instISAC->encoderSamplingRateKHz == kIsacWideband)) { | 
|  | if (codingMode == 1) { | 
|  | WebRtcIsac_RateAllocation(bottleneck, &bottleneckLB, &bottleneckUB, | 
|  | &(instISAC->bandwidthKHz)); | 
|  | } | 
|  |  | 
|  | instISAC->bandwidthKHz = isac16kHz; | 
|  | instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX; | 
|  | instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX; | 
|  |  | 
|  | EncoderInitLb(instLB, codingMode, encoder_operational_rate); | 
|  | EncoderInitUb(instUB, instISAC->bandwidthKHz); | 
|  |  | 
|  | memset(instISAC->analysisFBState1, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  | memset(instISAC->analysisFBState2, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  |  | 
|  | if (codingMode == 1) { | 
|  | instISAC->bottleneck = bottleneck; | 
|  | ControlLb(instLB, bottleneckLB, | 
|  | (instISAC->bandwidthKHz == isac8kHz) ? frameSizeMs:FRAMESIZE); | 
|  | if (instISAC->bandwidthKHz > isac8kHz) { | 
|  | ControlUb(instUB, bottleneckUB); | 
|  | } | 
|  | } else { | 
|  | instLB->ISACencLB_obj.enforceFrameSize = 0; | 
|  | instLB->ISACencLB_obj.new_framelength = FRAMESAMPLES; | 
|  | } | 
|  | } | 
|  | } | 
|  | instISAC->encoderSamplingRateKHz = encoder_operational_rate; | 
|  | instISAC->in_sample_rate_hz = sample_rate_hz; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_SetDecSampRate() | 
|  | * This function sets the sampling rate of the decoder. Initialization of the | 
|  | * decoder WILL NOT overwrite the sampling rate of the encoder. The default | 
|  | * value is 16 kHz which is set when the instance is created. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | *        - sample_rate_hz    : sampling rate in Hertz, valid values are 16000 | 
|  | *                              and 32000. | 
|  | * | 
|  | * Return value               : 0 if successful | 
|  | *                             -1 if failed. | 
|  | */ | 
|  | WebRtc_Word16 WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst, | 
|  | WebRtc_UWord16 sample_rate_hz) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | enum IsacSamplingRate decoder_operational_rate; | 
|  |  | 
|  | if (sample_rate_hz == 16000) { | 
|  | decoder_operational_rate = kIsacWideband; | 
|  | } else if (sample_rate_hz == 32000) { | 
|  | decoder_operational_rate = kIsacSuperWideband; | 
|  | } else { | 
|  | /* Sampling Frequency is not supported. */ | 
|  | instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if ((instISAC->decoderSamplingRateKHz == kIsacWideband) && | 
|  | (decoder_operational_rate == kIsacSuperWideband)) { | 
|  | /* Switching from wideband to super-wideband at the decoder | 
|  | * we need to reset the filter-bank and initialize upper-band decoder. */ | 
|  | memset(instISAC->synthesisFBState1, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  | memset(instISAC->synthesisFBState2, 0, | 
|  | FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32)); | 
|  |  | 
|  | if (DecoderInitUb(&(instISAC->instUB)) < 0) { | 
|  | return -1; | 
|  | } | 
|  | } | 
|  | instISAC->decoderSamplingRateKHz = decoder_operational_rate; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_EncSampRate() | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | * | 
|  | * Return value               : sampling rate in Hertz. The input to encoder | 
|  | *                              is expected to be sampled in this rate. | 
|  | * | 
|  | */ | 
|  | WebRtc_UWord16 WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | return instISAC->in_sample_rate_hz; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WebRtcIsac_DecSampRate() | 
|  | * Return the sampling rate of the decoded audio. | 
|  | * | 
|  | * Input: | 
|  | *        - ISAC_main_inst    : iSAC instance | 
|  | * | 
|  | * Return value               : sampling rate in Hertz. Decoder output is | 
|  | *                              sampled at this rate. | 
|  | * | 
|  | */ | 
|  | WebRtc_UWord16 WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst) { | 
|  | ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst; | 
|  | return instISAC->decoderSamplingRateKHz == kIsacWideband ? 16000 : 32000; | 
|  | } |