Added iSAC coder.
- Imported the floating point implementation of iSAC coder from stable public webRTC release:
http://code.google.com/p/webrtc/source/browse/#svn%2Fstable
- Added a reminder (in a TODO file) to switch from floating point to fixed point implementation.
Please note that this is the minimal amount of functionality we (the speech text-to-speech team) require
for delivering our unit selection algorithms for the Glass project. I'd be happy to address any comments
you have.
Change-Id: I20481680786ec5372258efcea69ea5c9750a321a
diff --git a/Android.mk b/Android.mk
index dc214e9..a6e7a49 100644
--- a/Android.mk
+++ b/Android.mk
@@ -20,6 +20,7 @@
include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_processing/utility/Android.mk
#include $(MY_WEBRTC_ROOT_PATH)/src/modules/utility/source/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/system_wrappers/source/Android.mk
+include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_coding/codecs/isac/main/source/Android.mk
# build .so
LOCAL_PATH := $(call my-dir)
@@ -65,3 +66,29 @@
endif
include $(BUILD_SHARED_LIBRARY)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../external/webrtc/android-webrtc.mk
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE := libwebrtc_audio_coding
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+ libwebrtc_isac \
+ libwebrtc_spl \
+ libwebrtc_system_wrappers
+
+LOCAL_STATIC_LIBRARIES := \
+ libprotobuf-cpp-2.3.0-lite
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl \
+ libstlport
+
+LOCAL_PRELINK_MODULE := false
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_SHARED_LIBRARY)
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..a5f997a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+Alexander Gutkin <agutkin@google.com>: Switch the iSAC codec to be
+ fixed rather than floating point. The current code uses floating
+ point implementation for purely experimental reasons.
diff --git a/src/modules/audio_coding/codecs/isac/main/interface/isac.h b/src/modules/audio_coding/codecs/isac/main/interface/isac.h
new file mode 100644
index 0000000..03c260b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/interface/isac.h
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
+
+/*
+ * Define the fixed-point numeric formats
+ */
+#include "typedefs.h"
+
+typedef struct WebRtcISACStruct ISACStruct;
+
+enum IsacSamplingRate {kIsacWideband = 16, kIsacSuperWideband = 32};
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ /******************************************************************************
+ * WebRtcIsac_AssignSize(...)
+ *
+ * This function returns the size of the ISAC instance, so that the instance
+ * can be created outside iSAC.
+ *
+ * Input:
+ * - samplingRate : sampling rate of the input/output audio.
+ *
+ * Output:
+ * - sizeinbytes : number of bytes needed to allocate for the
+ * instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_AssignSize(
+ int* sizeinbytes);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Assign(...)
+ *
+ * This function assignes the memory already created to the ISAC instance.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ * - samplingRate : sampling rate of the input/output audio.
+ * - ISAC_inst_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* ISAC_inst_Addr);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Create(
+ ISACStruct** ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : an ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Free(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_EncoderInit(...)
+ *
+ * This function initializes an 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, just valid if codec
+ * is created to work in 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
+ */
+
+ WebRtc_Word16 WebRtcIsac_EncoderInit(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 CodingMode);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms audio blocks and inserts it into a package.
+ * Input speech length has 160 samples if operating at 16 kHz sampling
+ * rate, or 320 if operating at 32 kHz sampling rate. The encoder buffers the
+ * input audio until the whole frame is buffered then proceeds with 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
+ * frame-size so it keeps buffering speech
+ * samples.
+ * : -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Encode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* speechIn,
+ WebRtc_Word16* encoded);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ *
+ * Return value
+ * : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_DecoderInit(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * 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.
+ * - send_ts : the RTP send timestamp, given in samples
+ * - 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);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes an ISAC frame. At 16 kHz sampling rate, the length
+ * of the output audio could be either 480 or 960 samples, equivalent to
+ * 30 or 60 ms respectively. At 32 kHz sampling rate, the length of the
+ * output audio is 960 samples, which is 30 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 len,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of frames, i.e. multiples of 30 ms audio. Therefore,
+ * the output is multiple of 480 samples if operating at 16 kHz and multiple
+ * of 960 if operating at 32 kHz.
+ *
+ * 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);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Control(...)
+ *
+ * This function sets the limit on the short-term average bit-rate and the
+ * frame length. Should be used only in Instantaneous mode. At 16 kHz sampling
+ * rate, an average bit-rate between 10000 to 32000 bps is valid and a
+ * frame-size of 30 or 60 ms is acceptable. At 32 kHz, an average bit-rate
+ * between 10000 to 56000 is acceptable, and the valid frame-size is 30 ms.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second.
+ * - framesize : frame-size in millisecond.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Control(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 rate,
+ WebRtc_Word16 framesize);
+
+
+ /******************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Therefore, this API is not
+ * applicable if the codec is created to operate in super-wideband 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 <= 56000 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 rateBPS,
+ WebRtc_Word16 frameSizeMs,
+ WebRtc_Word16 enforceFrameSize);
+
+
+ /******************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bit-stream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_ReadFrameLen(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* frameLength);
+
+
+ /******************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+ void WebRtcIsac_version(
+ char *version);
+
+
+ /******************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract 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);
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through in-band
+ * signalling retreived 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 is returned. The default
+ * value for bottleneck at 16 kHz encoder sampling rate is 32000 bits/sec,
+ * and it is 56000 bits/sec for 32 kHz sampling rate.
+ * 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);
+
+
+ /******************************************************************************
+ * 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.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * 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 120 and 400 bytes
+ * if encoder sampling rate is 16 kHz. For
+ * 32 kHz encoder sampling rate valid values
+ * are between 120 and 600 bytes.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetMaxPayloadSize(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 maxPayloadBytes);
+
+
+ /******************************************************************************
+ * 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.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * 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);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the decoder, i.e. the
+ * sampling rate of the decoded audio.
+ *
+ */
+
+ enum IsacSamplingRate WebRtcIsac_DecSampRate(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the encoder, the input audio
+ * is expected to be sampled at this rate.
+ *
+ */
+
+ enum IsacSamplingRate WebRtcIsac_EncSampRate(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * Set 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
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetDecSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * Set 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 reset to their default value.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetEncSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate);
+
+
+
+ /******************************************************************************
+ * 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! Currently not implemented for SWB mode.
+ * NOTE 3! 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.
+ * - isRCU : if the new bit-stream is an RCU stream.
+ * Note that the rate parameter always indicates
+ * the target rate of the main paylaod, regardless
+ * of 'isRCU' value.
+ *
+ * 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);
+
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - bweIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_GetDownLinkBwIndex(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* bweIndex,
+ WebRtc_Word16* jitterInfo);
+
+
+ /****************************************************************************
+ * 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 struct
+ * - bweIndex : Bandwidth estimate from other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkBw(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 bweIndex);
+
+
+ /****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - bweIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_ReadBwIndex(
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* bweIndex);
+
+
+
+ /*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * returns the frame lenght (in samples) of the next packet. In the case of channel-adaptive
+ * mode, iSAC decides on its frame lenght based on the estimated bottleneck
+ * this 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);
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * Populates "encoded" with the redundant payload of the recently encoded
+ * frame. 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.
+ *
+ * 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);
+
+
+ /****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload i 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 len,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/Android.mk b/src/modules/audio_coding/codecs/isac/main/source/Android.mk
new file mode 100644
index 0000000..07b2a31
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/Android.mk
@@ -0,0 +1,66 @@
+# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/../../../../../../../android-webrtc.mk
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_isac
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ arith_routines.c \
+ arith_routines_hist.c \
+ arith_routines_logist.c \
+ bandwidth_estimator.c \
+ crc.c \
+ decode.c \
+ decode_bwe.c \
+ encode.c \
+ encode_lpc_swb.c \
+ entropy_coding.c \
+ fft.c \
+ filter_functions.c \
+ filterbank_tables.c \
+ intialize.c \
+ isac.c \
+ filterbanks.c \
+ pitch_lag_tables.c \
+ lattice.c \
+ lpc_gain_swb_tables.c \
+ lpc_analysis.c \
+ lpc_shape_swb12_tables.c \
+ lpc_shape_swb16_tables.c \
+ lpc_tables.c \
+ pitch_estimator.c \
+ pitch_filter.c \
+ pitch_gain_tables.c \
+ spectrum_ar_model_tables.c \
+ transform.c
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../interface \
+ $(LOCAL_PATH)/../../../../../.. \
+ $(LOCAL_PATH)/../../../../../../common_audio/signal_processing/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl \
+ libstlport
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/modules/audio_coding/codecs/isac/main/source/arith_routines.c b/src/modules/audio_coding/codecs/isac/main/source/arith_routines.c
new file mode 100644
index 0000000..31c441a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/arith_routines.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "arith_routines.h"
+#include "settings.h"
+
+
+/*
+ * terminate and return byte stream;
+ * returns the number of bytes in the stream
+ */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata) /* in-/output struct containing bitstream */
+{
+ WebRtc_UWord8 *stream_ptr;
+
+
+ /* point to the right place in the stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+
+ /* find minimum length (determined by current interval width) */
+ if ( streamdata->W_upper > 0x01FFFFFF )
+ {
+ streamdata->streamval += 0x01000000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x01000000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ }
+ else
+ {
+ streamdata->streamval += 0x00010000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x00010000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ *stream_ptr++ = (WebRtc_UWord8) ((streamdata->streamval >> 16) & 0x00FF);
+ }
+
+ /* calculate stream length */
+ return (int)(stream_ptr - streamdata->stream);
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/arith_routines.h b/src/modules/audio_coding/codecs/isac/main/source/arith_routines.h
new file mode 100644
index 0000000..8e5f496
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/arith_routines.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+
+#include "structs.h"
+
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ WebRtc_Word16 *dataQ7, /* input: data vector */
+ const WebRtc_UWord16 *env, /* input: side info vector defining the width of the pdf */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+/* returns the number of bytes in the stream */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata); /* in-/output struct containing bitstream */
+
+/* returns the number of bytes in the stream so far */
+int WebRtcIsac_DecLogisticMulti2(
+ WebRtc_Word16 *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 *env, /* input: side info vector defining the width of the pdf */
+ const WebRtc_Word16 *dither, /* input: dither vector */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+void WebRtcIsac_EncHistMulti(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const int *data, /* input: data vector */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistBisectMulti(
+ int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ const int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistOneStepMulti(
+ int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *init_index,/* input: vector of initial cdf table search entries */
+ const int N); /* input: data vector length */
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c b/src/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
new file mode 100644
index 0000000..f4a13d6
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "settings.h"
+#include "arith_routines.h"
+
+
+/*
+ * code symbols into arithmetic bytestream
+ */
+void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const int *data, /* input: data vector */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord8 *stream_ptr_carry;
+ WebRtc_UWord32 cdf_lo, cdf_hi;
+ int k;
+
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ for (k=N; k>0; k--)
+ {
+ /* fetch cdf_lower and cdf_upper from cdf tables */
+ cdf_lo = (WebRtc_UWord32) *(*cdf + *data);
+ cdf_hi = (WebRtc_UWord32) *(*cdf++ + *data++ + 1);
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, using method of bisection
+ * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
+ */
+int WebRtcIsac_DecHistBisectMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ const WebRtc_UWord16 *cdf_ptr;
+ int size_tmp;
+ int k;
+
+ W_lower = 0; //to remove warning -DH
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start halfway the cdf range */
+ size_tmp = *cdf_size++ >> 1;
+ cdf_ptr = *cdf + (size_tmp - 1);
+
+ /* method of bisection */
+ for ( ;; )
+ {
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ size_tmp >>= 1;
+ if (size_tmp == 0) break;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ cdf_ptr += size_tmp;
+ } else {
+ W_upper = W_tmp;
+ cdf_ptr -= size_tmp;
+ }
+ }
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ } else {
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, taking single step up or
+ * down at a time
+ * cdf tables can be of arbitrary size, but large tables may take a lot of iterations
+ */
+int WebRtcIsac_DecHistOneStepMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *init_index, /* input: vector of initial cdf table search entries */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ const WebRtc_UWord16 *cdf_ptr;
+ int k;
+
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start at the specified table entry */
+ cdf_ptr = *cdf + (*init_index++);
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp)
+ {
+ for ( ;; )
+ {
+ W_lower = W_tmp;
+ if (cdf_ptr[0]==65535)
+ /* range check */
+ return -3;
+ W_tmp = W_upper_MSB * *++cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval <= W_tmp) break;
+ }
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ } else {
+ for ( ;; )
+ {
+ W_upper = W_tmp;
+ --cdf_ptr;
+ if (cdf_ptr<*cdf) {
+ /* range check */
+ return -3;
+ }
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp) break;
+ }
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c b/src/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
new file mode 100644
index 0000000..422855a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * This file contains functions for arithmatically encoding and
+ * decoding DFT coefficients.
+ *
+ */
+
+
+#include "arith_routines.h"
+
+
+
+static const WebRtc_Word32 kHistEdgesQ15[51] = {
+ -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+ -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
+ -65536, -52429, -39322, -26215, -13108, 0, 13107, 26214, 39321, 52428,
+ 65536, 78643, 91750, 104857, 117964, 131072, 144179, 157286, 170393, 183500,
+ 196608, 209715, 222822, 235929, 249036, 262144, 275251, 288358, 301465, 314572,
+ 327680};
+
+
+static const int kCdfSlopeQ0[51] = { /* Q0 */
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 13, 23, 47, 87, 154, 315, 700, 1088,
+ 2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
+ 1095, 660, 316, 145, 86, 41, 32, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 0};
+
+
+static const int kCdfQ16[51] = { /* Q16 */
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 29, 38, 57, 92, 153, 279, 559,
+ 994, 1983, 4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
+ 64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
+ 65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
+ 65535};
+
+
+
+/* function to be converted to fixed point */
+static __inline WebRtc_UWord32 piecewise(WebRtc_Word32 xinQ15) {
+
+ WebRtc_Word32 ind, qtmp1, qtmp2, qtmp3;
+ WebRtc_UWord32 tmpUW32;
+
+
+ qtmp2 = xinQ15;
+
+ if (qtmp2 < kHistEdgesQ15[0]) {
+ qtmp2 = kHistEdgesQ15[0];
+ }
+ if (qtmp2 > kHistEdgesQ15[50]) {
+ qtmp2 = kHistEdgesQ15[50];
+ }
+
+ qtmp1 = qtmp2 - kHistEdgesQ15[0]; /* Q15 - Q15 = Q15 */
+ ind = (qtmp1 * 5) >> 16; /* 2^16 / 5 = 0.4 in Q15 */
+ /* Q15 -> Q0 */
+ qtmp1 = qtmp2 - kHistEdgesQ15[ind]; /* Q15 - Q15 = Q15 */
+ qtmp2 = kCdfSlopeQ0[ind] * qtmp1; /* Q0 * Q15 = Q15 */
+ qtmp3 = qtmp2>>15; /* Q15 -> Q0 */
+
+ tmpUW32 = kCdfQ16[ind] + qtmp3; /* Q0 + Q0 = Q0 */
+ return tmpUW32;
+}
+
+
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ WebRtc_Word16 *dataQ7, /* input: data vector */
+ const WebRtc_UWord16 *envQ8, /* input: side info vector defining the width of the pdf */
+ const int N, /* input: data vector length / 2 */
+ const WebRtc_Word16 isSWB12kHz)
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord8 *maxStreamPtr;
+ WebRtc_UWord8 *stream_ptr_carry;
+ WebRtc_UWord32 cdf_lo, cdf_hi;
+ int k;
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1;
+ for (k = 0; k < N; k++)
+ {
+ /* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+
+ /* test and clip if probability gets too small */
+ while (cdf_lo+1 >= cdf_hi) {
+ /* clip */
+ if (*dataQ7 > 0) {
+ *dataQ7 -= 128;
+ cdf_hi = cdf_lo;
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ } else {
+ *dataQ7 += 128;
+ cdf_lo = cdf_hi;
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+ }
+ }
+
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+
+ if(stream_ptr > maxStreamPtr)
+ {
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+ }
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return 0;
+}
+
+
+
+int WebRtcIsac_DecLogisticMulti2(
+ WebRtc_Word16 *dataQ7, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 *envQ8, /* input: side info vector defining the width of the pdf */
+ const WebRtc_Word16 *ditherQ7,/* input: dither vector */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz)
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord32 cdf_tmp;
+ WebRtc_Word16 candQ7;
+ int k;
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k = 0; k < N; k++)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* find first candidate by inverting the logistic cdf */
+ candQ7 = - *ditherQ7 + 64;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_lower == W_tmp) return -1;
+ }
+ W_upper = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 - 64;
+ }
+ else
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while ( !(streamval > W_tmp) )
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_upper == W_tmp) return -1;
+ }
+ W_lower = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 + 64;
+ }
+ ditherQ7++;
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c b/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
new file mode 100644
index 0000000..d0a50c5
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
@@ -0,0 +1,1020 @@
+/*
+ * 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.
+ */
+
+/*
+ * BwEstimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ */
+
+#include "bandwidth_estimator.h"
+#include "settings.h"
+#include "isac.h"
+
+#include <math.h>
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const float kQRateTableWb[12] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f};
+
+
+static const float kQRateTableSwb[24] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23153.1f, 25342.9f, 27532.7f, 29722.5f,
+ 31912.3f, 34102.1f, 36291.9f, 38481.7f, 40671.4f, 42861.2f,
+ 45051.0f, 47240.8f, 49430.6f, 51620.4f, 53810.2f, 56000.0f,
+};
+
+
+
+
+WebRtc_Word32 WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ switch(encoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_SWB;
+ break;
+ }
+ }
+
+ switch(decoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_WB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ bwest_str->rec_bw = (WebRtc_Word32)INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_WB + INIT_HDR_RATE_WB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_SWB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_SWB + INIT_HDR_RATE_SWB);
+ bwest_str->rec_bw = (WebRtc_Word32)INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_SWB + INIT_HDR_RATE_SWB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_SWB;
+ break;
+ }
+ }
+
+ bwest_str->prev_rec_rtp_number = 0;
+ bwest_str->prev_rec_arr_ts = 0;
+ bwest_str->prev_rec_send_ts = 0;
+ bwest_str->prev_rec_rtp_rate = 1.0f;
+ bwest_str->last_update_ts = 0;
+ bwest_str->last_reduction_ts = 0;
+ bwest_str->count_tot_updates_rec = -9;
+ bwest_str->rec_jitter = 10.0f;
+ bwest_str->rec_jitter_short_term = 0.0f;
+ bwest_str->rec_jitter_short_term_abs = 5.0f;
+ bwest_str->rec_max_delay = 10.0f;
+ bwest_str->rec_max_delay_avg_Q = 10.0f;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->send_max_delay_avg = 10.0f;
+
+ bwest_str->hsn_detect_rec = 0;
+
+ bwest_str->num_consec_rec_pkts_over_30k = 0;
+
+ bwest_str->hsn_detect_snd = 0;
+
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+
+ bwest_str->in_wait_period = 0;
+
+ bwest_str->change_to_WB = 0;
+
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->inWaitLatePkts = 0;
+ bwest_str->senderTimestamp = 0;
+ bwest_str->receiverTimestamp = 0;
+ return 0;
+}
+
+/* This function updates both bottle neck rates */
+/* Parameters: */
+/* rtp_number - value from RTP packet, from NetEq */
+/* frame length - length of signal frame in ms, from iSAC decoder */
+/* send_ts - value in RTP header giving send time in samples */
+/* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
+/* pksize - size of packet in bytes, from NetEq */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+WebRtc_Word16 WebRtcIsac_UpdateBandwidthEstimator(
+ BwEstimatorstr *bwest_str,
+ const WebRtc_UWord16 rtp_number,
+ const WebRtc_Word32 frame_length,
+ const WebRtc_UWord32 send_ts,
+ const WebRtc_UWord32 arr_ts,
+ const WebRtc_Word32 pksize
+ /*, const WebRtc_UWord16 Index*/)
+{
+ float weight = 0.0f;
+ float curr_bw_inv = 0.0f;
+ float rec_rtp_rate;
+ float t_diff_proj;
+ float arr_ts_diff;
+ float send_ts_diff;
+ float arr_time_noise;
+ float arr_time_noise_abs;
+
+ float delay_correction_factor = 1;
+ float late_diff = 0.0f;
+ int immediate_set = 0;
+ int num_pkts_expected;
+
+
+ // We have to adjust the header-rate if the first packet has a
+ // frame-size different than the initialized value.
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+ }
+
+ /* UPDATE ESTIMATES ON THIS SIDE */
+ /* compute far-side transmission rate */
+ rec_rtp_rate = ((float)pksize * 8.0f * 1000.0f / (float)frame_length) +
+ bwest_str->rec_header_rate;
+ // rec_rtp_rate packet bits/s + header bits/s
+
+ /* check for timer wrap-around */
+ if (arr_ts < bwest_str->prev_rec_arr_ts)
+ {
+ bwest_str->prev_rec_arr_ts = arr_ts;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ return 0;
+ }
+
+ bwest_str->num_pkts_rec++;
+
+ /* check that it's not one of the first 9 packets */
+ if ( bwest_str->count_tot_updates_rec > 0 )
+ {
+ if(bwest_str->in_wait_period > 0 )
+ {
+ bwest_str->in_wait_period--;
+ }
+
+ bwest_str->inWaitLatePkts -= ((bwest_str->inWaitLatePkts > 0)? 1:0);
+ send_ts_diff = (float)(send_ts - bwest_str->prev_rec_send_ts);
+
+ if (send_ts_diff <= (16 * frame_length)*2)
+ //doesn't allow for a dropped packet, not sure necessary to be
+ // that strict -DH
+ {
+ /* if not been updated for a long time, reduce the BN estimate */
+ if((WebRtc_UWord32)(arr_ts - bwest_str->last_update_ts) *
+ 1000.0f / FS > 3000)
+ {
+ //how many frames should have been received since the last
+ // update if too many have been dropped or there have been
+ // big delays won't allow this reduction may no longer need
+ // the send_ts_diff here
+ num_pkts_expected = (int)(((float)(arr_ts -
+ bwest_str->last_update_ts) * 1000.0f /(float) FS) /
+ (float)frame_length);
+
+ if(((float)bwest_str->num_pkts_rec/(float)num_pkts_expected) >
+ 0.9)
+ {
+ float inv_bitrate = (float) pow( 0.99995,
+ (double)((WebRtc_UWord32)(arr_ts -
+ bwest_str->last_reduction_ts)*1000.0f/FS) );
+
+ if ( inv_bitrate )
+ {
+ bwest_str->rec_bw_inv /= inv_bitrate;
+
+ //precautionary, likely never necessary
+ if (bwest_str->hsn_detect_snd &&
+ bwest_str->hsn_detect_rec)
+ {
+ if (bwest_str->rec_bw_inv > 0.000066f)
+ {
+ bwest_str->rec_bw_inv = 0.000066f;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ }
+ /* reset time-since-update counter */
+ bwest_str->last_reduction_ts = arr_ts;
+ }
+ else
+ //reset here?
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+
+
+ /* temporarily speed up adaptation if frame length has changed */
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->count_tot_updates_rec = 10;
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+
+ bwest_str->rec_bw_inv = 1.0f /((float)bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+ }
+
+ ////////////////////////
+ arr_ts_diff = (float)(arr_ts - bwest_str->prev_rec_arr_ts);
+
+ if (send_ts_diff > 0 )
+ {
+ late_diff = arr_ts_diff - send_ts_diff;
+ }
+ else
+ {
+ late_diff = arr_ts_diff - (float)(16 * frame_length);
+ }
+
+ if((late_diff > 0) && !bwest_str->inWaitLatePkts)
+ {
+ bwest_str->numConsecLatePkts++;
+ bwest_str->consecLatency += late_diff;
+ }
+ else
+ {
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ }
+ if(bwest_str->numConsecLatePkts > 50)
+ {
+ float latencyMs = bwest_str->consecLatency/(FS/1000);
+ float averageLatencyMs = latencyMs / bwest_str->numConsecLatePkts;
+ delay_correction_factor = frame_length / (frame_length + averageLatencyMs);
+ immediate_set = 1;
+ bwest_str->inWaitLatePkts = (WebRtc_Word16)((bwest_str->consecLatency/(FS/1000)) / 30);// + 150;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ ///////////////////////////////////////////////
+
+
+
+ /* update only if previous packet was not lost */
+ if ( rtp_number == bwest_str->prev_rec_rtp_number + 1 )
+ {
+
+
+ if (!(bwest_str->hsn_detect_snd && bwest_str->hsn_detect_rec))
+ {
+ if ((arr_ts_diff > (float)(16 * frame_length)))
+ {
+ //1/2 second
+ if ((late_diff > 8000.0f) && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.7f;
+ bwest_str->in_wait_period = 55;
+ bwest_str->start_wait_period = arr_ts;
+ immediate_set = 1;
+ }
+ //320 ms
+ else if (late_diff > 5120.0f && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.8f;
+ immediate_set = 1;
+ bwest_str->in_wait_period = 44;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ }
+ }
+
+
+ if ((bwest_str->prev_rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ (rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ !bwest_str->in_wait_period)
+ {
+ /* test if still in initiation period and increment counter */
+ if (bwest_str->count_tot_updates_rec++ > 99)
+ {
+ /* constant weight after initiation part */
+ weight = 0.01f;
+ }
+ else
+ {
+ /* weight decreases with number of updates */
+ weight = 1.0f / (float) bwest_str->count_tot_updates_rec;
+ }
+ /* Bottle Neck Estimation */
+
+ /* limit outliers */
+ /* if more than 25 ms too much */
+ if (arr_ts_diff > frame_length * FS/1000 + 400.0f)
+ {
+ // in samples, why 25ms??
+ arr_ts_diff = frame_length * FS/1000 + 400.0f;
+ }
+ if(arr_ts_diff < (frame_length * FS/1000) - 160.0f)
+ {
+ /* don't allow it to be less than frame rate - 10 ms */
+ arr_ts_diff = (float)frame_length * FS/1000 - 160.0f;
+ }
+
+ /* compute inverse receiving rate for last packet */
+ curr_bw_inv = arr_ts_diff / ((float)(pksize + HEADER_SIZE) *
+ 8.0f * FS); // (180+35)*8*16000 = 27.5 Mbit....
+
+
+ if(curr_bw_inv <
+ (1.0f / (MAX_ISAC_BW + bwest_str->rec_header_rate)))
+ {
+ // don't allow inv rate to be larger than MAX
+ curr_bw_inv = (1.0f /
+ (MAX_ISAC_BW + bwest_str->rec_header_rate));
+ }
+
+ /* update bottle neck rate estimate */
+ bwest_str->rec_bw_inv = weight * curr_bw_inv +
+ (1.0f - weight) * bwest_str->rec_bw_inv;
+
+ /* reset time-since-update counter */
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3 * FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* Jitter Estimation */
+ /* projected difference between arrival times */
+ t_diff_proj = ((float)(pksize + HEADER_SIZE) * 8.0f *
+ 1000.0f) / bwest_str->rec_bw_avg;
+
+
+ // difference between projected and actual
+ // arrival time differences
+ arr_time_noise = (float)(arr_ts_diff*1000.0f/FS) -
+ t_diff_proj;
+ arr_time_noise_abs = (float) fabs( arr_time_noise );
+
+ /* long term averaged absolute jitter */
+ bwest_str->rec_jitter = weight * arr_time_noise_abs +
+ (1.0f - weight) * bwest_str->rec_jitter;
+ if (bwest_str->rec_jitter > 10.0f)
+ {
+ bwest_str->rec_jitter = 10.0f;
+ }
+ /* short term averaged absolute jitter */
+ bwest_str->rec_jitter_short_term_abs = 0.05f *
+ arr_time_noise_abs + 0.95f *
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* short term averaged jitter */
+ bwest_str->rec_jitter_short_term = 0.05f * arr_time_noise +
+ 0.95f * bwest_str->rec_jitter_short_term;
+ }
+ }
+ }
+ else
+ {
+ // reset time-since-update counter when
+ // receiving the first 9 packets
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->count_tot_updates_rec++;
+ }
+
+ /* limit minimum bottle neck rate */
+ if (bwest_str->rec_bw_inv > 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ // limit maximum bitrate
+ if (bwest_str->rec_bw_inv < 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ // Replace bwest_str->rec_max_delay by the new
+ // value (atomic operation)
+ bwest_str->rec_max_delay = 3.0f * bwest_str->rec_jitter;
+
+ /* store send and arrival time stamp */
+ bwest_str->prev_rec_arr_ts = arr_ts ;
+ bwest_str->prev_rec_send_ts = send_ts;
+
+ /* Replace bwest_str->rec_bw by the new value (atomic operation) */
+ bwest_str->rec_bw = (WebRtc_Word32)(1.0f / bwest_str->rec_bw_inv -
+ bwest_str->rec_header_rate);
+
+ if (immediate_set)
+ {
+ bwest_str->rec_bw = (WebRtc_Word32) (delay_correction_factor *
+ (float) bwest_str->rec_bw);
+
+ if (bwest_str->rec_bw < (WebRtc_Word32) MIN_ISAC_BW)
+ {
+ bwest_str->rec_bw = (WebRtc_Word32) MIN_ISAC_BW;
+ }
+
+ bwest_str->rec_bw_avg = bwest_str->rec_bw +
+ bwest_str->rec_header_rate;
+
+ bwest_str->rec_bw_avg_Q = (float) bwest_str->rec_bw;
+
+ bwest_str->rec_jitter_short_term = 0.0f;
+
+ bwest_str->rec_bw_inv = 1.0f / (bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+
+ bwest_str->count_tot_updates_rec = 1;
+
+ immediate_set = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->numConsecLatePkts = 0;
+ }
+
+ return 0;
+}
+
+
+/* This function updates the send bottle neck rate */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+WebRtc_Word16 WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16 index,
+ enum IsacSamplingRate encoderSamplingFreq)
+{
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ if(encoderSamplingFreq == kIsacWideband)
+ {
+ if(index > 11)
+ {
+ index -= 12;
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableWb[index];
+ }
+ else
+ {
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableSwb[index];
+ }
+
+ if (bwest_str->send_bw_avg > (float) 28000 && !bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k++;
+
+ if (bwest_str->num_consec_snt_pkts_over_30k >= 66)
+ {
+ //approx 2 seconds with 30ms frames
+ bwest_str->hsn_detect_snd = 1;
+ }
+ }
+ else if (!bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+ }
+ return 0;
+}
+
+// called when there is upper-band bit-stream to update jitter
+// statistics.
+WebRtc_Word16 WebRtcIsac_UpdateUplinkJitter(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word32 index)
+{
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ if(index > 0)
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ return 0;
+}
+
+
+
+// Returns the bandwidth/jitter estimation code (integer 0...23)
+// to put in the sending iSAC payload
+WebRtc_UWord16
+WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16* bottleneckIndex,
+ WebRtc_Word16* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq)
+{
+ float MaxDelay;
+ //WebRtc_UWord16 MaxDelayBit;
+
+ float rate;
+ float r;
+ float e1, e2;
+ const float weight = 0.1f;
+ const float* ptrQuantizationTable;
+ WebRtc_Word16 addJitterInfo;
+ WebRtc_Word16 minInd;
+ WebRtc_Word16 maxInd;
+ WebRtc_Word16 midInd;
+
+ /* Get Max Delay Bit */
+ /* get unquantized max delay */
+ MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str);
+
+ if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) *
+ bwest_str->rec_max_delay_avg_Q - weight * MIN_ISAC_MD) )
+ {
+ jitterInfo[0] = 0;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MIN_ISAC_MD;
+ }
+ else
+ {
+ jitterInfo[0] = 1;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f-weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MAX_ISAC_MD;
+ }
+
+ // Get unquantized rate.
+ rate = (float)WebRtcIsac_GetDownlinkBandwidth(bwest_str);
+
+ /* Get Rate Index */
+ if(decoderSamplingFreq == kIsacWideband)
+ {
+ ptrQuantizationTable = kQRateTableWb;
+ addJitterInfo = 1;
+ maxInd = 11;
+ }
+ else
+ {
+ ptrQuantizationTable = kQRateTableSwb;
+ addJitterInfo = 0;
+ maxInd = 23;
+ }
+
+ minInd = 0;
+ while(maxInd > minInd + 1)
+ {
+ midInd = (maxInd + minInd) >> 1;
+ if(rate > ptrQuantizationTable[midInd])
+ {
+ minInd = midInd;
+ }
+ else
+ {
+ maxInd = midInd;
+ }
+ }
+ // Chose the index which gives results an average which is closest
+ // to rate
+ r = (1 - weight) * bwest_str->rec_bw_avg_Q - rate;
+ e1 = weight * ptrQuantizationTable[minInd] + r;
+ e2 = weight * ptrQuantizationTable[maxInd] + r;
+ e1 = (e1 > 0)? e1:-e1;
+ e2 = (e2 > 0)? e2:-e2;
+ if(e1 < e2)
+ {
+ bottleneckIndex[0] = minInd;
+ }
+ else
+ {
+ bottleneckIndex[0] = maxInd;
+ }
+
+ bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q +
+ weight * ptrQuantizationTable[bottleneckIndex[0]];
+ bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo;
+
+ bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight *
+ (rate + bwest_str->rec_header_rate);
+
+ return 0;
+}
+
+
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+WebRtc_Word32 WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 rec_bw;
+ float jitter_sign;
+ float bw_adjust;
+
+ /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */
+ jitter_sign = bwest_str->rec_jitter_short_term /
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* adjust bw proportionally to negative average jitter sign */
+ bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+
+ /* adjust Rate if jitter sign is mostly constant */
+ rec_bw = (WebRtc_Word32)(bwest_str->rec_bw * bw_adjust);
+
+ /* limit range of bottle neck rate */
+ if (rec_bw < MIN_ISAC_BW)
+ {
+ rec_bw = MIN_ISAC_BW;
+ }
+ else if (rec_bw > MAX_ISAC_BW)
+ {
+ rec_bw = MAX_ISAC_BW;
+ }
+ return rec_bw;
+}
+
+/* Returns the max delay (in ms) */
+WebRtc_Word32
+WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 rec_max_delay;
+
+ rec_max_delay = (WebRtc_Word32)(bwest_str->rec_max_delay);
+
+ /* limit range of jitter estimate */
+ if (rec_max_delay < MIN_ISAC_MD)
+ {
+ rec_max_delay = MIN_ISAC_MD;
+ }
+ else if (rec_max_delay > MAX_ISAC_MD)
+ {
+ rec_max_delay = MAX_ISAC_MD;
+ }
+ return rec_max_delay;
+}
+
+/* get the bottle neck rate from here to far side, as estimated by far side */
+void
+WebRtcIsac_GetUplinkBandwidth(
+ const BwEstimatorstr* bwest_str,
+ WebRtc_Word32* bitRate)
+{
+ /* limit range of bottle neck rate */
+ if (bwest_str->send_bw_avg < MIN_ISAC_BW)
+ {
+ *bitRate = MIN_ISAC_BW;
+ }
+ else if (bwest_str->send_bw_avg > MAX_ISAC_BW)
+ {
+ *bitRate = MAX_ISAC_BW;
+ }
+ else
+ {
+ *bitRate = (WebRtc_Word32)(bwest_str->send_bw_avg);
+ }
+ return;
+}
+
+/* Returns the max delay value from the other side in ms */
+WebRtc_Word32
+WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 send_max_delay;
+
+ send_max_delay = (WebRtc_Word32)(bwest_str->send_max_delay_avg);
+
+ /* limit range of jitter estimate */
+ if (send_max_delay < MIN_ISAC_MD)
+ {
+ send_max_delay = MIN_ISAC_MD;
+ }
+ else if (send_max_delay > MAX_ISAC_MD)
+ {
+ send_max_delay = MAX_ISAC_MD;
+ }
+ return send_max_delay;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,WebRtc_Word16 frequentLargePackets*/)
+{
+ double MinRate = 0.0;
+ int MinBytes;
+ double TransmissionTime;
+ int burstInterval = BURST_INTERVAL;
+
+ // first 10 packets @ low rate, then INIT_BURST_LEN packets @
+ // fixed rate of INIT_RATE bps
+ if (State->InitCounter > 0)
+ {
+ if (State->InitCounter-- <= INIT_BURST_LEN)
+ {
+ if(bandwidth == isac8kHz)
+ {
+ MinRate = INIT_RATE_WB;
+ }
+ else
+ {
+ MinRate = INIT_RATE_SWB;
+ }
+ }
+ else
+ {
+ MinRate = 0;
+ }
+ }
+ else
+ {
+ /* handle burst */
+ if (State->BurstCounter)
+ {
+ if (State->StillBuffered < (1.0 - 1.0/BURST_LEN) * DelayBuildUp)
+ {
+ /* max bps derived from BottleNeck and DelayBuildUp values */
+ MinRate = (1.0 + (FS/1000) * DelayBuildUp /
+ (double)(BURST_LEN * FrameSamples)) * BottleNeck;
+ }
+ else
+ {
+ // max bps derived from StillBuffered and DelayBuildUp
+ // values
+ MinRate = (1.0 + (FS/1000) * (DelayBuildUp -
+ State->StillBuffered) / (double)FrameSamples) * BottleNeck;
+ if (MinRate < 1.04 * BottleNeck)
+ {
+ MinRate = 1.04 * BottleNeck;
+ }
+ }
+ State->BurstCounter--;
+ }
+ }
+
+
+ /* convert rate from bits/second to bytes/packet */
+ MinBytes = (int) (MinRate * FrameSamples / (8.0 * FS));
+
+ /* StreamSize will be adjusted if less than MinBytes */
+ if (StreamSize < MinBytes)
+ {
+ StreamSize = MinBytes;
+ }
+
+ /* keep track of when bottle neck was last exceeded by at least 1% */
+ if (StreamSize * 8.0 * FS / FrameSamples > 1.01 * BottleNeck) {
+ if (State->PrevExceed) {
+ /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+ State->ExceedAgo -= /*BURST_INTERVAL*/ burstInterval / (BURST_LEN - 1);
+ if (State->ExceedAgo < 0)
+ State->ExceedAgo = 0;
+ }
+ else
+ {
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ State->PrevExceed = 1;
+ }
+ }
+ else
+ {
+ State->PrevExceed = 0;
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ }
+
+ /* set burst flag if bottle neck not exceeded for long time */
+ if ((State->ExceedAgo > burstInterval) &&
+ (State->BurstCounter == 0))
+ {
+ if (State->PrevExceed)
+ {
+ State->BurstCounter = BURST_LEN - 1;
+ }
+ else
+ {
+ State->BurstCounter = BURST_LEN;
+ }
+ }
+
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ {
+ State->StillBuffered = 0.0;
+ }
+
+ return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+ RateModel *State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck) /* bottle neck rate; excl headers (bps) */
+{
+ double TransmissionTime;
+
+ /* avoid the initial "high-rate" burst */
+ State->InitCounter = 0;
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ State->StillBuffered = 0.0;
+
+}
+
+
+void WebRtcIsac_InitRateModel(
+ RateModel *State)
+{
+ State->PrevExceed = 0; /* boolean */
+ State->ExceedAgo = 0; /* ms */
+ State->BurstCounter = 0; /* packets */
+ State->InitCounter = INIT_BURST_LEN + 10; /* packets */
+ State->StillBuffered = 1.0; /* ms */
+}
+
+int WebRtcIsac_GetNewFrameLength(
+ double bottle_neck,
+ int current_framesamples)
+{
+ int new_framesamples;
+
+ const int Thld_20_30 = 20000;
+
+ //const int Thld_30_20 = 30000;
+ const int Thld_30_20 = 1000000; // disable 20 ms frames
+
+ const int Thld_30_60 = 18000;
+ //const int Thld_30_60 = 0; // disable 60 ms frames
+
+ const int Thld_60_30 = 27000;
+
+
+ new_framesamples = current_framesamples;
+
+ /* find new framelength */
+ switch(current_framesamples) {
+ case 320:
+ if (bottle_neck < Thld_20_30)
+ new_framesamples = 480;
+ break;
+ case 480:
+ if (bottle_neck < Thld_30_60)
+ new_framesamples = 960;
+ else if (bottle_neck > Thld_30_20)
+ new_framesamples = 320;
+ break;
+ case 960:
+ if (bottle_neck >= Thld_60_30)
+ new_framesamples = 480;
+ break;
+ }
+
+ return new_framesamples;
+}
+
+double WebRtcIsac_GetSnr(
+ double bottle_neck,
+ int framesamples)
+{
+ double s2nr;
+
+ const double a_20 = -30.0;
+ const double b_20 = 0.8;
+ const double c_20 = 0.0;
+
+ const double a_30 = -23.0;
+ const double b_30 = 0.48;
+ const double c_30 = 0.0;
+
+ const double a_60 = -23.0;
+ const double b_60 = 0.53;
+ const double c_60 = 0.0;
+
+
+ /* find new SNR value */
+ switch(framesamples) {
+ case 320:
+ s2nr = a_20 + b_20 * bottle_neck * 0.001 + c_20 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 480:
+ s2nr = a_30 + b_30 * bottle_neck * 0.001 + c_30 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 960:
+ s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ default:
+ s2nr = 0;
+ }
+
+ return s2nr;
+
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h b/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
new file mode 100644
index 0000000..5604d7b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include "structs.h"
+#include "settings.h"
+
+
+#define MIN_ISAC_BW 10000
+#define MIN_ISAC_BW_LB 10000
+#define MIN_ISAC_BW_UB 25000
+
+#define MAX_ISAC_BW 56000
+#define MAX_ISAC_BW_UB 32000
+#define MAX_ISAC_BW_LB 32000
+
+#define MIN_ISAC_MD 5
+#define MAX_ISAC_MD 25
+
+// assumed header size, in bytes; we don't know the exact number
+// (header compression may be used)
+#define HEADER_SIZE 35
+
+// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
+#define INIT_FRAME_LEN_WB 60
+#define INIT_FRAME_LEN_SWB 30
+
+// Initial Bottleneck Estimate, in bits/sec, for
+// Wideband & Super-wideband mode
+#define INIT_BN_EST_WB 20e3f
+#define INIT_BN_EST_SWB 56e3f
+
+// Initial Header rate (header rate depends on frame-size),
+// in bits/sec, for Wideband & Super-Wideband mode.
+#define INIT_HDR_RATE_WB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
+#define INIT_HDR_RATE_SWB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
+
+// number of packets in a row for a high rate burst
+#define BURST_LEN 3
+
+// ms, max time between two full bursts
+#define BURST_INTERVAL 500
+
+// number of packets in a row for initial high rate burst
+#define INIT_BURST_LEN 5
+
+// bits/s, rate for the first BURST_LEN packets
+#define INIT_RATE_WB INIT_BN_EST_WB
+#define INIT_RATE_SWB INIT_BN_EST_SWB
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ /* This function initializes the struct */
+ /* to be called before using the struct for anything else */
+ /* returns 0 if everything went fine, -1 otherwise */
+ WebRtc_Word32 WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+ /* This function updates the receiving estimate */
+ /* Parameters: */
+ /* rtp_number - value from RTP packet, from NetEq */
+ /* frame length - length of signal frame in ms, from iSAC decoder */
+ /* send_ts - value in RTP header giving send time in samples */
+ /* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
+ /* pksize - size of packet in bytes, from NetEq */
+ /* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+ /* returns 0 if everything went fine, -1 otherwise */
+ WebRtc_Word16 WebRtcIsac_UpdateBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ const WebRtc_UWord16 rtp_number,
+ const WebRtc_Word32 frame_length,
+ const WebRtc_UWord32 send_ts,
+ const WebRtc_UWord32 arr_ts,
+ const WebRtc_Word32 pksize);
+
+ /* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16 Index,
+ enum IsacSamplingRate encoderSamplingFreq);
+
+ /* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the sending iSAC payload */
+ WebRtc_UWord16 WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16* bottleneckIndex,
+ WebRtc_Word16* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq);
+
+ /* Returns the bandwidth estimation (in bps) */
+ WebRtc_Word32 WebRtcIsac_GetDownlinkBandwidth(
+ const BwEstimatorstr *bwest_str);
+
+ /* Returns the max delay (in ms) */
+ WebRtc_Word32 WebRtcIsac_GetDownlinkMaxDelay(
+ const BwEstimatorstr *bwest_str);
+
+ /* Returns the bandwidth that iSAC should send with in bps */
+ void WebRtcIsac_GetUplinkBandwidth(
+ const BwEstimatorstr* bwest_str,
+ WebRtc_Word32* bitRate);
+
+ /* Returns the max delay value from the other side in ms */
+ WebRtc_Word32 WebRtcIsac_GetUplinkMaxDelay(
+ const BwEstimatorstr *bwest_str);
+
+
+ /*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+ int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameLen, /* ms per frame */
+ const double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,WebRtc_Word16 frequentLargePackets*/);
+
+ /*
+ * update long-term average bitrate and amount of data in buffer
+ */
+ void WebRtcIsac_UpdateRateModel(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+
+ void WebRtcIsac_InitRateModel(
+ RateModel *State);
+
+ /* Returns the new framelength value (input argument: bottle_neck) */
+ int WebRtcIsac_GetNewFrameLength(
+ double bottle_neck,
+ int current_framelength);
+
+ /* Returns the new SNR value (input argument: bottle_neck) */
+ double WebRtcIsac_GetSnr(
+ double bottle_neck,
+ int new_framelength);
+
+
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkJitter(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word32 index);
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/codec.h b/src/modules/audio_coding/codecs/isac/main/source/codec.h
new file mode 100644
index 0000000..0b4d862
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/codec.h
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+
+#include "structs.h"
+
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream);
+
+int WebRtcIsac_EstimateBandwidth(BwEstimatorstr* bwest_str, Bitstr* streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts, WebRtc_UWord32 arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdec_obj,
+ WebRtc_Word16* current_framesamples,
+ WebRtc_Word16 isRCUPayload);
+
+int WebRtcIsac_DecodeRcuLb(float* signal_out, ISACLBDecStruct* ISACdec_obj,
+ WebRtc_Word16* current_framesamples);
+
+int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj,
+ WebRtc_Word16 codingMode, WebRtc_Word16
+ bottleneckIndex);
+
+int WebRtcIsac_EncodeStoredDataLb(const ISAC_SaveEncData_t* ISACSavedEnc_obj,
+ Bitstr* ISACBitStr_obj, int BWnumber,
+ float scale);
+
+int WebRtcIsac_EncodeStoredDataUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj, Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo, float scale, enum ISACBandwidth bandwidth);
+
+WebRtc_Word16 WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj, Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bit-rate in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bit-rate allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bit-rate allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+WebRtc_Word16 WebRtcIsac_RateAllocation(WebRtc_Word32 inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb16()
+ *
+ * Decode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdec_obj,
+ WebRtc_Word16 isRCUPayload);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb12()
+ *
+ * Decode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdec_obj,
+ WebRtc_Word16 isRCUPayload);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb16()
+ *
+ * Encode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACenc_obj,
+ WebRtc_Word32 jitterInfo);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb12()
+ *
+ * Encode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACenc_obj,
+ WebRtc_Word32 jitterInfo);
+
+/************************** initialization functions *************************/
+
+void WebRtcIsac_InitMasking(MaskFiltstr* maskdata);
+
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr* prefiltdata);
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr* postfiltdata);
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr* pitchfiltdata);
+
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* State);
+
+
+/**************************** transform functions ****************************/
+
+void WebRtcIsac_InitTransform();
+
+void WebRtcIsac_Time2Spec(double* inre1, double* inre2, WebRtc_Word16* outre,
+ WebRtc_Word16* outim, FFTstr* fftstr_obj);
+
+void WebRtcIsac_Spec2time(double* inre, double* inim, double* outre1,
+ double* outre2, FFTstr* fftstr_obj);
+
+
+/******************************* filter functions ****************************/
+
+void WebRtcIsac_AllPoleFilter(double* InOut, double* Coef, int lengthInOut,
+ int orderCoef);
+
+void WebRtcIsac_AllZeroFilter(double* In, double* Coef, int lengthInOut,
+ int orderCoef, double* Out);
+
+void WebRtcIsac_ZeroPoleFilter(double* In, double* ZeroCoef, double* PoleCoef,
+ int lengthInOut, int orderCoef, double* Out);
+
+
+/***************************** filterbank functions **************************/
+
+void WebRtcIsac_SplitAndFilterFloat(float* in, float* LP, float* HP,
+ double* LP_la, double* HP_la,
+ PreFiltBankstr* prefiltdata);
+
+
+void WebRtcIsac_FilterAndCombineFloat(float* InLP, float* InHP, float* Out,
+ PostFiltBankstr* postfiltdata);
+
+
+/************************* normalized lattice filters ************************/
+
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef, float* stateF, float* stateG,
+ float* lat_in, double* filtcoeflo,
+ double* lat_out);
+
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef, float* stateF, float* stateG,
+ double* lat_in, double* lo_filt_coef,
+ float* lat_out);
+
+void WebRtcIsac_Dir2Lat(double* a, int orderCoef, float* sth, float* cth);
+
+void WebRtcIsac_AutoCorr(double* r, const double* x, int N, int order);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/crc.c b/src/modules/audio_coding/codecs/isac/main/source/crc.c
new file mode 100644
index 0000000..098e4b7
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/crc.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "crc.h"
+#include <stdlib.h>
+#include "signal_processing_library.h"
+
+#define POLYNOMIAL 0x04c11db7L
+
+
+static const WebRtc_UWord32 kCrcTable[256] = {
+ 0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4,
+ 0x808d07d, 0xcc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - bitstream : payload bitstream
+ * - len_bitstream_in_bytes : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsac_GetCrc(const WebRtc_Word16* bitstream,
+ WebRtc_Word16 len_bitstream_in_bytes,
+ WebRtc_UWord32* crc)
+{
+ WebRtc_UWord8* bitstream_ptr_uw8;
+ WebRtc_UWord32 crc_state;
+ int byte_cntr;
+ int crc_tbl_indx;
+
+ /* Sanity Check. */
+ if (bitstream == NULL) {
+ return -1;
+ }
+ /* cast to UWord8 pointer */
+ bitstream_ptr_uw8 = (WebRtc_UWord8 *)bitstream;
+
+ /* initialize */
+ crc_state = 0xFFFFFFFF;
+
+ for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
+ crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
+ bitstream_ptr_uw8[byte_cntr]) & 0xFF;
+ crc_state = WEBRTC_SPL_LSHIFT_U32(crc_state, 8) ^ kCrcTable[crc_tbl_indx];
+ }
+
+ *crc = ~crc_state;
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/crc.h b/src/modules/audio_coding/codecs/isac/main/source/crc.h
new file mode 100644
index 0000000..0151278
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/crc.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * crc.h
+ *
+ * Checksum functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+
+#include "typedefs.h"
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - encoded : payload bit stream
+ * - no_of_word8s : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsac_GetCrc(
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16 no_of_word8s,
+ WebRtc_UWord32* crc);
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/decode.c b/src/modules/audio_coding/codecs/isac/main/source/decode.c
new file mode 100644
index 0000000..2b06cd0
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/decode.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_B.c
+ *
+ * This file contains definition of funtions for decoding.
+ * Decoding of lower-band, including normal-decoding and RCU decoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+
+#include "codec.h"
+#include "entropy_coding.h"
+#include "pitch_estimator.h"
+#include "bandwidth_estimator.h"
+#include "structs.h"
+#include "settings.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdecLB_obj,
+ WebRtc_Word16* current_framesamples,
+ WebRtc_Word16 isRCUPayload) {
+ int k;
+ int len, err;
+ WebRtc_Word16 bandwidthInd;
+
+ float LP_dec_float[FRAMESAMPLES_HALF];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+
+ double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES];
+ double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+
+ double PitchLags[4];
+ double PitchGains[4];
+ double AvgPitchGain;
+ WebRtc_Word16 PitchGains_Q12[4];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ float gain;
+
+ int frame_nb; /* counter */
+ int frame_mode; /* 0 30ms, 1 for 60ms */
+ /* Processed_samples: 480 (30, 60 ms). Cannot take other values. */
+
+ WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj));
+
+ len = 0;
+
+ /* Decode framelength and BW estimation - not used,
+ only for stream pointer*/
+ err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
+ current_framesamples);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Frame_mode:
+ * 0: indicates 30 ms frame (480 samples)
+ * 1: indicates 60 ms frame (960 samples) */
+ frame_mode = *current_framesamples / MAX_FRAMESAMPLES;
+
+ err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
+ if (err < 0) {
+ return err;
+ }
+
+ /* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames
+ bundled together (60ms). */
+ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+ /* Decode & de-quantize pitch parameters */
+ err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj,
+ PitchGains_Q12);
+ if (err < 0) {
+ return err;
+ }
+
+ err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12,
+ PitchLags);
+ if (err < 0) {
+ return err;
+ }
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+ /* Decode & de-quantize filter coefficients. */
+ err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef,
+ hi_filt_coef);
+ if (err < 0) {
+ return err;
+ }
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12,
+ kIsacLowerBand, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+
+ /* Inverse transform. */
+ WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw,
+ &ISACdecLB_obj->fftstr_obj);
+
+ /* Convert PitchGains back to float for pitchfilter_post */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ }
+ if (isRCUPayload) {
+ for (k = 0; k < 240; k++) {
+ LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ }
+ }
+
+ /* Inverse pitch filter. */
+ WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj,
+ PitchLags, PitchGains);
+ /* Convert AvgPitchGain back to float for computation of gain. */
+ AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096;
+ gain = 1.0f - 0.45f * (float)AvgPitchGain;
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* Reduce gain to compensate for pitch enhancer. */
+ LPw_pf[k] *= gain;
+ }
+
+ if (isRCUPayload) {
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* Compensation for transcoding gain changes. */
+ LPw_pf[k] *= RCU_TRANSCODING_SCALE;
+ HPw[k] *= RCU_TRANSCODING_SCALE;
+ }
+ }
+ /* Perceptual post-filtering (using normalized lattice filter). */
+ WebRtcIsac_NormLatticeFilterAr(
+ ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef,
+ LP_dec_float);
+ WebRtcIsac_NormLatticeFilterAr(
+ ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef,
+ HP_dec_float);
+
+ /* Recombine the 2 bands. */
+ WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float,
+ signal_out + frame_nb * FRAMESAMPLES,
+ &ISACdecLB_obj->postfiltbankstr_obj);
+ }
+ return len;
+}
+
+
+/*
+ * This decode function is called when the codec is operating in 16 kHz
+ * bandwidth to decode the upperband, i.e. 8-16 kHz.
+ *
+ * Contrary to lower-band, the upper-band (8-16 kHz) is not split in
+ * frequency, but split to 12 sub-frames, i.e. twice as lower-band.
+ */
+int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
+ WebRtc_Word16 isRCUPayload) {
+ int len, err;
+
+ double halfFrameFirst[FRAMESAMPLES_HALF];
+ double halfFrameSecond[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) +
+ (UB_LPC_ORDER + 1)];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+ const WebRtc_Word16 kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+ len = 0;
+
+ /* Decode & de-quantize filter coefficients. */
+ memset(percepFilterParam, 0, sizeof(percepFilterParam));
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac16kHz);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+ kIsacUpperBand16, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+ if (isRCUPayload) {
+ int n;
+ for (n = 0; n < 240; n++) {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+ /* Inverse transform. */
+ WebRtcIsac_Spec2time(real_f, imag_f, halfFrameFirst, halfFrameSecond,
+ &ISACdecUB_obj->fftstr_obj);
+
+ /* Perceptual post-filtering (using normalized lattice filter). */
+ WebRtcIsac_NormLatticeFilterAr(
+ UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
+ &percepFilterParam[(UB_LPC_ORDER + 1)], signal_out);
+
+ WebRtcIsac_NormLatticeFilterAr(
+ UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
+ &percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)],
+ &signal_out[FRAMESAMPLES_HALF]);
+
+ return len;
+}
+
+/*
+ * This decode function is called when the codec operates at 0-12 kHz
+ * bandwidth to decode the upperband, i.e. 8-12 kHz.
+ *
+ * At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
+ * kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
+ * reconstructed and 12-16 kHz replaced with zeros. Then two bands
+ * are combined, to reconstruct the upperband 8-16 kHz.
+ */
+int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
+ WebRtc_Word16 isRCUPayload) {
+ int len, err;
+
+ float LP_dec_float[FRAMESAMPLES_HALF];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+ const WebRtc_Word16 kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+ len = 0;
+
+ /* Decode & dequantize filter coefficients. */
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac12kHz);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+ kIsacUpperBand12, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+
+ if (isRCUPayload) {
+ int n;
+ for (n = 0; n < 240; n++) {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+ /* Inverse transform. */
+ WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj);
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
+ ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG,
+ LPw, percepFilterParam, LP_dec_float);
+ /* Zero for 12-16 kHz. */
+ memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
+ /* Recombine the 2 bands. */
+ WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
+ &ISACdecUB_obj->postfiltbankstr_obj);
+ return len;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/decode_bwe.c b/src/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
new file mode 100644
index 0000000..cdac7fa
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "structs.h"
+#include "bandwidth_estimator.h"
+#include "entropy_coding.h"
+#include "codec.h"
+
+
+int
+WebRtcIsac_EstimateBandwidth(
+ BwEstimatorstr* bwest_str,
+ Bitstr* streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ WebRtc_Word16 index;
+ WebRtc_Word16 frame_samples;
+ WebRtc_UWord32 sendTimestampIn16kHz;
+ WebRtc_UWord32 arrivalTimestampIn16kHz;
+ WebRtc_UWord32 diffSendTime;
+ WebRtc_UWord32 diffArrivalTime;
+ int err;
+
+ /* decode framelength and BW estimation */
+ err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+ err = WebRtcIsac_DecodeSendBW(streamdata, &index);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ // We like BWE to work at 16 kHz sampling rate,
+ // therefore, we have to change the timestamps accordingly.
+ // translate the send timestamp if required
+ diffSendTime = (WebRtc_UWord32)((WebRtc_UWord32)send_ts -
+ (WebRtc_UWord32)bwest_str->senderTimestamp);
+ bwest_str->senderTimestamp = send_ts;
+
+ diffArrivalTime = (WebRtc_UWord32)((WebRtc_UWord32)arr_ts -
+ (WebRtc_UWord32)bwest_str->receiverTimestamp);
+ bwest_str->receiverTimestamp = arr_ts;
+
+ if(decoderSampRate == kIsacSuperWideband)
+ {
+ diffArrivalTime = (WebRtc_UWord32)diffArrivalTime >> 1;
+ diffSendTime = (WebRtc_UWord32)diffSendTime >> 1;
+ }
+ // arrival timestamp in 16 kHz
+ arrivalTimestampIn16kHz = (WebRtc_UWord32)((WebRtc_UWord32)
+ bwest_str->prev_rec_arr_ts + (WebRtc_UWord32)diffArrivalTime);
+ // send timestamp in 16 kHz
+ sendTimestampIn16kHz = (WebRtc_UWord32)((WebRtc_UWord32)
+ bwest_str->prev_rec_send_ts + (WebRtc_UWord32)diffSendTime);
+
+ err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
+ (frame_samples * 1000) / FS, sendTimestampIn16kHz,
+ arrivalTimestampIn16kHz, packet_size);
+ // error check
+ if(err < 0)
+ {
+ return err;
+ }
+
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/encode.c b/src/modules/audio_coding/codecs/isac/main/source/encode.c
new file mode 100644
index 0000000..f6bdc17
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/encode.c
@@ -0,0 +1,1252 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * This file contains definition of funtions for encoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "structs.h"
+#include "codec.h"
+#include "pitch_estimator.h"
+#include "entropy_coding.h"
+#include "arith_routines.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "spectrum_ar_model_tables.h"
+#include "lpc_tables.h"
+#include "lpc_analysis.h"
+#include "bandwidth_estimator.h"
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+
+
+#define UB_LOOKAHEAD 24
+
+
+/*
+ Rate allocation tables of lower and upper-band bottleneck for
+ 12kHz & 16kHz bandwidth.
+
+ 12 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 38,
+ 39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
+ and the upper-band bottlenecks are specified in
+ 'kLowerBandBitRate12' and 'kUpperBandBitRate12'
+ tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
+ bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
+ overall bottleneck of the codec, we use linear interpolation to get
+ lower-band and upper-band bottlenecks.
+
+ 16 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
+ 52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
+ bottlenecks are specified in 'kLowerBandBitRate16' and
+ 'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
+ of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
+ kbps for upper-band. Given an overall bottleneck of the codec, we use linear
+ interpolation to get lower-band and upper-band bottlenecks.
+
+ */
+
+/* 38 39.17 40.33 41.5 42.67 43.83 45 */
+static const WebRtc_Word16 kLowerBandBitRate12[7] = {
+ 29000, 30000, 30000, 31000, 31000, 32000, 32000 };
+static const WebRtc_Word16 kUpperBandBitRate12[7] = {
+ 25000, 25000, 27000, 27000, 29000, 29000, 32000 };
+
+/* 50 51.2 52.4 53.6 54.8 56 */
+static const WebRtc_Word16 kLowerBandBitRate16[6] = {
+ 31000, 31000, 32000, 32000, 32000, 32000 };
+static const WebRtc_Word16 kUpperBandBitRate16[6] = {
+ 28000, 29000, 29000, 30000, 31000, 32000 };
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bottleneck in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bottleneck allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bottleneck allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+WebRtc_Word16 WebRtcIsac_RateAllocation(WebRtc_Word32 inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz) {
+ WebRtc_Word16 idx;
+ double idxD;
+ double idxErr;
+ if (inRateBitPerSec < 38000) {
+ /* If the given overall bottleneck is less than 38000 then
+ * then codec has to operate in wideband mode, i.e. 8 kHz
+ * bandwidth. */
+ *rateLBBitPerSec = (WebRtc_Word16)((inRateBitPerSec > 32000) ?
+ 32000 : inRateBitPerSec);
+ *rateUBBitPerSec = 0;
+ *bandwidthKHz = isac8kHz;
+ } else if ((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000)) {
+ /* At a bottleneck between 38 and 50 kbps the codec is operating
+ * at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
+ * upper/lower bottleneck */
+
+ /* Find the bottlenecks by linear interpolation,
+ * step is (45000 - 38000)/6.0 we use the inverse of it. */
+ const double stepSizeInv = 8.5714286e-4;
+ idxD = (inRateBitPerSec - 38000) * stepSizeInv;
+ idx = (idxD >= 6) ? 6 : ((WebRtc_Word16)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate12[idx];
+ *rateUBBitPerSec = kUpperBandBitRate12[idx];
+
+ if (idx < 6) {
+ *rateLBBitPerSec += (WebRtc_Word16)(
+ idxErr * (kLowerBandBitRate12[idx + 1] - kLowerBandBitRate12[idx]));
+ *rateUBBitPerSec += (WebRtc_Word16)(
+ idxErr * (kUpperBandBitRate12[idx + 1] - kUpperBandBitRate12[idx]));
+ }
+ *bandwidthKHz = isac12kHz;
+ } else if ((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000)) {
+ /* A bottleneck between 50 and 56 kbps corresponds to bandwidth
+ * of 16 kHz. Using xxxBandBitRate16[] to calculates
+ * upper/lower bottleneck. */
+
+ /* Find the bottlenecks by linear interpolation
+ * step is (56000 - 50000)/5 we use the inverse of it. */
+ const double stepSizeInv = 8.3333333e-4;
+ idxD = (inRateBitPerSec - 50000) * stepSizeInv;
+ idx = (idxD >= 5) ? 5 : ((WebRtc_Word16)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate16[idx];
+ *rateUBBitPerSec = kUpperBandBitRate16[idx];
+
+ if (idx < 5) {
+ *rateLBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kLowerBandBitRate16[idx + 1] -
+ kLowerBandBitRate16[idx]));
+
+ *rateUBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kUpperBandBitRate16[idx + 1] -
+ kUpperBandBitRate16[idx]));
+ }
+ *bandwidthKHz = isac16kHz;
+ } else {
+ /* Out-of-range botlteneck value. */
+ return -1;
+ }
+
+ /* limit the values. */
+ *rateLBBitPerSec = (*rateLBBitPerSec > 32000) ? 32000 : *rateLBBitPerSec;
+ *rateUBBitPerSec = (*rateUBBitPerSec > 32000) ? 32000 : *rateUBBitPerSec;
+ return 0;
+}
+
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream) {
+ bit_stream->W_upper = 0xFFFFFFFF;
+ bit_stream->stream_index = 0;
+ bit_stream->streamval = 0;
+}
+
+int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj,
+ WebRtc_Word16 codingMode,
+ WebRtc_Word16 bottleneckIndex) {
+ int stream_length = 0;
+ int err;
+ int k;
+ int iterCntr;
+
+ double lofilt_coef[(ORDERLO + 1)*SUBFRAMES];
+ double hifilt_coef[(ORDERHI + 1)*SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ double PitchLags[4];
+ double PitchGains[4];
+ WebRtc_Word16 PitchGains_Q12[4];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ int frame_mode; /* 0 for 30ms, 1 for 60ms */
+ int status = 0;
+ int my_index;
+ transcode_obj transcodingParam;
+ double bytesLeftSpecCoding;
+ WebRtc_UWord16 payloadLimitBytes;
+
+ /* Copy new frame-length and bottleneck rate only for the first 10 ms data */
+ if (ISACencLB_obj->buffer_index == 0) {
+ /* Set the framelength for the next packet. */
+ ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength;
+ }
+ /* 'frame_mode' is 0 (30 ms) or 1 (60 ms). */
+ frame_mode = ISACencLB_obj->current_framesamples / MAX_FRAMESAMPLES;
+
+ /* buffer speech samples (by 10ms packet) until the frame-length */
+ /* is reached (30 or 60 ms). */
+ /*****************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] = in[k];
+ }
+
+ /* If buffersize is not equal to current framesize then increase index
+ * and return. We do no encoding untill we have enough audio. */
+ if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != FRAMESAMPLES) {
+ ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* If buffer reached the right size, reset index and continue with
+ * encoding the frame. */
+ ISACencLB_obj->buffer_index = 0;
+
+ /* End of buffer function. */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+ /* This is to avoid Linux warnings until we change 'int' to 'Word32'
+ * at all places. */
+ int intVar;
+ /* reset bitstream */
+ WebRtcIsac_ResetBitstream(&(ISACencLB_obj->bitstr_obj));
+
+ if ((codingMode == 0) && (frame_mode == 0) &&
+ (ISACencLB_obj->enforceFrameSize == 0)) {
+ ISACencLB_obj->new_framelength = WebRtcIsac_GetNewFrameLength(
+ ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+ }
+
+ ISACencLB_obj->s2nr = WebRtcIsac_GetSnr(
+ ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+
+ /* Encode frame length. */
+ status = WebRtcIsac_EncodeFrameLen(
+ ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj);
+ if (status < 0) {
+ /* Wrong frame size. */
+ return status;
+ }
+ /* Save framelength for multiple packets memory. */
+ ISACencLB_obj->SaveEnc_obj.framelength =
+ ISACencLB_obj->current_framesamples;
+
+ /* To be used for Redundant Coding. */
+ ISACencLB_obj->lastBWIdx = bottleneckIndex;
+ intVar = (int)bottleneckIndex;
+ WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj);
+ }
+
+ /* Split signal in two bands. */
+ WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP,
+ LP_lookahead, HP_lookahead,
+ &ISACencLB_obj->prefiltbankstr_obj);
+
+ /* estimate pitch parameters and pitch-filter lookahead signal */
+ WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf,
+ &ISACencLB_obj->pitchanalysisstr_obj, PitchLags,
+ PitchGains);
+
+ /* Encode in FIX Q12. */
+
+ /* Convert PitchGain to Fixed point. */
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchGains_Q12[k] = (WebRtc_Word16)(PitchGains[k] * 4096.0);
+ }
+
+ /* Set where to store data in multiple packets memory. */
+ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 0;
+ } else {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 1;
+ }
+
+ /* Quantize & encode pitch parameters. */
+ WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+ WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead,
+ &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr,
+ PitchGains_Q12, lofilt_coef, hifilt_coef);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Convert PitchGains back to FLOAT for pitchfilter_pre. */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ }
+
+ /* Store the state of arithmetic coder before coding LPC gains. */
+ transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper;
+ transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index;
+ transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+ transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+ }
+
+ /* Code gains */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Get the correct value for the payload limit and calculate the
+ * number of bytes left for coding the spectrum. */
+ if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* It is a 60ms and we are in the first 30ms then the limit at
+ * this point should be half of the assigned value. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1;
+ } else if (frame_mode == 0) {
+ /* It is a 30ms frame */
+ /* Subract 3 because termination process may add 3 bytes. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
+ } else {
+ /* This is the second half of a 60ms frame. */
+ /* Subract 3 because termination process may add 3 bytes. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
+ }
+ bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+ /* Perceptual pre-filtering (using normalized lattice filter). */
+ /* Low-band filtering. */
+ WebRtcIsac_NormLatticeFilterMa(ORDERLO,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoG,
+ LP, lofilt_coef, LPw);
+ /* High-band filtering. */
+ WebRtcIsac_NormLatticeFilterMa(ORDERHI,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiG,
+ HP, hifilt_coef, HPw);
+ /* Pitch filter. */
+ WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
+ PitchLags, PitchGains);
+ /* Transform */
+ WebRtcIsac_Time2Spec(LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj);
+
+ /* Save data for multiple packets memory. */
+ my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+ ISACencLB_obj->SaveEnc_obj.AvgPitchGain[ISACencLB_obj->SaveEnc_obj.startIdx] =
+ AvgPitchGain_Q12;
+
+ /* Quantization and loss-less coding. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+ &ISACencLB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload). */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30ms of a 60ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr = 0;
+ while ((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size */
+ if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* This was the first 30ms of a 60ms frame. Although
+ the payload is larger than it should be but we let
+ the second 30ms be encoded. Maybe together we
+ won't exceed the limit. */
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ } else if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ if (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ } else {
+ return status;
+ }
+ }
+
+ if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ /* Being conservative */
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
+ transcodingParam.stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on
+ the number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ lofilt_coef[(LPC_LOBAND_ORDER + 1) * k] =
+ transcodingParam.loFiltGain[k] * transcodeScale;
+ hifilt_coef[(LPC_HIBAND_ORDER + 1) * k] =
+ transcodingParam.hiFiltGain[k] * transcodeScale;
+ transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+ transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+ }
+
+ /* Scale DFT coefficients. */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (WebRtc_Word16)(fre[k] * transcodeScale);
+ fim[k] = (WebRtc_Word16)(fim[k] * transcodeScale);
+ }
+
+ /* Save data for multiple packets memory. */
+ my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+ /* Re-store the state of arithmetic coder before coding LPC gains. */
+ ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+ ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+ ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+ transcodingParam.stream[0];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+ transcodingParam.stream[1];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+ transcodingParam.stream[2];
+
+ /* Code gains. */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Update the number of bytes left for encoding the spectrum. */
+ bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+ /* Encode the spectrum. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+ &ISACencLB_obj->bitstr_obj);
+
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload). */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30 ms of a 60 ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr++;
+ }
+
+ /* If 60 ms frame-size and just processed the first 30 ms, */
+ /* go back to main function to buffer the other 30 ms speech frame. */
+ if (frame_mode == 1) {
+ if (ISACencLB_obj->frame_nb == 0) {
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ } else if (ISACencLB_obj->frame_nb == 1) {
+ ISACencLB_obj->frame_nb = 0;
+ /* Also update the frame-length for next packet,
+ in Adaptive mode only. */
+ if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0)) {
+ ISACencLB_obj->new_framelength =
+ WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
+ ISACencLB_obj->current_framesamples);
+ }
+ }
+ } else {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ /* Complete arithmetic coding. */
+ stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
+ return stream_length;
+}
+
+
+
+static int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj,
+ WebRtc_UWord16 payloadLimitBytes,
+ double bytesLeftSpecCoding,
+ transcode_obj* transcodingParam,
+ WebRtc_Word16* fre, WebRtc_Word16* fim,
+ double* lpcGains, enum ISACBand band, int status) {
+
+ int iterCntr = 0;
+ int k;
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+ const WebRtc_Word16 kAveragePitchGain = 0.0;
+
+ do {
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size. */
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+
+ if (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ /* Being conservative. */
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
+ transcodingParam->stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on the
+ number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains. */
+ if (band == kIsacUpperBand16) {
+ /* Two sets of coefficients if 16 kHz. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam->loFiltGain[k] *= transcodeScale;
+ transcodingParam->hiFiltGain[k] *= transcodeScale;
+ }
+ } else {
+ /* One sets of coefficients if 12 kHz. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam->loFiltGain[k] *= transcodeScale;
+ }
+ }
+
+ /* Scale DFT coefficients. */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (WebRtc_Word16)(fre[k] * transcodeScale + 0.5);
+ fim[k] = (WebRtc_Word16)(fim[k] * transcodeScale + 0.5);
+ }
+ /* Store FFT coefficients for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ ISACencUB_obj->bitstr_obj.W_upper = transcodingParam->W_upper;
+ ISACencUB_obj->bitstr_obj.stream_index = transcodingParam->stream_index;
+ ISACencUB_obj->bitstr_obj.streamval = transcodingParam->streamval;
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 2] =
+ transcodingParam->stream[0];
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 1] =
+ transcodingParam->stream[1];
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index] =
+ transcodingParam->stream[2];
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+ SUBFRAMES * sizeof(double));
+ /* Entropy Code lpc-gains, indices are stored for a later use.*/
+ WebRtcIsac_EncodeLpcGainUb(transcodingParam->loFiltGain,
+ &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ /* If 16kHz should do one more set. */
+ if (band == kIsacUpperBand16) {
+ /* Store the gains for multiple encoding. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain[SUBFRAMES],
+ &lpcGains[SUBFRAMES], SUBFRAMES * sizeof(double));
+ /* Entropy Code lpc-gains, indices are stored for a later use.*/
+ WebRtcIsac_EncodeLpcGainUb(
+ transcodingParam->hiFiltGain, &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+ }
+
+ /* Update the number of bytes left for encoding the spectrum. */
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Encode the spectrum. */
+ status = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain,
+ band, &ISACencUB_obj->bitstr_obj);
+ if ((status < 0) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload). */
+ return status;
+ }
+ iterCntr++;
+ } while ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH));
+ return 0;
+}
+
+int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACencUB_obj,
+ WebRtc_Word32 jitterInfo) {
+ int err;
+ int k;
+
+ double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES << 1) +
+ (1 + UB_LPC_ORDER)];
+
+ double LP_lookahead[FRAMESAMPLES];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[2];
+ double corr[SUBFRAMES << 1][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES << 1];
+ transcode_obj transcodingParam;
+ WebRtc_UWord16 payloadLimitBytes;
+ double s2nr;
+ const WebRtc_Word16 kAveragePitchGain = 0.0;
+ int bytesLeftSpecCoding;
+
+ /* Buffer speech samples (by 10ms packet) until the frame-length is */
+ /* reached (30 ms). */
+ /*********************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+ FRAMESAMPLES_10ms * sizeof(float));
+
+ /* If buffer size is not equal to current frame-size, and end of file is
+ * not reached yet, we don't do encoding unless we have the whole frame. */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+
+ /* End of buffer function. */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ /* Reset bit-stream */
+ WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+ /* Encoding of bandwidth information. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+
+ status = WebRtcIsac_EncodeBandwidth(isac16kHz, &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+ memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
+
+ for (k = 0; k < FRAMESAMPLES; k++) {
+ LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
+ }
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ &lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
+
+ memcpy(ISACencUB_obj->lastLPCVec,
+ &lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
+ sizeof(double) * UB_LPC_ORDER);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac16kHz,
+ &ISACencUB_obj->SaveEnc_obj);
+
+ /* the first set of lpc parameters are from the last sub-frame of
+ * the previous frame. so we don't care about them. */
+ WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
+ (SUBFRAMES << 1), lpcGains, corr, varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
+ }
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+ (SUBFRAMES << 1) * sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+ WebRtcIsac_EncodeLpcGainUb(
+ &lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+
+ /* Get the correct value for the payload limit and calculate the number of
+ bytes left for coding the spectrum. It is a 30ms frame
+ Subract 3 because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ for (k = 0; k < (SUBFRAMES << 1); k++) {
+ percepFilterParams[k * (UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
+ lpcGains[k];
+ }
+
+ /* LPC filtering (using normalized lattice filter), */
+ /* first half-frame. */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[0],
+ &percepFilterParams[UB_LPC_ORDER + 1],
+ &LP_lookahead[0]);
+
+ /* Second half-frame filtering. */
+ WebRtcIsac_NormLatticeFilterMa(
+ UB_LPC_ORDER, ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
+ &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)],
+ &LP_lookahead[FRAMESAMPLES_HALF]);
+
+ WebRtcIsac_Time2Spec(&LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF],
+ fre, fim, &ISACencUB_obj->fftstr_obj);
+
+ /* Store FFT coefficients for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, sizeof(fre));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim, sizeof(fim));
+
+ /* Prepare the audio buffer for the next packet
+ * move the last 3 ms to the beginning of the buffer. */
+ memcpy(ISACencUB_obj->data_buffer_float,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
+ LB_TOTAL_DELAY_SAMPLES * sizeof(float));
+ /* start writing with 3 ms delay to compensate for the delay
+ * of the lower-band. */
+ ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj, &ISACencUB_obj->bitstr_obj,
+ sizeof(Bitstr));
+
+ /* Qantization and lossless coding */
+ /* Note that there is no pitch-gain for this band so kAveragePitchGain = 0
+ * is passed to the function. In fact, the function ignores the 3rd parameter
+ * for this band. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand16,
+ &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ return err;
+ }
+
+ if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+ &transcodingParam, fre, fim, lpcGains,
+ kIsacUpperBand16, err);
+ }
+ if (err < 0) {
+ return err;
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACencUB_obj,
+ WebRtc_Word32 jitterInfo) {
+ int err;
+ int k;
+
+ double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+ double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[1];
+
+ double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES];
+ transcode_obj transcodingParam;
+ WebRtc_UWord16 payloadLimitBytes;
+ double s2nr;
+ const WebRtc_Word16 kAveragePitchGain = 0.0;
+ double bytesLeftSpecCoding;
+
+ /* Buffer speech samples (by 10ms packet) until the framelength is */
+ /* reached (30 ms). */
+ /********************************************************************/
+
+ /* Fill the buffer with 10ms input data. */
+ memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+ FRAMESAMPLES_10ms * sizeof(float));
+
+ /* if buffer-size is not equal to current frame-size then increase the
+ index and return. We do the encoding when we have enough audio. */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* If buffer reached the right size, reset index and continue
+ with encoding the frame */
+ ISACencUB_obj->buffer_index = 0;
+
+ /* End of buffer function */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ /* Reset bit-stream. */
+ WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+ /* Encoding bandwidth information. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+ status = WebRtcIsac_EncodeBandwidth(isac12kHz, &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+ /* Split signal in two bands. */
+ WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
+ HP_lookahead, LP_lookahead,
+ &ISACencUB_obj->prefiltbankstr_obj);
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ lpcVecs, corr, varscale, isac12kHz);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac12kHz,
+ &ISACencUB_obj->SaveEnc_obj);
+
+ WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains, corr,
+ varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains. */
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ }
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
+ sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ for (k = 0; k < SUBFRAMES; k++) {
+ percepFilterParams[k * (UB_LPC_ORDER + 1)] = lpcGains[k];
+ }
+
+ /* perceptual pre-filtering (using normalized lattice filter) */
+ /* low-band filtering */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP,
+ percepFilterParams, LPw);
+
+ /* Get the correct value for the payload limit and calculate the number
+ of bytes left for coding the spectrum. It is a 30ms frame Subract 3
+ because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ memset(HPw, 0, sizeof(HPw));
+
+ /* Transform */
+ WebRtcIsac_Time2Spec(LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj);
+
+ /* Store FFT coefficients for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Quantization and loss-less coding */
+ /* The 4th parameter to this function is pitch-gain, which is only used
+ * when encoding 0-8 kHz band, and irrelevant in this function, therefore,
+ * we insert zero here. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand12,
+ &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload) */
+ return err;
+ }
+
+ if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+ &transcodingParam, fre, fim, lpcGains,
+ kIsacUpperBand12, err);
+ }
+ if (err < 0) {
+ return err;
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+
+
+
+
+/* This function is used to create a new bit-stream with new BWE.
+ The same data as previously encoded with the function WebRtcIsac_Encoder().
+ The data needed is taken from the structure, where it was stored
+ when calling the encoder. */
+
+int WebRtcIsac_EncodeStoredDataLb(const ISAC_SaveEncData_t* ISACSavedEnc_obj,
+ Bitstr* ISACBitStr_obj, int BWnumber,
+ float scale) {
+ int ii;
+ int status;
+ int BWno = BWnumber;
+
+ const WebRtc_UWord16* WebRtcIsac_kQPitchGainCdf_ptr[1];
+ const WebRtc_UWord16** cdf;
+
+ double tmpLPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * 2];
+ double tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * 2];
+ int tmpLPCindex_g[12 * 2];
+ WebRtc_Word16 tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
+ const int kModel = 0;
+
+ /* Sanity Check - possible values for BWnumber is 0 - 23. */
+ if ((BWnumber < 0) || (BWnumber > 23)) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* Reset bit-stream. */
+ WebRtcIsac_ResetBitstream(ISACBitStr_obj);
+
+ /* Encode frame length */
+ status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
+ ISACBitStr_obj);
+ if (status < 0) {
+ /* Wrong frame size. */
+ return status;
+ }
+
+ /* Transcoding */
+ if ((scale > 0.0) && (scale < 1.0)) {
+ /* Compensate LPC gain. */
+ for (ii = 0;
+ ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_lo[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_lo[ii];
+ }
+ for (ii = 0;
+ ii < ((ORDERHI + 1) * SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_hi[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_hi[ii];
+ }
+ /* Scale DFT. */
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = (WebRtc_Word16)((scale) * (float)ISACSavedEnc_obj->fre[ii]);
+ tmp_fim[ii] = (WebRtc_Word16)((scale) * (float)ISACSavedEnc_obj->fim[ii]);
+ }
+ } else {
+ for (ii = 0;
+ ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCindex_g[ii] = ISACSavedEnc_obj->LPCindex_g[ii];
+ }
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
+ tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
+ }
+ }
+
+ /* Encode bandwidth estimate. */
+ WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
+
+ /* Loop over number of 30 msec */
+ for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
+ /* Encode pitch gains. */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchGain_index[ii],
+ WebRtcIsac_kQPitchGainCdf_ptr, 1);
+
+ /* Entropy coding of quantization pitch lags */
+ /* Voicing classification. */
+ if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ } else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ } else {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ }
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES * ii],
+ cdf, PITCH_SUBFRAMES);
+
+ /* LPC */
+ /* Only one model exists. The entropy coding is done only for backward
+ * compatibility. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj, &kModel,
+ WebRtcIsac_kQKltModelCdfPtr, 1);
+ /* Entropy coding of quantization indices - LPC shape only. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE * ii],
+ WebRtcIsac_kQKltCdfPtrShape,
+ KLT_ORDER_SHAPE);
+
+ /* If transcoding, get new LPC gain indices */
+ if (scale < 1.0) {
+ WebRtcIsac_TranscodeLPCCoef(
+ &tmpLPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * ii],
+ &tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * ii],
+ &tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
+ }
+
+ /* Entropy coding of quantization indices - LPC gain. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN * ii],
+ WebRtcIsac_kQKltCdfPtrGain, KLT_ORDER_GAIN);
+
+ /* Quantization and loss-less coding. */
+ status = WebRtcIsac_EncodeSpec(&tmp_fre[ii * FRAMESAMPLES_HALF],
+ &tmp_fim[ii * FRAMESAMPLES_HALF],
+ ISACSavedEnc_obj->AvgPitchGain[ii],
+ kIsacLowerBand, ISACBitStr_obj);
+ if (status < 0) {
+ return status;
+ }
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(ISACBitStr_obj);
+}
+
+
+int WebRtcIsac_EncodeStoredDataUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo,
+ float scale,
+ enum ISACBandwidth bandwidth) {
+ int n;
+ int err;
+ double lpcGain[SUBFRAMES];
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+ const WebRtc_UWord16** shape_cdf;
+ int shape_len;
+ const WebRtc_Word16 kAveragePitchGain = 0.0;
+ enum ISACBand band;
+ /* Reset bitstream. */
+ WebRtcIsac_ResetBitstream(bitStream);
+
+ /* Encode jitter index. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
+
+ err = WebRtcIsac_EncodeBandwidth(bandwidth, bitStream);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Encode LPC-shape. */
+ if (bandwidth == isac12kHz) {
+ shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb12;
+ shape_len = UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME;
+ band = kIsacUpperBand12;
+ } else {
+ shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb16;
+ shape_len = UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME;
+ band = kIsacUpperBand16;
+ }
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
+ shape_cdf, shape_len);
+
+ if ((scale <= 0.0) || (scale >= 1.0)) {
+ /* We only consider scales between zero and one. */
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ if (bandwidth == isac16kHz) {
+ /* Store gain indices of the second half. */
+ WebRtcIsac_EncHistMulti(bitStream,
+ &ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ }
+ /* Store FFT coefficients. */
+ err = WebRtcIsac_EncodeSpec(ISACSavedEnc_obj->realFFT,
+ ISACSavedEnc_obj->imagFFT, kAveragePitchGain,
+ band, bitStream);
+ } else {
+ /* Scale LPC gain and FFT coefficients. */
+ for (n = 0; n < SUBFRAMES; n++) {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
+ }
+ /* Store LPC gains. */
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+
+ if (bandwidth == isac16kHz) {
+ /* Scale and code the gains of the second half of the frame, if 16kHz. */
+ for (n = 0; n < SUBFRAMES; n++) {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
+ }
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+ }
+
+ for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+ realFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->realFFT[n] +
+ 0.5f);
+ imagFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->imagFFT[n] +
+ 0.5f);
+ }
+ /* Store FFT coefficients. */
+ err = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain,
+ band, bitStream);
+ }
+ if (err < 0) {
+ /* Error happened while encoding FFT coefficients. */
+ return err;
+ }
+
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(bitStream);
+}
+
+WebRtc_Word16 WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+ Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth) {
+ int n;
+ WebRtc_Word16 status;
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+ enum ISACBand band;
+ const WebRtc_Word16 kAveragePitchGain = 0.0;
+ /* Store bit-stream object. */
+ memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
+
+ /* Scale FFT coefficients. */
+ for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+ realFFT[n] = (WebRtc_Word16)((float)ISACSavedEncObj->realFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ imagFFT[n] = (WebRtc_Word16)((float)ISACSavedEncObj->imagFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ }
+
+ band = (bandwidth == isac12kHz) ? kIsacUpperBand12 : kIsacUpperBand16;
+ status = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain, band,
+ bitStreamObj);
+ if (status < 0) {
+ return status;
+ } else {
+ /* Terminate entropy coding */
+ return WebRtcIsac_EncTerminate(bitStreamObj);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c b/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
new file mode 100644
index 0000000..2bf4c36
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * code_LPC_UB.c
+ *
+ * This file contains definition of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#include "encode_lpc_swb.h"
+#include "typedefs.h"
+#include "settings.h"
+
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+WebRtc_Word16
+WebRtcIsac_RemoveLarMean(
+ double* lar,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 numVec;
+ const double* meanLAR;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ // REMOVE MEAN
+ *lar++ -= meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16
+WebRtcIsac_DecorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ const double* ptrData;
+ const double* ptrRow;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 larVecCntr;
+ WebRtc_Word16 numVec;
+ const double* decorrMat;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ numVec = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // decorrMat * data
+ //
+ // data is assumed to contain 'numVec' of LAR
+ // vectors (mean removed) each of dimension 'UB_LPC_ORDER'
+ // concatenated one after the other.
+ //
+
+ ptrData = data;
+ for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
+ {
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out += ptrData[colCntr] * ptrRow[colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16
+WebRtcIsac_DecorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ const double* decorrMat;
+ WebRtc_Word16 interVecDim;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // data * decorrMat
+ //
+ // data is of size 'interVecDim' * 'UB_LPC_ORDER'
+ // That is 'interVecDim' of LAR vectors (mean removed)
+ // in columns each of dimension 'UB_LPC_ORDER'.
+ // matrix is stored column-wise.
+ //
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] +=
+ data[coeffCntr + rowCntr * UB_LPC_ORDER] *
+ decorrMat[rowCntr * interVecDim + colCntr];
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double
+WebRtcIsac_QuantizeUncorrLar(
+ double* data,
+ int* recIdx,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 cntr;
+ WebRtc_Word32 idx;
+ WebRtc_Word16 interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+ const WebRtc_Word16* numQuantCell;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Quantize the parametrs.
+ //
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ idx = (WebRtc_Word32)floor((*data - leftRecPoint[cntr]) /
+ quantizationStepSize + 0.5);
+ if(idx < 0)
+ {
+ idx = 0;
+ }
+ else if(idx >= numQuantCell[cntr])
+ {
+ idx = numQuantCell[cntr] - 1;
+ }
+
+ *data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
+ *recIdx++ = idx;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+WebRtc_Word16
+WebRtcIsac_DequantizeLpcParam(
+ const int* idx,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 cntr;
+ WebRtc_Word16 interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Dequantize given the quantization indices
+ //
+
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16
+WebRtcIsac_CorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 numVec;
+ const double* ptrData;
+ const double* intraVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+
+ ptrData = data;
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ *out += ptrData[rowCntr] *
+ intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16
+WebRtcIsac_CorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 interVecDim;
+ double myVec[UB16_LPC_VEC_PER_FRAME];
+ const double* interVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ myVec[rowCntr] = 0;
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
+ interVecDecorrMat[rowCntr * interVecDim + colCntr];
+ //ptrData += UB_LPC_ORDER;
+ }
+ }
+
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+WebRtc_Word16
+WebRtcIsac_AddLarMean(
+ double* data,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 numVec;
+ const double* meanLAR;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ *data++ += meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+WebRtc_Word16
+WebRtcIsac_ToLogDomainRemoveMean(
+ double* data)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateLPGain(
+ const double* data,
+ double* out)
+{
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
+ }
+ out++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+ double* data,
+ int* idx)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
+ WebRtcIsac_kQSizeLpcGain + 0.5);
+
+ if(*idx < 0)
+ {
+ *idx = 0;
+ }
+ else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
+ {
+ *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
+ }
+ *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+
+ data++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcGain(
+ const int* idx,
+ double* out)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+ out++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateLpcGain(
+ const double* data,
+ double* out)
+{
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
+ }
+ out++;
+ }
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+WebRtc_Word16 WebRtcIsac_AddMeanToLinearDomain(
+ double* lpcGains)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
+ }
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h b/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
new file mode 100644
index 0000000..e7f1a76
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode_lpc_swb.h
+ *
+ * This file contains declaration of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+
+#include "typedefs.h"
+#include "settings.h"
+#include "structs.h"
+
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+WebRtc_Word16 WebRtcIsac_RemoveLarMean(
+ double* lar,
+ WebRtc_Word16 bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateIntraVec(
+ const double* inLAR,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double WebRtcIsac_QuantizeUncorrLar(
+ double* data,
+ int* idx,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+WebRtc_Word16 WebRtcIsac_AddLarMean(
+ double* data,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcParam(
+ const int* idx,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+WebRtc_Word16 WebRtcIsac_ToLogDomainRemoveMean(
+ double* lpGains);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateLPGain(
+ const double* data,
+ double* out);
+
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+ double* lpGains,
+ int* idx);
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcGain(
+ const int* idx,
+ double* lpGains);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateLpcGain(
+ const double* data,
+ double* out);
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+WebRtc_Word16 WebRtcIsac_AddMeanToLinearDomain(
+ double* lpcGains);
+
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
diff --git a/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.c b/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
new file mode 100644
index 0000000..49c695c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
@@ -0,0 +1,2066 @@
+/*
+ * 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.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This header file defines all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+
+#include "entropy_coding.h"
+#include "settings.h"
+#include "arith_routines.h"
+#include "signal_processing_library.h"
+#include "spectrum_ar_model_tables.h"
+#include "lpc_tables.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "encode_lpc_swb.h"
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+#include "os_specific_inline.h"
+
+#include <math.h>
+#include <string.h>
+
+static const WebRtc_UWord16 kLpcVecPerSegmentUb12 = 5;
+static const WebRtc_UWord16 kLpcVecPerSegmentUb16 = 4;
+
+/* CDF array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const WebRtc_UWord16 kOneBitEqualProbCdf[3] = {
+ 0, 32768, 65535 };
+
+/* Pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const WebRtc_UWord16* kOneBitEqualProbCdf_ptr[1] = {
+ kOneBitEqualProbCdf };
+
+/*
+ * Initial cdf index for decoder of encoded bandwidth
+ * (12 vs 16 kHz) indicator.
+ */
+static const WebRtc_UWord16 kOneBitEqualProbInitIndex[1] = { 1 };
+
+
+static const int kIsSWB12 = 1;
+
+/* compute correlation from power spectrum */
+static void FindCorrelation(WebRtc_Word32* PSpecQ12, WebRtc_Word32* CorrQ7) {
+ WebRtc_Word32 summ[FRAMESAMPLES / 8];
+ WebRtc_Word32 diff[FRAMESAMPLES / 8];
+ const WebRtc_Word16* CS_ptrQ9;
+ WebRtc_Word32 sum;
+ int k, n;
+
+ for (k = 0; k < FRAMESAMPLES / 8; k++) {
+ summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+ diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+ }
+
+ sum = 2;
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ sum += summ[n];
+ }
+ CorrQ7[0] = sum;
+
+ for (k = 0; k < AR_ORDER; k += 2) {
+ sum = 0;
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++)
+ sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9;
+ CorrQ7[k + 1] = sum;
+ }
+
+ for (k = 1; k < AR_ORDER; k += 2) {
+ sum = 0;
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++)
+ sum += (CS_ptrQ9[n] * summ[n] + 256) >> 9;
+ CorrQ7[k + 1] = sum;
+ }
+}
+
+/* compute inverse AR power spectrum */
+/* Changed to the function used in iSAC FIX for compatibility reasons */
+static void FindInvArSpec(const WebRtc_Word16* ARCoefQ12,
+ const WebRtc_Word32 gainQ10,
+ WebRtc_Word32* CurveQ16) {
+ WebRtc_Word32 CorrQ11[AR_ORDER + 1];
+ WebRtc_Word32 sum, tmpGain;
+ WebRtc_Word32 diffQ16[FRAMESAMPLES / 8];
+ const WebRtc_Word16* CS_ptrQ9;
+ int k, n;
+ WebRtc_Word16 round, shftVal = 0, sh;
+
+ sum = 0;
+ for (n = 0; n < AR_ORDER + 1; n++) {
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */
+ }
+ sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6),
+ 65) + 32768, 16); /* Q8 */
+ CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9);
+
+ /* To avoid overflow, we shift down gainQ10 if it is large.
+ * We will not lose any precision */
+ if (gainQ10 > 400000) {
+ tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3);
+ round = 32;
+ shftVal = 6;
+ } else {
+ tmpGain = gainQ10;
+ round = 256;
+ shftVal = 9;
+ }
+
+ for (k = 1; k < AR_ORDER + 1; k++) {
+ sum = 16384;
+ for (n = k; n < AR_ORDER + 1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n - k], ARCoefQ12[n]); /* Q24 */
+ sum = WEBRTC_SPL_RSHIFT_W32(sum, 15);
+ CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round,
+ shftVal);
+ }
+ sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7);
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ CurveQ16[n] = sum;
+ }
+ for (k = 1; k < AR_ORDER; k += 2) {
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
+ WebRtcIsac_kCos[k][n], CorrQ11[k + 1]) + 2, 2);
+ }
+ }
+
+ CS_ptrQ9 = WebRtcIsac_kCos[0];
+
+ /* If CorrQ11[1] too large we avoid getting overflow in the
+ * calculation by shifting */
+ sh = WebRtcSpl_NormW32(CorrQ11[1]);
+ if (CorrQ11[1] == 0) { /* Use next correlation */
+ sh = WebRtcSpl_NormW32(CorrQ11[2]);
+ }
+ if (sh < 9) {
+ shftVal = 9 - sh;
+ } else {
+ shftVal = 0;
+ }
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
+ CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2);
+ }
+ for (k = 2; k < AR_ORDER; k += 2) {
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
+ CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k + 1], shftVal)) + 2, 2);
+ }
+ }
+
+ for (k = 0; k < FRAMESAMPLES / 8; k++) {
+ CurveQ16[FRAMESAMPLES_QUARTER - 1 - k] = CurveQ16[k] -
+ WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
+ CurveQ16[k] += WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
+ }
+}
+
+/* Generate array of dither samples in Q7. */
+static void GenerateDitherQ7Lb(WebRtc_Word16* bufQ7, WebRtc_UWord32 seed,
+ int length, WebRtc_Word16 AvgPitchGain_Q12) {
+ int k, shft;
+ WebRtc_Word16 dither1_Q7, dither2_Q7, dither_gain_Q14;
+
+ /* This threshold should be equal to that in decode_spec(). */
+ if (AvgPitchGain_Q12 < 614) {
+ for (k = 0; k < length - 2; k += 3) {
+ /* New random unsigned int. */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64 (Q7). */
+ /* dither = seed * 128 / 4294967295 */
+ dither1_Q7 = (WebRtc_Word16)(((int)seed + 16777216) >> 25);
+
+ /* New random unsigned int. */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64. */
+ dither2_Q7 = (WebRtc_Word16)(((int)seed + 16777216) >> 25);
+
+ shft = (seed >> 25) & 15;
+ if (shft < 5) {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k + 1] = dither2_Q7;
+ bufQ7[k + 2] = 0;
+ } else if (shft < 10) {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k + 1] = 0;
+ bufQ7[k + 2] = dither2_Q7;
+ } else {
+ bufQ7[k] = 0;
+ bufQ7[k + 1] = dither1_Q7;
+ bufQ7[k + 2] = dither2_Q7;
+ }
+ }
+ } else {
+ dither_gain_Q14 = (WebRtc_Word16)(22528 - 10 * AvgPitchGain_Q12);
+
+ /* Dither on half of the coefficients. */
+ for (k = 0; k < length - 1; k += 2) {
+ /* New random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64. */
+ dither1_Q7 = (WebRtc_Word16)(((int)seed + 16777216) >> 25);
+
+ /* Dither sample is placed in either even or odd index. */
+ shft = (seed >> 25) & 1; /* Either 0 or 1 */
+
+ bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192) >> 14);
+ bufQ7[k + 1 - shft] = 0;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * GenerateDitherQ7LbUB()
+ *
+ * generate array of dither samples in Q7 There are less zeros in dither
+ * vector compared to GenerateDitherQ7Lb.
+ *
+ * A uniform random number generator with the range of [-64 64] is employed
+ * but the generated dithers are scaled by 0.35, a heuristic scaling.
+ *
+ * Input:
+ * -seed : the initial seed for the random number generator.
+ * -length : the number of dither values to be generated.
+ *
+ * Output:
+ * -bufQ7 : pointer to a buffer where dithers are written to.
+ */
+static void GenerateDitherQ7LbUB(
+ WebRtc_Word16* bufQ7,
+ WebRtc_UWord32 seed,
+ int length) {
+ int k;
+ for (k = 0; k < length; k++) {
+ /* new random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64 (Q7). */
+ /* bufQ7 = seed * 128 / 4294967295 */
+ bufQ7[k] = (WebRtc_Word16)(((int)seed + 16777216) >> 25);
+
+ /* Scale by 0.35. */
+ bufQ7[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k], 2048, 13);
+ }
+}
+
+/*
+ * Function to decode the complex spectrum from the bit stream
+ * returns the total number of bytes in the stream.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata, WebRtc_Word16 AvgPitchGain_Q12,
+ enum ISACBand band, double* fr, double* fi) {
+ WebRtc_Word16 DitherQ7[FRAMESAMPLES];
+ WebRtc_Word16 data[FRAMESAMPLES];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER + 1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 gainQ10;
+ WebRtc_Word32 gain2_Q10, res;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ int k, len, i;
+ int is_12khz = !kIsSWB12;
+ int num_dft_coeff = FRAMESAMPLES;
+ /* Create dither signal. */
+ if (band == kIsacLowerBand) {
+ GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES,
+ AvgPitchGain_Q12);
+ } else {
+ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
+ if (band == kIsacUpperBand12) {
+ is_12khz = kIsSWB12;
+ num_dft_coeff = FRAMESAMPLES_HALF;
+ }
+ }
+
+ /* Decode model parameters. */
+ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* Compute inverse AR power spectrum. */
+ FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* Convert to magnitude spectrum,
+ * by doing square-roots (modified from SPLIB). */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt < 0)
+ in_sqrt = -in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7,
+ num_dft_coeff, is_12khz);
+ /* Arithmetic decoding of spectrum. */
+ if (len < 1) {
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+ }
+
+ switch (band) {
+ case kIsacLowerBand: {
+ /* Scale down spectral samples with low SNR. */
+ WebRtc_Word32 p1;
+ WebRtc_Word32 p2;
+ if (AvgPitchGain_Q12 <= 614) {
+ p1 = 30 << 10;
+ p2 = 32768 + (33 << 16);
+ } else {
+ p1 = 36 << 10;
+ p2 = 32768 + (40 << 16);
+ }
+ for (k = 0; k < FRAMESAMPLES; k += 4) {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(p1, (WebRtc_Word16)(
+ (invARSpec2_Q16[k >> 2] + p2) >> 16));
+ *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k + 1] * gainQ10 + 512) >> 10) / 128.0;
+ *fr++ = (double)((data[k + 2] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k + 3] * gainQ10 + 512) >> 10) / 128.0;
+ }
+ break;
+ }
+ case kIsacUpperBand12: {
+ for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4) {
+ fr[i] = (double)data[ k ] / 128.0;
+ fi[i] = (double)data[k + 1] / 128.0;
+ i++;
+ fr[i] = (double)data[k + 2] / 128.0;
+ fi[i] = (double)data[k + 3] / 128.0;
+ i++;
+ }
+ /* The second half of real and imaginary coefficients is zero. This is
+ * due to using the old FFT module which requires two signals as input
+ * while in 0-12 kHz mode we only have 8-12 kHz band, and the second
+ * signal is set to zero. */
+ memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+ sizeof(double));
+ memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+ sizeof(double));
+ break;
+ }
+ case kIsacUpperBand16: {
+ for (i = 0, k = 0; k < FRAMESAMPLES; k += 4, i++) {
+ fr[i] = (double)data[ k ] / 128.0;
+ fi[i] = (double)data[k + 1] / 128.0;
+ fr[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 2] / 128.0;
+ fi[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 3] / 128.0;
+ }
+ break;
+ }
+ }
+ return len;
+}
+
+
+int WebRtcIsac_EncodeSpec(const WebRtc_Word16* fr, const WebRtc_Word16* fi,
+ WebRtc_Word16 AvgPitchGain_Q12, enum ISACBand band,
+ Bitstr* streamdata) {
+ WebRtc_Word16 ditherQ7[FRAMESAMPLES];
+ WebRtc_Word16 dataQ7[FRAMESAMPLES];
+ WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 CorrQ7[AR_ORDER + 1];
+ WebRtc_Word32 CorrQ7_norm[AR_ORDER + 1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER + 1];
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word16 val;
+ WebRtc_Word32 nrg, res;
+ WebRtc_UWord32 sum;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ WebRtc_Word16 err;
+ WebRtc_UWord32 nrg_u32;
+ int shift_var;
+ int k, n, j, i;
+ int is_12khz = !kIsSWB12;
+ int num_dft_coeff = FRAMESAMPLES;
+
+ /* Create dither signal. */
+ if (band == kIsacLowerBand) {
+ GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES,
+ AvgPitchGain_Q12);
+ } else {
+ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
+ if (band == kIsacUpperBand12) {
+ is_12khz = kIsSWB12;
+ num_dft_coeff = FRAMESAMPLES_HALF;
+ }
+ }
+
+ /* add dither and quantize, and compute power spectrum */
+ switch (band) {
+ case kIsacLowerBand: {
+ for (k = 0; k < FRAMESAMPLES; k += 4) {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum += val * val;
+
+ val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[k >> 2] = sum >> 2;
+ }
+ break;
+ }
+ case kIsacUpperBand12: {
+ for (k = 0, j = 0; k < FRAMESAMPLES_HALF; k += 4) {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ PSpec[j++] = sum >> 1;
+
+ val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[j++] = sum >> 1;
+ }
+ break;
+ }
+ case kIsacUpperBand16: {
+ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) {
+ val = ((fr[j] + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((fi[j] + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 2] + 64) &
+ 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum += val * val;
+
+ val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 3] + 64) &
+ 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[k >> 2] = sum >> 2;
+ }
+ break;
+ }
+ }
+
+ /* compute correlation from power spectrum */
+ FindCorrelation(PSpec, CorrQ7);
+
+ /* Find AR coefficients */
+ /* Aumber of bit shifts to 14-bit normalize CorrQ7[0]
+ * (leaving room for sign) */
+ shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (shift_var > 0) {
+ for (k = 0; k < AR_ORDER + 1; k++) {
+ CorrQ7_norm[k] = CorrQ7[k] << shift_var;
+ }
+ } else {
+ for (k = 0; k < AR_ORDER + 1; k++) {
+ CorrQ7_norm[k] = CorrQ7[k] >> (-shift_var);
+ }
+ }
+
+ /* Find RC coefficients. */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* Quantize & code RC Coefficient. */
+ WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ /* Compute ARCoef' * Corr * ARCoef in Q19. */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++) {
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ }
+ for (n = j + 1; n <= AR_ORDER; n++) {
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ }
+ }
+
+ nrg_u32 = (WebRtc_UWord32)nrg;
+ if (shift_var > 0) {
+ nrg_u32 = nrg_u32 >> shift_var;
+ } else {
+ nrg_u32 = nrg_u32 << (-shift_var);
+ }
+ if (nrg_u32 > 0x7FFFFFFF) {
+ nrg = 0x7FFFFFFF;
+ } else {
+ nrg = (WebRtc_Word32)nrg_u32;
+ }
+ /* Also shifts 31 bits to the left! */
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg);
+
+ /* Quantize & code gain2_Q10. */
+ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+ return -1;
+ }
+
+ /* Compute inverse AR power spectrum. */
+ FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+ /* Convert to magnitude spectrum, by doing square-roots
+ * (modified from SPLIB). */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt < 0) {
+ in_sqrt = -in_sqrt;
+ }
+ newRes = (in_sqrt / res + res) >> 1;
+ do {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+ /* arithmetic coding of spectrum */
+ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+ num_dft_coeff, is_12khz);
+ if (err < 0) {
+ return (err);
+ }
+ return 0;
+}
+
+
+/* step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a) {
+ int m, k;
+ double tmp[MAX_AR_MODEL_ORDER];
+
+ a[0] = 1.0;
+ tmp[0] = 1.0;
+ for (m = 1; m <= N; m++) {
+ /* copy */
+ memcpy(&tmp[1], &a[1], (m - 1) * sizeof(double));
+ a[m] = RC[m - 1];
+ for (k = 1; k < m; k++) {
+ a[k] += RC[m - 1] * tmp[m - k];
+ }
+ }
+ return;
+}
+
+/* step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC) {
+ int m, k;
+ double tmp[MAX_AR_MODEL_ORDER];
+ double tmp_inv;
+
+ RC[N - 1] = a[N];
+ for (m = N - 1; m > 0; m--) {
+ tmp_inv = 1.0 / (1.0 - RC[m] * RC[m]);
+ for (k = 1; k <= m; k++) {
+ tmp[k] = (a[k] - RC[m] * a[m - k + 1]) * tmp_inv;
+ }
+
+ memcpy(&a[1], &tmp[1], (m - 1) * sizeof(double));
+ RC[m - 1] = tmp[m];
+ }
+ return;
+}
+
+
+#define MAX_ORDER 100
+
+/* Matlab's LAR definition */
+void WebRtcIsac_Rc2Lar(const double* refc, double* lar, int order) {
+ int k;
+ for (k = 0; k < order; k++) {
+ lar[k] = log((1 + refc[k]) / (1 - refc[k]));
+ }
+}
+
+
+void WebRtcIsac_Lar2Rc(const double* lar, double* refc, int order) {
+ int k;
+ double tmp;
+
+ for (k = 0; k < order; k++) {
+ tmp = exp(lar[k]);
+ refc[k] = (tmp - 1) / (tmp + 1);
+ }
+}
+
+void WebRtcIsac_Poly2Lar(double* lowband, int orderLo, double* hiband,
+ int orderHi, int Nsub, double* lars) {
+ int k;
+ double rc[MAX_ORDER], *inpl, *inph, *outp;
+
+ inpl = lowband;
+ inph = hiband;
+ outp = lars;
+ for (k = 0; k < Nsub; k++) {
+ /* gains */
+ outp[0] = inpl[0];
+ outp[1] = inph[0];
+ outp += 2;
+
+ /* Low band */
+ inpl[0] = 1.0;
+ WebRtcIsac_Poly2Rc(inpl, orderLo, rc);
+ WebRtcIsac_Rc2Lar(rc, outp, orderLo);
+ outp += orderLo;
+
+ /* High band */
+ inph[0] = 1.0;
+ WebRtcIsac_Poly2Rc(inph, orderHi, rc);
+ WebRtcIsac_Rc2Lar(rc, outp, orderHi);
+ outp += orderHi;
+
+ inpl += orderLo + 1;
+ inph += orderHi + 1;
+ }
+}
+
+
+WebRtc_Word16 WebRtcIsac_Poly2LarUB(double* lpcVecs, WebRtc_Word16 bandwidth) {
+ double poly[MAX_ORDER];
+ double rc[MAX_ORDER];
+ double* ptrIO;
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 vecSize;
+ WebRtc_Word16 numVec;
+
+ vecSize = UB_LPC_ORDER;
+ switch (bandwidth) {
+ case isac12kHz: {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz: {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ ptrIO = lpcVecs;
+ poly[0] = 1.0;
+ for (vecCntr = 0; vecCntr < numVec; vecCntr++) {
+ memcpy(&poly[1], ptrIO, sizeof(double) * vecSize);
+ WebRtcIsac_Poly2Rc(poly, vecSize, rc);
+ WebRtcIsac_Rc2Lar(rc, ptrIO, vecSize);
+ ptrIO += vecSize;
+ }
+ return 0;
+}
+
+
+void WebRtcIsac_Lar2Poly(double* lars, double* lowband, int orderLo,
+ double* hiband, int orderHi, int Nsub) {
+ int k, orderTot;
+ double rc[MAX_ORDER], *outpl, *outph, *inp;
+
+ orderTot = (orderLo + orderHi + 2);
+ outpl = lowband;
+ outph = hiband;
+ /* First two elements of 'inp' store gains*/
+ inp = lars;
+ for (k = 0; k < Nsub; k++) {
+ /* Low band */
+ WebRtcIsac_Lar2Rc(&inp[2], rc, orderLo);
+ WebRtcIsac_Rc2Poly(rc, orderLo, outpl);
+
+ /* High band */
+ WebRtcIsac_Lar2Rc(&inp[orderLo + 2], rc, orderHi);
+ WebRtcIsac_Rc2Poly(rc, orderHi, outph);
+
+ /* gains */
+ outpl[0] = inp[0];
+ outph[0] = inp[1];
+
+ outpl += orderLo + 1;
+ outph += orderHi + 1;
+ inp += orderTot;
+ }
+}
+
+/*
+ * assumes 2 LAR vectors interpolates to 'numPolyVec' A-polynomials
+ * Note: 'numPolyVecs' includes the first and the last point of the interval
+ */
+void WebRtcIsac_Lar2PolyInterpolUB(double* larVecs, double* percepFilterParams,
+ int numPolyVecs) {
+ int polyCntr, coeffCntr;
+ double larInterpol[UB_LPC_ORDER];
+ double rc[UB_LPC_ORDER];
+ double delta[UB_LPC_ORDER];
+
+ /* calculate the step-size for linear interpolation coefficients */
+ for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+ delta[coeffCntr] = (larVecs[UB_LPC_ORDER + coeffCntr] -
+ larVecs[coeffCntr]) / (numPolyVecs - 1);
+ }
+
+ for (polyCntr = 0; polyCntr < numPolyVecs; polyCntr++) {
+ for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+ larInterpol[coeffCntr] = larVecs[coeffCntr] +
+ delta[coeffCntr] * polyCntr;
+ }
+ WebRtcIsac_Lar2Rc(larInterpol, rc, UB_LPC_ORDER);
+
+ /* convert to A-polynomial, the following function returns A[0] = 1;
+ * which is written where gains had to be written. Then we write the
+ * gain (outside this function). This way we say a memcpy. */
+ WebRtcIsac_Rc2Poly(rc, UB_LPC_ORDER, percepFilterParams);
+ percepFilterParams += (UB_LPC_ORDER + 1);
+ }
+}
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata, double* LPCCoef_lo,
+ double* LPCCoef_hi) {
+ double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+ int err;
+
+ err = WebRtcIsac_DecodeLpcCoef(streamdata, lars);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+ }
+ WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+ SUBFRAMES);
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+ double* percepFilterParams,
+ WebRtc_Word16 bandwidth) {
+ double lpcCoeff[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int err;
+ int interpolCntr;
+ int subframeCntr;
+ WebRtc_Word16 numSegments;
+ WebRtc_Word16 numVecPerSegment;
+ WebRtc_Word16 numGains;
+
+ double percepFilterGains[SUBFRAMES << 1];
+ double* ptrOutParam = percepFilterParams;
+
+ err = WebRtcIsac_DecodeLpcCoefUB(streamdata, lpcCoeff, percepFilterGains,
+ bandwidth);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+ }
+
+ switch (bandwidth) {
+ case isac12kHz: {
+ numGains = SUBFRAMES;
+ numSegments = UB_LPC_VEC_PER_FRAME - 1;
+ numVecPerSegment = kLpcVecPerSegmentUb12;
+ break;
+ }
+ case isac16kHz: {
+ numGains = SUBFRAMES << 1;
+ numSegments = UB16_LPC_VEC_PER_FRAME - 1;
+ numVecPerSegment = kLpcVecPerSegmentUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for (interpolCntr = 0; interpolCntr < numSegments; interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(&lpcCoeff[interpolCntr * UB_LPC_ORDER],
+ ptrOutParam, numVecPerSegment + 1);
+ ptrOutParam += (numVecPerSegment * (UB_LPC_ORDER + 1));
+ }
+
+ ptrOutParam = percepFilterParams;
+
+ if (bandwidth == isac16kHz) {
+ ptrOutParam += (1 + UB_LPC_ORDER);
+ }
+
+ for (subframeCntr = 0; subframeCntr < numGains; subframeCntr++) {
+ *ptrOutParam = percepFilterGains[subframeCntr];
+ ptrOutParam += (1 + UB_LPC_ORDER);
+ }
+ return 0;
+}
+
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef) {
+ int j, k, n, pos, pos2, posg, poss, offsg, offss, offs2;
+ int index_g[KLT_ORDER_GAIN], index_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs_g[KLT_ORDER_GAIN], tmpcoeffs_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN], tmpcoeffs2_s[KLT_ORDER_SHAPE];
+ double sum;
+ int err;
+ int model = 1;
+
+ /* entropy decoding of model number */
+ /* We are keeping this for backward compatibility of bit-streams. */
+ err = WebRtcIsac_DecHistOneStepMulti(&model, streamdata,
+ WebRtcIsac_kQKltModelCdfPtr,
+ WebRtcIsac_kQKltModelInitIndex, 1);
+ if (err < 0) {
+ return err;
+ }
+ /* Only accepted value of model is 0. It is kept in bit-stream for backward
+ * compatibility. */
+ if (model != 0) {
+ return -ISAC_DISALLOWED_LPC_MODEL;
+ }
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kQKltCdfPtrShape,
+ WebRtcIsac_kQKltInitIndexShape, KLT_ORDER_SHAPE);
+ if (err < 0) {
+ return err;
+ }
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_g, streamdata, WebRtcIsac_kQKltCdfPtrGain,
+ WebRtcIsac_kQKltInitIndexGain, KLT_ORDER_GAIN);
+ if (err < 0) {
+ return err;
+ }
+
+ /* find quantization levels for coefficients */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_s[k] =
+ WebRtcIsac_kQKltLevelsShape[WebRtcIsac_kQKltOffsetShape[k] +
+ index_s[k]];
+ }
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOffsetGain[k] +
+ index_g[k]];
+ }
+
+ /* Inverse KLT */
+
+ /* Left transform, transpose matrix! */
+ offsg = 0;
+ offss = 0;
+ posg = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ offs2 += LPC_GAIN_ORDER;
+ }
+ offs2 = 0;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ offs2 += LPC_SHAPE_ORDER;
+ }
+ offsg += LPC_GAIN_ORDER;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform, transpose matrix */
+ offsg = 0;
+ offss = 0;
+ posg = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+ pos += LPC_GAIN_ORDER;
+ pos2 += SUBFRAMES;
+
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* scaling, mean addition, and gain restoration */
+ posg = 0;
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* log gains */
+ LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef[pos] = exp(LPCCoef[pos]);
+ pos++;
+ posg++;
+ LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef[pos] = exp(LPCCoef[pos]);
+ pos++;
+ posg++;
+
+ /* Low-band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+
+ /* High-band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+ }
+ return 0;
+}
+
+/* Encode LPC in LAR domain. */
+void WebRtcIsac_EncodeLar(double* LPCCoef, Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData) {
+ int j, k, n, pos, pos2, poss, offss, offs2;
+ int index_s[KLT_ORDER_SHAPE];
+ int index_ovr_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs2_s[KLT_ORDER_SHAPE];
+ double sum;
+ const int kModel = 0;
+
+ /* Mean removal and scaling. */
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* First two element are gains, move over them. */
+ pos += 2;
+
+ /* Low-band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, poss++, pos++) {
+ tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+ tmpcoeffs_s[poss] *= LPC_LOBAND_SCALE;
+ }
+
+ /* High-band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, poss++, pos++) {
+ tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+ tmpcoeffs_s[poss] *= LPC_HIBAND_SCALE;
+ }
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = k;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2];
+ pos2 += LPC_SHAPE_ORDER;
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform. */
+ offss = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2++];
+ pos += LPC_SHAPE_ORDER;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Quantize coefficients. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ index_s[k] = (WebRtcIsac_lrint(tmpcoeffs_s[k] / KLT_STEPSIZE)) +
+ WebRtcIsac_kQKltQuantMinShape[k];
+ if (index_s[k] < 0) {
+ index_s[k] = 0;
+ } else if (index_s[k] > WebRtcIsac_kQKltMaxIndShape[k]) {
+ index_s[k] = WebRtcIsac_kQKltMaxIndShape[k];
+ }
+ index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[k] + index_s[k];
+ }
+
+
+ /* Only one model remains in this version of the code, kModel = 0. We
+ * are keeping for bit-streams to be backward compatible. */
+ /* entropy coding of model number */
+ WebRtcIsac_EncHistMulti(streamdata, &kModel, WebRtcIsac_kQKltModelCdfPtr, 1);
+
+ /* Save data for creation of multiple bit streams */
+ /* Entropy coding of quantization indices - shape only. */
+ WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape,
+ KLT_ORDER_SHAPE);
+
+ /* Save data for creation of multiple bit streams. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ encData->LPCindex_s[KLT_ORDER_SHAPE * encData->startIdx + k] = index_s[k];
+ }
+
+ /* Find quantization levels for shape coefficients. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_s[k] = WebRtcIsac_kQKltLevelsShape[index_ovr_s[k]];
+ }
+ /* Inverse KLT. */
+ /* Left transform, transpose matrix.! */
+ offss = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ offs2 += LPC_SHAPE_ORDER;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform, Transpose matrix */
+ offss = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Scaling, mean addition, and gain restoration. */
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* Ignore gains. */
+ pos += 2;
+
+ /* Low band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+
+ /* High band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+ }
+}
+
+
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata, ISAC_SaveEncData_t* encData) {
+ double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+ int k;
+
+ WebRtcIsac_Poly2Lar(LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI, SUBFRAMES,
+ lars);
+ WebRtcIsac_EncodeLar(lars, streamdata, encData);
+ WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+ SUBFRAMES);
+ /* Save data for creation of multiple bit streams (and transcoding). */
+ for (k = 0; k < (ORDERLO + 1)*SUBFRAMES; k++) {
+ encData->LPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * encData->startIdx + k] =
+ LPCCoef_lo[k];
+ }
+ for (k = 0; k < (ORDERHI + 1)*SUBFRAMES; k++) {
+ encData->LPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * encData->startIdx + k] =
+ LPCCoef_hi[k];
+ }
+}
+
+
+WebRtc_Word16 WebRtcIsac_EncodeLpcUB(double* lpcVecs, Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ WebRtc_Word16 bandwidth,
+ ISACUBSaveEncDataStruct* encData) {
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int interpolCntr;
+
+ WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth);
+ WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth);
+ WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth);
+
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+
+ switch (bandwidth) {
+ case isac12kHz: {
+ /* Store the indices to be used for multiple encoding. */
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+ UB_LPC_VEC_PER_FRAME * sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12,
+ UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+ for (interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS;
+ interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+ kLpcVecPerSegmentUb12 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ case isac16kHz: {
+ /* Store the indices to be used for multiple encoding. */
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+ UB16_LPC_VEC_PER_FRAME * sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16,
+ UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+ for (interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS;
+ interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+ kLpcVecPerSegmentUb16 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData) {
+ int j, k, n, pos, pos2, posg, offsg, offs2;
+ int index_g[KLT_ORDER_GAIN];
+ int index_ovr_g[KLT_ORDER_GAIN];
+ double tmpcoeffs_g[KLT_ORDER_GAIN];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN];
+ double sum;
+ /* log gains, mean removal and scaling */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offsg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+ pos2 += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform. */
+ offsg = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+ pos += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Quantize coefficients. */
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ /* Get index. */
+ pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+ index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+ if (index_g[k] < 0) {
+ index_g[k] = 0;
+ } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+ /* Find quantization levels for coefficients. */
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+
+ /* Save data for creation of multiple bit streams. */
+ encData->LPCindex_g[KLT_ORDER_GAIN * encData->startIdx + k] = index_g[k];
+ }
+
+ /* Entropy coding of quantization indices - gain. */
+ WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain,
+ KLT_ORDER_GAIN);
+
+ /* Find quantization levels for coefficients. */
+ /* Left transform. */
+ offsg = 0;
+ posg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n = 0; n < LPC_GAIN_ORDER; n++)
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+ tmpcoeffs2_g[posg++] = sum;
+ offs2 += LPC_GAIN_ORDER;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform, transpose matrix. */
+ offsg = 0;
+ posg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+ pos += LPC_GAIN_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+
+ /* Scaling, mean addition, and gain restoration. */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ sum += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef_lo[k * (LPC_LOBAND_ORDER + 1)] = exp(sum);
+ pos++;
+ posg++;
+ sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ sum += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef_hi[k * (LPC_HIBAND_ORDER + 1)] = exp(sum);
+ pos++;
+ posg++;
+ }
+
+}
+
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains, Bitstr* streamdata,
+ int* lpcGainIndex) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+ WebRtcIsac_DecorrelateLPGain(lpGains, U);
+ WebRtcIsac_QuantizeLpcGain(U, idx);
+ /* Store the index for re-encoding for FEC. */
+ memcpy(lpcGainIndex, idx, UB_LPC_GAIN_DIM * sizeof(int));
+ WebRtcIsac_CorrelateLpcGain(U, lpGains);
+ WebRtcIsac_AddMeanToLinearDomain(lpGains);
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+ UB_LPC_GAIN_DIM);
+}
+
+
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+ WebRtcIsac_DecorrelateLPGain(lpGains, U);
+ WebRtcIsac_QuantizeLpcGain(U, idx);
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+ UB_LPC_GAIN_DIM);
+}
+
+
+
+WebRtc_Word16 WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ int err;
+ err = WebRtcIsac_DecHistOneStepMulti(idx, streamdata,
+ WebRtcIsac_kLpcGainCdfMat,
+ WebRtcIsac_kLpcGainEntropySearch,
+ UB_LPC_GAIN_DIM);
+ if (err < 0) {
+ return -1;
+ }
+ WebRtcIsac_DequantizeLpcGain(idx, U);
+ WebRtcIsac_CorrelateLpcGain(U, lpGains);
+ WebRtcIsac_AddMeanToLinearDomain(lpGains);
+ return 0;
+}
+
+
+
+/* decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, WebRtc_Word16* RCQ15) {
+ int k, err;
+ int index[AR_ORDER];
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsac_DecHistOneStepMulti(index, streamdata,
+ WebRtcIsac_kQArRcCdfPtr,
+ WebRtcIsac_kQArRcInitIndex, AR_ORDER);
+ if (err < 0)
+ return err;
+
+ /* find quantization levels for reflection coefficients */
+ for (k = 0; k < AR_ORDER; k++) {
+ RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+ }
+ return 0;
+}
+
+
+/* quantize & code RC */
+void WebRtcIsac_EncodeRc(WebRtc_Word16* RCQ15, Bitstr* streamdata) {
+ int k;
+ int index[AR_ORDER];
+
+ /* quantize reflection coefficients (add noise feedback?) */
+ for (k = 0; k < AR_ORDER; k++) {
+ index[k] = WebRtcIsac_kQArRcInitIndex[k];
+
+ if (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k]]) {
+ while (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1]) {
+ index[k]++;
+ }
+ } else {
+ while (RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ;
+ }
+ RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+ }
+
+ /* entropy coding of quantization indices */
+ WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER);
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, WebRtc_Word32* gainQ10) {
+ int index, err;
+
+ /* entropy decoding of quantization index */
+ err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata,
+ WebRtcIsac_kQGainCdf_ptr,
+ WebRtcIsac_kQGainInitIndex, 1);
+ if (err < 0) {
+ return err;
+ }
+ /* find quantization level */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+ return 0;
+}
+
+
+/* quantize & code squared Gain */
+int WebRtcIsac_EncodeGain2(WebRtc_Word32* gainQ10, Bitstr* streamdata) {
+ int index;
+
+ /* find quantization index */
+ index = WebRtcIsac_kQGainInitIndex[0];
+ if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index]) {
+ while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1]) {
+ index++;
+ }
+ } else {
+ while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ;
+ }
+ /* De-quantize */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+
+ /* entropy coding of quantization index */
+ WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1);
+ return 0;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata,
+ WebRtc_Word16* PitchGains_Q12) {
+ int index_comb, err;
+ const WebRtc_UWord16* WebRtcIsac_kQPitchGainCdf_ptr[1];
+
+ /* Entropy decoding of quantization indices */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata,
+ WebRtcIsac_kQPitchGainCdf_ptr,
+ WebRtcIsac_kQCdfTableSizeGain, 1);
+ /* Error check, Q_mean_Gain.. tables are of size 144 */
+ if ((err < 0) || (index_comb < 0) || (index_comb > 144)) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+ }
+ /* De-quantize back to pitch gains by table look-up. */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+ return 0;
+}
+
+
+/* Quantize & code Pitch Gains. */
+void WebRtcIsac_EncodePitchGain(WebRtc_Word16* PitchGains_Q12,
+ Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData) {
+ int k, j;
+ double C;
+ double S[PITCH_SUBFRAMES];
+ int index[3];
+ int index_comb;
+ const WebRtc_UWord16* WebRtcIsac_kQPitchGainCdf_ptr[1];
+ double PitchGains[PITCH_SUBFRAMES] = {0, 0, 0, 0};
+
+ /* Take the asin. */
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ S[k] = asin(PitchGains[k]);
+ }
+
+ /* Find quantization index; only for the first three
+ * transform coefficients. */
+ for (k = 0; k < 3; k++) {
+ /* transform */
+ C = 0.0;
+ for (j = 0; j < PITCH_SUBFRAMES; j++) {
+ C += WebRtcIsac_kTransform[k][j] * S[j];
+ }
+ /* Quantize */
+ index[k] = WebRtcIsac_lrint(C / PITCH_GAIN_STEPSIZE);
+
+ /* Check that the index is not outside the boundaries of the table. */
+ if (index[k] < WebRtcIsac_kIndexLowerLimitGain[k]) {
+ index[k] = WebRtcIsac_kIndexLowerLimitGain[k];
+ } else if (index[k] > WebRtcIsac_kIndexUpperLimitGain[k]) {
+ index[k] = WebRtcIsac_kIndexUpperLimitGain[k];
+ }
+ index[k] -= WebRtcIsac_kIndexLowerLimitGain[k];
+ }
+
+ /* Calculate unique overall index. */
+ index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] +
+ WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2];
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+
+ /* entropy coding of quantization pitch gains */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(streamdata, &index_comb,
+ WebRtcIsac_kQPitchGainCdf_ptr, 1);
+ encData->pitchGain_index[encData->startIdx] = index_comb;
+}
+
+
+
+/* Pitch LAG */
+/* Decode & de-quantize Pitch Lags. */
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata, WebRtc_Word16* PitchGain_Q12,
+ double* PitchLags) {
+ int k, err;
+ double StepSize;
+ double C;
+ int index[PITCH_SUBFRAMES];
+ double mean_gain;
+ const double* mean_val2, *mean_val3, *mean_val4;
+ const WebRtc_Word16* lower_limit;
+ const WebRtc_UWord16* init_index;
+ const WebRtc_UWord16* cdf_size;
+ const WebRtc_UWord16** cdf;
+ double PitchGain[4] = {0, 0, 0, 0};
+
+ /* compute mean pitch gain */
+ mean_gain = 0.0;
+ for (k = 0; k < 4; k++) {
+ PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+ mean_gain += PitchGain[k];
+ }
+ mean_gain /= 4.0;
+
+ /* voicing classification. */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ init_index = WebRtcIsac_kQInitIndexLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ init_index = WebRtcIsac_kQInitIndexLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ init_index = WebRtcIsac_kQInitIndexLagHi;
+ }
+
+ /* Entropy decoding of quantization indices. */
+ err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+ if ((err < 0) || (index[0] < 0)) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+ }
+ err = WebRtcIsac_DecHistOneStepMulti(index + 1, streamdata, cdf + 1,
+ init_index, 3);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+ }
+
+ /* Unquantize back to transform coefficients and do the inverse transform:
+ * S = T'*C. */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+ }
+ C = mean_val2[index[1]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+ }
+ C = mean_val3[index[2]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+ }
+ C = mean_val4[index[3]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+ }
+ return 0;
+}
+
+
+
+/* Quantize & code pitch lags. */
+void WebRtcIsac_EncodePitchLag(double* PitchLags, WebRtc_Word16* PitchGain_Q12,
+ Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData) {
+ int k, j;
+ double StepSize;
+ double C;
+ int index[PITCH_SUBFRAMES];
+ double mean_gain;
+ const double* mean_val2, *mean_val3, *mean_val4;
+ const WebRtc_Word16* lower_limit, *upper_limit;
+ const WebRtc_UWord16** cdf;
+ double PitchGain[4] = {0, 0, 0, 0};
+
+ /* compute mean pitch gain */
+ mean_gain = 0.0;
+ for (k = 0; k < 4; k++) {
+ PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+ mean_gain += PitchGain[k];
+ }
+ mean_gain /= 4.0;
+
+ /* Save data for creation of multiple bit streams */
+ encData->meanGain[encData->startIdx] = mean_gain;
+
+ /* Voicing classification. */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ upper_limit = WebRtcIsac_kQindexUpperLimitLagHi;
+ }
+
+ /* find quantization index */
+ for (k = 0; k < 4; k++) {
+ /* transform */
+ C = 0.0;
+ for (j = 0; j < PITCH_SUBFRAMES; j++) {
+ C += WebRtcIsac_kTransform[k][j] * PitchLags[j];
+ }
+ /* quantize */
+ index[k] = WebRtcIsac_lrint(C / StepSize);
+
+ /* check that the index is not outside the boundaries of the table */
+ if (index[k] < lower_limit[k]) {
+ index[k] = lower_limit[k];
+ } else if (index[k] > upper_limit[k]) index[k] = upper_limit[k]; {
+ index[k] -= lower_limit[k];
+ }
+ /* Save data for creation of multiple bit streams */
+ encData->pitchIndex[PITCH_SUBFRAMES * encData->startIdx + k] = index[k];
+ }
+
+ /* Un-quantize back to transform coefficients and do the inverse transform:
+ * S = T'*C */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+ }
+ C = mean_val2[index[1]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+ }
+ C = mean_val3[index[2]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+ }
+ C = mean_val4[index[3]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+ }
+ /* entropy coding of quantization pitch lags */
+ WebRtcIsac_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+}
+
+
+
+/* Routines for in-band signaling of bandwidth estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const WebRtc_UWord16 WebRtcIsac_kFrameLengthCdf[4] = {
+ 0, 21845, 43690, 65535 };
+
+/* pointer to cdf array for frame length indicator */
+const WebRtc_UWord16* WebRtcIsac_kFrameLengthCdf_ptr[1] = {
+ WebRtcIsac_kFrameLengthCdf };
+
+/* initial cdf index for decoder of frame length indicator */
+const WebRtc_UWord16 WebRtcIsac_kFrameLengthInitIndex[1] = { 1 };
+
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, WebRtc_Word16* framesamples) {
+ int frame_mode, err;
+ err = 0;
+ /* entropy decoding of frame length [1:30ms,2:60ms] */
+ err = WebRtcIsac_DecHistOneStepMulti(&frame_mode, streamdata,
+ WebRtcIsac_kFrameLengthCdf_ptr,
+ WebRtcIsac_kFrameLengthInitIndex, 1);
+ if (err < 0)
+ return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
+
+ switch (frame_mode) {
+ case 1:
+ *framesamples = 480; /* 30ms */
+ break;
+ case 2:
+ *framesamples = 960; /* 60ms */
+ break;
+ default:
+ err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
+ }
+ return err;
+}
+
+int WebRtcIsac_EncodeFrameLen(WebRtc_Word16 framesamples, Bitstr* streamdata) {
+ int frame_mode, status;
+
+ status = 0;
+ frame_mode = 0;
+ /* entropy coding of frame length [1:480 samples,2:960 samples] */
+ switch (framesamples) {
+ case 480:
+ frame_mode = 1;
+ break;
+ case 960:
+ frame_mode = 2;
+ break;
+ default:
+ status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
+ }
+
+ if (status < 0)
+ return status;
+
+ WebRtcIsac_EncHistMulti(streamdata, &frame_mode,
+ WebRtcIsac_kFrameLengthCdf_ptr, 1);
+ return status;
+}
+
+/* cdf array for estimated bandwidth */
+static const WebRtc_UWord16 kBwCdf[25] = {
+ 0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
+ 32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
+ 62804, 65535 };
+
+/* pointer to cdf array for estimated bandwidth */
+static const WebRtc_UWord16* kBwCdfPtr[1] = { kBwCdf };
+
+/* initial cdf index for decoder of estimated bandwidth*/
+static const WebRtc_UWord16 kBwInitIndex[1] = { 7 };
+
+
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, WebRtc_Word16* BWno) {
+ int BWno32, err;
+
+ /* entropy decoding of sender's BW estimation [0..23] */
+ err = WebRtcIsac_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr,
+ kBwInitIndex, 1);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+ }
+ *BWno = (WebRtc_Word16)BWno32;
+ return err;
+}
+
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata) {
+ /* entropy encoding of receiver's BW estimation [0..23] */
+ WebRtcIsac_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+}
+
+
+/* estimate code length of LPC Coef */
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo, double* LPCCoef_hi,
+ int* index_g) {
+ int j, k, n, pos, pos2, posg, offsg, offs2;
+ int index_ovr_g[KLT_ORDER_GAIN];
+ double tmpcoeffs_g[KLT_ORDER_GAIN];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN];
+ double sum;
+
+ /* log gains, mean removal and scaling */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offsg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+ pos2 += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform. */
+ offsg = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+ pos += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offsg += LPC_GAIN_ORDER;
+ }
+
+
+ /* quantize coefficients */
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ /* Get index. */
+ pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+ index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+ if (index_g[k] < 0) {
+ index_g[k] = 0;
+ } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+ /* find quantization levels for coefficients */
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+ }
+}
+
+
+/* Decode & de-quantize LPC Coefficients. */
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata, double* lpcVecs,
+ double* percepFilterGains,
+ WebRtc_Word16 bandwidth) {
+ int index_s[KLT_ORDER_SHAPE];
+
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int err;
+
+ /* Entropy decoding of quantization indices. */
+ switch (bandwidth) {
+ case isac12kHz: {
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb12,
+ WebRtcIsac_kLpcShapeEntropySearchUb12, UB_LPC_ORDER *
+ UB_LPC_VEC_PER_FRAME);
+ break;
+ }
+ case isac16kHz: {
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb16,
+ WebRtcIsac_kLpcShapeEntropySearchUb16, UB_LPC_ORDER *
+ UB16_LPC_VEC_PER_FRAME);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if (err < 0) {
+ return err;
+ }
+
+ WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth);
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+ WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata);
+
+ if (bandwidth == isac16kHz) {
+ /* Decode another set of Gains. */
+ WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata);
+ }
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+ Bitstr* streamData) {
+ int bandwidthMode;
+ switch (bandwidth) {
+ case isac12kHz: {
+ bandwidthMode = 0;
+ break;
+ }
+ case isac16kHz: {
+ bandwidthMode = 1;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_ENCODER_BANDWIDTH;
+ }
+ WebRtcIsac_EncHistMulti(streamData, &bandwidthMode, kOneBitEqualProbCdf_ptr,
+ 1);
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+ enum ISACBandwidth* bandwidth) {
+ int bandwidthMode;
+ if (WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+ switch (bandwidthMode) {
+ case 0: {
+ *bandwidth = isac12kHz;
+ break;
+ }
+ case 1: {
+ *bandwidth = isac16kHz;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER;
+ }
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_EncodeJitterInfo(WebRtc_Word32 jitterIndex,
+ Bitstr* streamData) {
+ /* This is to avoid LINUX warning until we change 'int' to 'Word32'. */
+ int intVar;
+
+ if ((jitterIndex < 0) || (jitterIndex > 1)) {
+ return -1;
+ }
+ intVar = (int)(jitterIndex);
+ /* Use the same CDF table as for bandwidth
+ * both take two values with equal probability.*/
+ WebRtcIsac_EncHistMulti(streamData, &intVar, kOneBitEqualProbCdf_ptr, 1);
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_DecodeJitterInfo(Bitstr* streamData,
+ WebRtc_Word32* jitterInfo) {
+ int intVar;
+ /* Use the same CDF table as for bandwidth
+ * both take two values with equal probability. */
+ if (WebRtcIsac_DecHistOneStepMulti(&intVar, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+ *jitterInfo = (WebRtc_Word16)(intVar);
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.h b/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
new file mode 100644
index 0000000..1a46953
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file declares all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+
+#include "settings.h"
+#include "structs.h"
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpec()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ * - AvgPitchGain_Q12 : average pitch-gain of the frame. This is only
+ * relevant for 0-4 kHz band, and the input value is
+ * not used in other bands.
+ * - band : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ * - *fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * - *fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata, WebRtc_Word16 AvgPitchGain_Q12,
+ enum ISACBand band, double* fr, double* fi);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpec()
+ * Encode real and imaginary part of the DFT coefficients into the given
+ * bit-stream.
+ *
+ * Input:
+ * - *fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * - *fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ * - AvgPitchGain_Q12 : average pitch-gain of the frame. This is only
+ * relevant for 0-4 kHz band, and the input value is
+ * not used in other bands.
+ * - band : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpec(const WebRtc_Word16* fr, const WebRtc_Word16* fi,
+ WebRtc_Word16 AvgPitchGain_Q12, enum ISACBand band,
+ Bitstr* streamdata);
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef);
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata, double* lpcVecs,
+ double* percepFilterGains,
+ WebRtc_Word16 bandwidth);
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata, double* LPCCoef_lo,
+ double* LPCCoef_hi);
+
+/* quantize & code LPC Coef */
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata, ISAC_SaveEncData_t* encData);
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcUB()
+ * Encode LPC parameters, given as A-polynomial, of upper-band. The encoding
+ * is performed in LAR domain.
+ * For the upper-band, we compute and encode LPC of some sub-frames, LPC of
+ * other sub-frames are computed by linear interpolation, in LAR domain. This
+ * function performs the interpolation and returns the LPC of all sub-frames.
+ *
+ * Inputs:
+ * - lpcCoef : a buffer containing A-polynomials of sub-frames
+ * (excluding first coefficient that is 1).
+ * - bandwidth : specifies if the codec is operating at 0-12 kHz
+ * or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a structure containing the encoded
+ * data and the parameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - interpolLPCCoeff : Decoded and interpolated LPC (A-polynomial)
+ * of all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeLpcUB(double* lpcCoeff, Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ WebRtc_Word16 bandwidth,
+ ISACUBSaveEncDataStruct* encData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeInterpolLpcUb()
+ * Decode LPC coefficients and interpolate to get the coefficients fo all
+ * sub-frmaes.
+ *
+ * Inputs:
+ * - bandwidth : spepecifies if the codec is in 0-12 kHz or
+ * 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - percepFilterParam : Decoded and interpolated LPC (A-polynomial) of
+ * all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+ double* percepFilterParam,
+ WebRtc_Word16 bandwidth);
+
+/* Decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, WebRtc_Word16* RCQ15);
+
+/* Quantize & code RC */
+void WebRtcIsac_EncodeRc(WebRtc_Word16* RCQ15, Bitstr* streamdata);
+
+/* Decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, WebRtc_Word32* Gain2);
+
+/* Quantize & code squared Gain (input is squared gain) */
+int WebRtcIsac_EncodeGain2(WebRtc_Word32* gain2, Bitstr* streamdata);
+
+void WebRtcIsac_EncodePitchGain(WebRtc_Word16* PitchGains_Q12,
+ Bitstr* streamdata,
+ ISAC_SaveEncData_t* encData);
+
+void WebRtcIsac_EncodePitchLag(double* PitchLags, WebRtc_Word16* PitchGain_Q12,
+ Bitstr* streamdata, ISAC_SaveEncData_t* encData);
+
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata,
+ WebRtc_Word16* PitchGain_Q12);
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata, WebRtc_Word16* PitchGain_Q12,
+ double* PitchLag);
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, WebRtc_Word16* framelength);
+int WebRtcIsac_EncodeFrameLen(WebRtc_Word16 framelength, Bitstr* streamdata);
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, WebRtc_Word16* BWno);
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata);
+
+/* Step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC);
+
+/* Step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a);
+
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo, double* LPCCoef_hi,
+ int* index_g);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Encode LPC gains of sub-Frames.
+ *
+ * Input/outputs:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded. The input values are
+ * overwritten by the quantized values.
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpcGainIndex : quantization indices for lpc gains, these will
+ * be stored to be used for FEC.
+ */
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains, Bitstr* streamdata,
+ int* lpcGainIndex);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Store LPC gains of sub-Frames in 'streamdata'.
+ *
+ * Input:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded.
+ * Input/outputs:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ */
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeLpcGainUb()
+ * Decode the LPC gain of sub-frames.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpGains : a buffer where decoded LPC gians will be stored.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeBandwidth()
+ * Encode if the bandwidth of encoded audio is 0-12 kHz or 0-16 kHz.
+ *
+ * Input:
+ * - bandwidth : an enumerator specifying if the codec in is
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+ Bitstr* streamData);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeBandwidth()
+ * Decode the bandwidth of the encoded audio, i.e. if the bandwidth is 0-12 kHz
+ * or 0-16 kHz.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - bandwidth : an enumerator specifying if the codec is in
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+ enum ISACBandwidth* bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Input:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeJitterInfo(WebRtc_Word32 jitterIndex,
+ Bitstr* streamData);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeJitterInfo(Bitstr* streamData,
+ WebRtc_Word32* jitterInfo);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/fft.c b/src/modules/audio_coding/codecs/isac/main/source/fft.c
new file mode 100644
index 0000000..c824798
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/fft.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
+ * Queen's Univ at Kingston (Canada)
+ *
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose without fee is hereby granted, provided that this
+ * entire notice is included in all copies of any software which is
+ * or includes a copy or modification of this software and in all
+ * copies of the supporting documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
+ * UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
+ * KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * All of which is to say that you can do what you like with this
+ * source code provided you don't try to sell it as your own and you
+ * include an unaltered copy of this message (including the
+ * copyright).
+ *
+ * It is also implicitly understood that bug fixes and improvements
+ * should make their way back to the general Internet community so
+ * that everyone benefits.
+ *
+ * Changes:
+ * Trivial type modifications by the WebRTC authors.
+ */
+
+
+/*
+ * File:
+ * WebRtcIsac_Fftn.c
+ *
+ * Public:
+ * WebRtcIsac_Fftn / fftnf ();
+ *
+ * Private:
+ * WebRtcIsac_Fftradix / fftradixf ();
+ *
+ * Descript:
+ * multivariate complex Fourier transform, computed in place
+ * using mixed-radix Fast Fourier Transform algorithm.
+ *
+ * Fortran code by:
+ * RC Singleton, Stanford Research Institute, Sept. 1968
+ *
+ * translated by f2c (version 19950721).
+ *
+ * int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[],
+ * int iSign, double scaling);
+ *
+ * NDIM = the total number dimensions
+ * DIMS = a vector of array sizes
+ * if NDIM is zero then DIMS must be zero-terminated
+ *
+ * RE and IM hold the real and imaginary components of the data, and return
+ * the resulting real and imaginary Fourier coefficients. Multidimensional
+ * data *must* be allocated contiguously. There is no limit on the number
+ * of dimensions.
+ *
+ * ISIGN = the sign of the complex exponential (ie, forward or inverse FFT)
+ * the magnitude of ISIGN (normally 1) is used to determine the
+ * correct indexing increment (see below).
+ *
+ * SCALING = normalizing constant by which the final result is *divided*
+ * if SCALING == -1, normalize by total dimension of the transform
+ * if SCALING < -1, normalize by the square-root of the total dimension
+ *
+ * example:
+ * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
+ *
+ * int dims[3] = {n1,n2,n3}
+ * WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling);
+ *
+ *-----------------------------------------------------------------------*
+ * int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass,
+ * size_t nSpan, int iSign, size_t max_factors,
+ * size_t max_perm);
+ *
+ * RE, IM - see above documentation
+ *
+ * Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must
+ * be called once for each dimension, but the calls may be in any order.
+ *
+ * NTOTAL = the total number of complex data values
+ * NPASS = the dimension of the current variable
+ * NSPAN/NPASS = the spacing of consecutive data values while indexing the
+ * current variable
+ * ISIGN - see above documentation
+ *
+ * example:
+ * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
+ *
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1, n1, 1, maxf, maxp);
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2, n1*n2, 1, maxf, maxp);
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp);
+ *
+ * single-variate transform,
+ * NTOTAL = N = NSPAN = (number of complex data values),
+ *
+ * WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp);
+ *
+ * The data can also be stored in a single array with alternating real and
+ * imaginary parts, the magnitude of ISIGN is changed to 2 to give correct
+ * indexing increment, and data [0] and data [1] used to pass the initial
+ * addresses for the sequences of real and imaginary values,
+ *
+ * example:
+ * REAL data [2*NTOTAL];
+ * WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp);
+ *
+ * for temporary allocation:
+ *
+ * MAX_FACTORS >= the maximum prime factor of NPASS
+ * MAX_PERM >= the number of prime factors of NPASS. In addition,
+ * if the square-free portion K of NPASS has two or more prime
+ * factors, then MAX_PERM >= (K-1)
+ *
+ * storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS
+ * has more than one square-free factor, the product of the square-free
+ * factors must be <= 210 array storage for maximum prime factor of 23 the
+ * following two constants should agree with the array dimensions.
+ *
+ *----------------------------------------------------------------------*/
+#include "fft.h"
+
+#include <stdlib.h>
+#include <math.h>
+
+
+
+/* double precision routine */
+static int
+WebRtcIsac_Fftradix (double Re[], double Im[],
+ size_t nTotal, size_t nPass, size_t nSpan, int isign,
+ int max_factors, unsigned int max_perm,
+ FFTstr *fftstate);
+
+
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846264338327950288
+#endif
+
+#ifndef SIN60
+# define SIN60 0.86602540378443865 /* sin(60 deg) */
+# define COS72 0.30901699437494742 /* cos(72 deg) */
+# define SIN72 0.95105651629515357 /* sin(72 deg) */
+#endif
+
+# define REAL double
+# define FFTN WebRtcIsac_Fftn
+# define FFTNS "fftn"
+# define FFTRADIX WebRtcIsac_Fftradix
+# define FFTRADIXS "fftradix"
+
+
+int WebRtcIsac_Fftns(unsigned int ndim, const int dims[],
+ double Re[],
+ double Im[],
+ int iSign,
+ double scaling,
+ FFTstr *fftstate)
+{
+
+ size_t nSpan, nPass, nTotal;
+ unsigned int i;
+ int ret, max_factors, max_perm;
+
+ /*
+ * tally the number of elements in the data array
+ * and determine the number of dimensions
+ */
+ nTotal = 1;
+ if (ndim && dims [0])
+ {
+ for (i = 0; i < ndim; i++)
+ {
+ if (dims [i] <= 0)
+ {
+ return -1;
+ }
+ nTotal *= dims [i];
+ }
+ }
+ else
+ {
+ ndim = 0;
+ for (i = 0; dims [i]; i++)
+ {
+ if (dims [i] <= 0)
+ {
+ return -1;
+ }
+ nTotal *= dims [i];
+ ndim++;
+ }
+ }
+
+ /* determine maximum number of factors and permuations */
+#if 1
+ /*
+ * follow John Beale's example, just use the largest dimension and don't
+ * worry about excess allocation. May be someone else will do it?
+ */
+ max_factors = max_perm = 1;
+ for (i = 0; i < ndim; i++)
+ {
+ nSpan = dims [i];
+ if ((int)nSpan > max_factors)
+ {
+ max_factors = (int)nSpan;
+ }
+ if ((int)nSpan > max_perm)
+ {
+ max_perm = (int)nSpan;
+ }
+ }
+#else
+ /* use the constants used in the original Fortran code */
+ max_factors = 23;
+ max_perm = 209;
+#endif
+ /* loop over the dimensions: */
+ nPass = 1;
+ for (i = 0; i < ndim; i++)
+ {
+ nSpan = dims [i];
+ nPass *= nSpan;
+ ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign,
+ max_factors, max_perm, fftstate);
+ /* exit, clean-up already done */
+ if (ret)
+ return ret;
+ }
+
+ /* Divide through by the normalizing constant: */
+ if (scaling && scaling != 1.0)
+ {
+ if (iSign < 0) iSign = -iSign;
+ if (scaling < 0.0)
+ {
+ scaling = (double)nTotal;
+ if (scaling < -1.0)
+ scaling = sqrt (scaling);
+ }
+ scaling = 1.0 / scaling; /* multiply is often faster */
+ for (i = 0; i < nTotal; i += iSign)
+ {
+ Re [i] *= scaling;
+ Im [i] *= scaling;
+ }
+ }
+ return 0;
+}
+
+/*
+ * singleton's mixed radix routine
+ *
+ * could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's
+ * possible to make this a standalone function
+ */
+
+static int FFTRADIX (REAL Re[],
+ REAL Im[],
+ size_t nTotal,
+ size_t nPass,
+ size_t nSpan,
+ int iSign,
+ int max_factors,
+ unsigned int max_perm,
+ FFTstr *fftstate)
+{
+ int ii, mfactor, kspan, ispan, inc;
+ int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt;
+
+
+ REAL radf;
+ REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp;
+ REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp;
+
+ REAL *Rtmp = NULL; /* temp space for real part*/
+ REAL *Itmp = NULL; /* temp space for imaginary part */
+ REAL *Cos = NULL; /* Cosine values */
+ REAL *Sin = NULL; /* Sine values */
+
+ REAL s60 = SIN60; /* sin(60 deg) */
+ REAL c72 = COS72; /* cos(72 deg) */
+ REAL s72 = SIN72; /* sin(72 deg) */
+ REAL pi2 = M_PI; /* use PI first, 2 PI later */
+
+
+ fftstate->SpaceAlloced = 0;
+ fftstate->MaxPermAlloced = 0;
+
+
+ // initialize to avoid warnings
+ k3 = c2 = c3 = s2 = s3 = 0.0;
+
+ if (nPass < 2)
+ return 0;
+
+ /* allocate storage */
+ if (fftstate->SpaceAlloced < max_factors * sizeof (REAL))
+ {
+#ifdef SUN_BROKEN_REALLOC
+ if (!fftstate->SpaceAlloced) /* first time */
+ {
+ fftstate->SpaceAlloced = max_factors * sizeof (REAL);
+ }
+ else
+ {
+#endif
+ fftstate->SpaceAlloced = max_factors * sizeof (REAL);
+#ifdef SUN_BROKEN_REALLOC
+ }
+#endif
+ }
+ else
+ {
+ /* allow full use of alloc'd space */
+ max_factors = fftstate->SpaceAlloced / sizeof (REAL);
+ }
+ if (fftstate->MaxPermAlloced < max_perm)
+ {
+#ifdef SUN_BROKEN_REALLOC
+ if (!fftstate->MaxPermAlloced) /* first time */
+ else
+#endif
+ fftstate->MaxPermAlloced = max_perm;
+ }
+ else
+ {
+ /* allow full use of alloc'd space */
+ max_perm = fftstate->MaxPermAlloced;
+ }
+ if (fftstate->Tmp0 == NULL || fftstate->Tmp1 == NULL || fftstate->Tmp2 == NULL || fftstate->Tmp3 == NULL
+ || fftstate->Perm == NULL) {
+ return -1;
+ }
+
+ /* assign pointers */
+ Rtmp = (REAL *) fftstate->Tmp0;
+ Itmp = (REAL *) fftstate->Tmp1;
+ Cos = (REAL *) fftstate->Tmp2;
+ Sin = (REAL *) fftstate->Tmp3;
+
+ /*
+ * Function Body
+ */
+ inc = iSign;
+ if (iSign < 0) {
+ s72 = -s72;
+ s60 = -s60;
+ pi2 = -pi2;
+ inc = -inc; /* absolute value */
+ }
+
+ /* adjust for strange increments */
+ nt = inc * (int)nTotal;
+ ns = inc * (int)nSpan;
+ kspan = ns;
+
+ nn = nt - inc;
+ jc = ns / (int)nPass;
+ radf = pi2 * (double) jc;
+ pi2 *= 2.0; /* use 2 PI from here on */
+
+ ii = 0;
+ jf = 0;
+ /* determine the factors of n */
+ mfactor = 0;
+ k = (int)nPass;
+ while (k % 16 == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = 4;
+ k /= 16;
+ }
+ j = 3;
+ jj = 9;
+ do {
+ while (k % jj == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = j;
+ k /= jj;
+ }
+ j += 2;
+ jj = j * j;
+ } while (jj <= k);
+ if (k <= 4) {
+ kt = mfactor;
+ fftstate->factor [mfactor] = k;
+ if (k != 1)
+ mfactor++;
+ } else {
+ if (k - (k / 4 << 2) == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = 2;
+ k /= 4;
+ }
+ kt = mfactor;
+ j = 2;
+ do {
+ if (k % j == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = j;
+ k /= j;
+ }
+ j = ((j + 1) / 2 << 1) + 1;
+ } while (j <= k);
+ }
+ if (kt) {
+ j = kt;
+ do {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = fftstate->factor [j - 1];
+ j--;
+ } while (j);
+ }
+
+ /* test that mfactors is in range */
+ if (mfactor > NFACTOR)
+ {
+ return -1;
+ }
+
+ /* compute fourier transform */
+ for (;;) {
+ sd = radf / (double) kspan;
+ cd = sin(sd);
+ cd = 2.0 * cd * cd;
+ sd = sin(sd + sd);
+ kk = 0;
+ ii++;
+
+ switch (fftstate->factor [ii - 1]) {
+ case 2:
+ /* transform for factor of 2 (including rotation factor) */
+ kspan /= 2;
+ k1 = kspan + 2;
+ do {
+ do {
+ k2 = kk + kspan;
+ ak = Re [k2];
+ bk = Im [k2];
+ Re [k2] = Re [kk] - ak;
+ Im [k2] = Im [kk] - bk;
+ Re [kk] += ak;
+ Im [kk] += bk;
+ kk = k2 + kspan;
+ } while (kk < nn);
+ kk -= nn;
+ } while (kk < jc);
+ if (kk >= kspan)
+ goto Permute_Results_Label; /* exit infinite loop */
+ do {
+ c1 = 1.0 - cd;
+ s1 = sd;
+ do {
+ do {
+ do {
+ k2 = kk + kspan;
+ ak = Re [kk] - Re [k2];
+ bk = Im [kk] - Im [k2];
+ Re [kk] += Re [k2];
+ Im [kk] += Im [k2];
+ Re [k2] = c1 * ak - s1 * bk;
+ Im [k2] = s1 * ak + c1 * bk;
+ kk = k2 + kspan;
+ } while (kk < (nt-1));
+ k2 = kk - nt;
+ c1 = -c1;
+ kk = k1 - k2;
+ } while (kk > k2);
+ ak = c1 - (cd * c1 + sd * s1);
+ s1 = sd * c1 - cd * s1 + s1;
+ c1 = 2.0 - (ak * ak + s1 * s1);
+ s1 *= c1;
+ c1 *= ak;
+ kk += jc;
+ } while (kk < k2);
+ k1 += inc + inc;
+ kk = (k1 - kspan + 1) / 2 + jc - 1;
+ } while (kk < (jc + jc));
+ break;
+
+ case 4: /* transform for factor of 4 */
+ ispan = kspan;
+ kspan /= 4;
+
+ do {
+ c1 = 1.0;
+ s1 = 0.0;
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ k3 = k2 + kspan;
+ akp = Re [kk] + Re [k2];
+ akm = Re [kk] - Re [k2];
+ ajp = Re [k1] + Re [k3];
+ ajm = Re [k1] - Re [k3];
+ bkp = Im [kk] + Im [k2];
+ bkm = Im [kk] - Im [k2];
+ bjp = Im [k1] + Im [k3];
+ bjm = Im [k1] - Im [k3];
+ Re [kk] = akp + ajp;
+ Im [kk] = bkp + bjp;
+ ajp = akp - ajp;
+ bjp = bkp - bjp;
+ if (iSign < 0) {
+ akp = akm + bjm;
+ bkp = bkm - ajm;
+ akm -= bjm;
+ bkm += ajm;
+ } else {
+ akp = akm - bjm;
+ bkp = bkm + ajm;
+ akm += bjm;
+ bkm -= ajm;
+ }
+ /* avoid useless multiplies */
+ if (s1 == 0.0) {
+ Re [k1] = akp;
+ Re [k2] = ajp;
+ Re [k3] = akm;
+ Im [k1] = bkp;
+ Im [k2] = bjp;
+ Im [k3] = bkm;
+ } else {
+ Re [k1] = akp * c1 - bkp * s1;
+ Re [k2] = ajp * c2 - bjp * s2;
+ Re [k3] = akm * c3 - bkm * s3;
+ Im [k1] = akp * s1 + bkp * c1;
+ Im [k2] = ajp * s2 + bjp * c2;
+ Im [k3] = akm * s3 + bkm * c3;
+ }
+ kk = k3 + kspan;
+ } while (kk < nt);
+
+ c2 = c1 - (cd * c1 + sd * s1);
+ s1 = sd * c1 - cd * s1 + s1;
+ c1 = 2.0 - (c2 * c2 + s1 * s1);
+ s1 *= c1;
+ c1 *= c2;
+ /* values of c2, c3, s2, s3 that will get used next time */
+ c2 = c1 * c1 - s1 * s1;
+ s2 = 2.0 * c1 * s1;
+ c3 = c2 * c1 - s2 * s1;
+ s3 = c2 * s1 + s2 * c1;
+ kk = kk - nt + jc;
+ } while (kk < kspan);
+ kk = kk - kspan + inc;
+ } while (kk < jc);
+ if (kspan == jc)
+ goto Permute_Results_Label; /* exit infinite loop */
+ break;
+
+ default:
+ /* transform for odd factors */
+#ifdef FFT_RADIX4
+ return -1;
+ break;
+#else /* FFT_RADIX4 */
+ k = fftstate->factor [ii - 1];
+ ispan = kspan;
+ kspan /= k;
+
+ switch (k) {
+ case 3: /* transform for factor of 3 (optional code) */
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ ak = Re [kk];
+ bk = Im [kk];
+ aj = Re [k1] + Re [k2];
+ bj = Im [k1] + Im [k2];
+ Re [kk] = ak + aj;
+ Im [kk] = bk + bj;
+ ak -= 0.5 * aj;
+ bk -= 0.5 * bj;
+ aj = (Re [k1] - Re [k2]) * s60;
+ bj = (Im [k1] - Im [k2]) * s60;
+ Re [k1] = ak - bj;
+ Re [k2] = ak + bj;
+ Im [k1] = bk + aj;
+ Im [k2] = bk - aj;
+ kk = k2 + kspan;
+ } while (kk < (nn - 1));
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+
+ case 5: /* transform for factor of 5 (optional code) */
+ c2 = c72 * c72 - s72 * s72;
+ s2 = 2.0 * c72 * s72;
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ k3 = k2 + kspan;
+ k4 = k3 + kspan;
+ akp = Re [k1] + Re [k4];
+ akm = Re [k1] - Re [k4];
+ bkp = Im [k1] + Im [k4];
+ bkm = Im [k1] - Im [k4];
+ ajp = Re [k2] + Re [k3];
+ ajm = Re [k2] - Re [k3];
+ bjp = Im [k2] + Im [k3];
+ bjm = Im [k2] - Im [k3];
+ aa = Re [kk];
+ bb = Im [kk];
+ Re [kk] = aa + akp + ajp;
+ Im [kk] = bb + bkp + bjp;
+ ak = akp * c72 + ajp * c2 + aa;
+ bk = bkp * c72 + bjp * c2 + bb;
+ aj = akm * s72 + ajm * s2;
+ bj = bkm * s72 + bjm * s2;
+ Re [k1] = ak - bj;
+ Re [k4] = ak + bj;
+ Im [k1] = bk + aj;
+ Im [k4] = bk - aj;
+ ak = akp * c2 + ajp * c72 + aa;
+ bk = bkp * c2 + bjp * c72 + bb;
+ aj = akm * s2 - ajm * s72;
+ bj = bkm * s2 - bjm * s72;
+ Re [k2] = ak - bj;
+ Re [k3] = ak + bj;
+ Im [k2] = bk + aj;
+ Im [k3] = bk - aj;
+ kk = k4 + kspan;
+ } while (kk < (nn-1));
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+
+ default:
+ if (k != jf) {
+ jf = k;
+ s1 = pi2 / (double) k;
+ c1 = cos(s1);
+ s1 = sin(s1);
+ if (jf > max_factors){
+ return -1;
+ }
+ Cos [jf - 1] = 1.0;
+ Sin [jf - 1] = 0.0;
+ j = 1;
+ do {
+ Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1;
+ Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1;
+ k--;
+ Cos [k - 1] = Cos [j - 1];
+ Sin [k - 1] = -Sin [j - 1];
+ j++;
+ } while (j < k);
+ }
+ do {
+ do {
+ k1 = kk;
+ k2 = kk + ispan;
+ ak = aa = Re [kk];
+ bk = bb = Im [kk];
+ j = 1;
+ k1 += kspan;
+ do {
+ k2 -= kspan;
+ j++;
+ Rtmp [j - 1] = Re [k1] + Re [k2];
+ ak += Rtmp [j - 1];
+ Itmp [j - 1] = Im [k1] + Im [k2];
+ bk += Itmp [j - 1];
+ j++;
+ Rtmp [j - 1] = Re [k1] - Re [k2];
+ Itmp [j - 1] = Im [k1] - Im [k2];
+ k1 += kspan;
+ } while (k1 < k2);
+ Re [kk] = ak;
+ Im [kk] = bk;
+ k1 = kk;
+ k2 = kk + ispan;
+ j = 1;
+ do {
+ k1 += kspan;
+ k2 -= kspan;
+ jj = j;
+ ak = aa;
+ bk = bb;
+ aj = 0.0;
+ bj = 0.0;
+ k = 1;
+ do {
+ k++;
+ ak += Rtmp [k - 1] * Cos [jj - 1];
+ bk += Itmp [k - 1] * Cos [jj - 1];
+ k++;
+ aj += Rtmp [k - 1] * Sin [jj - 1];
+ bj += Itmp [k - 1] * Sin [jj - 1];
+ jj += j;
+ if (jj > jf) {
+ jj -= jf;
+ }
+ } while (k < jf);
+ k = jf - j;
+ Re [k1] = ak - bj;
+ Im [k1] = bk + aj;
+ Re [k2] = ak + bj;
+ Im [k2] = bk - aj;
+ j++;
+ } while (j < k);
+ kk += ispan;
+ } while (kk < nn);
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+ }
+
+ /* multiply by rotation factor (except for factors of 2 and 4) */
+ if (ii == mfactor)
+ goto Permute_Results_Label; /* exit infinite loop */
+ kk = jc;
+ do {
+ c2 = 1.0 - cd;
+ s1 = sd;
+ do {
+ c1 = c2;
+ s2 = s1;
+ kk += kspan;
+ do {
+ do {
+ ak = Re [kk];
+ Re [kk] = c2 * ak - s2 * Im [kk];
+ Im [kk] = s2 * ak + c2 * Im [kk];
+ kk += ispan;
+ } while (kk < nt);
+ ak = s1 * s2;
+ s2 = s1 * c2 + c1 * s2;
+ c2 = c1 * c2 - ak;
+ kk = kk - nt + kspan;
+ } while (kk < ispan);
+ c2 = c1 - (cd * c1 + sd * s1);
+ s1 += sd * c1 - cd * s1;
+ c1 = 2.0 - (c2 * c2 + s1 * s1);
+ s1 *= c1;
+ c2 *= c1;
+ kk = kk - ispan + jc;
+ } while (kk < kspan);
+ kk = kk - kspan + jc + inc;
+ } while (kk < (jc + jc));
+ break;
+#endif /* FFT_RADIX4 */
+ }
+ }
+
+ /* permute the results to normal order---done in two stages */
+ /* permutation for square factors of n */
+Permute_Results_Label:
+ fftstate->Perm [0] = ns;
+ if (kt) {
+ k = kt + kt + 1;
+ if (mfactor < k)
+ k--;
+ j = 1;
+ fftstate->Perm [k] = jc;
+ do {
+ fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1];
+ fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1];
+ j++;
+ k--;
+ } while (j < k);
+ k3 = fftstate->Perm [k];
+ kspan = fftstate->Perm [1];
+ kk = jc;
+ k2 = kspan;
+ j = 1;
+ if (nPass != nTotal) {
+ /* permutation for multivariate transform */
+ Permute_Multi_Label:
+ do {
+ do {
+ k = kk + jc;
+ do {
+ /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
+ ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
+ bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
+ kk += inc;
+ k2 += inc;
+ } while (kk < (k-1));
+ kk += ns - jc;
+ k2 += ns - jc;
+ } while (kk < (nt-1));
+ k2 = k2 - nt + kspan;
+ kk = kk - nt + jc;
+ } while (k2 < (ns-1));
+ do {
+ do {
+ k2 -= fftstate->Perm [j - 1];
+ j++;
+ k2 = fftstate->Perm [j] + k2;
+ } while (k2 > fftstate->Perm [j - 1]);
+ j = 1;
+ do {
+ if (kk < (k2-1))
+ goto Permute_Multi_Label;
+ kk += jc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ } while (kk < (ns-1));
+ } else {
+ /* permutation for single-variate transform (optional code) */
+ Permute_Single_Label:
+ do {
+ /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
+ ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
+ bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
+ kk += inc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ do {
+ do {
+ k2 -= fftstate->Perm [j - 1];
+ j++;
+ k2 = fftstate->Perm [j] + k2;
+ } while (k2 >= fftstate->Perm [j - 1]);
+ j = 1;
+ do {
+ if (kk < k2)
+ goto Permute_Single_Label;
+ kk += inc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ } while (kk < (ns-1));
+ }
+ jc = k3;
+ }
+
+ if ((kt << 1) + 1 >= mfactor)
+ return 0;
+ ispan = fftstate->Perm [kt];
+ /* permutation for square-free factors of n */
+ j = mfactor - kt;
+ fftstate->factor [j] = 1;
+ do {
+ fftstate->factor [j - 1] *= fftstate->factor [j];
+ j--;
+ } while (j != kt);
+ kt++;
+ nn = fftstate->factor [kt - 1] - 1;
+ if (nn > (int) max_perm) {
+ return -1;
+ }
+ j = jj = 0;
+ for (;;) {
+ k = kt + 1;
+ k2 = fftstate->factor [kt - 1];
+ kk = fftstate->factor [k - 1];
+ j++;
+ if (j > nn)
+ break; /* exit infinite loop */
+ jj += kk;
+ while (jj >= k2) {
+ jj -= k2;
+ k2 = kk;
+ k++;
+ kk = fftstate->factor [k - 1];
+ jj += kk;
+ }
+ fftstate->Perm [j - 1] = jj;
+ }
+ /* determine the permutation cycles of length greater than 1 */
+ j = 0;
+ for (;;) {
+ do {
+ j++;
+ kk = fftstate->Perm [j - 1];
+ } while (kk < 0);
+ if (kk != j) {
+ do {
+ k = kk;
+ kk = fftstate->Perm [k - 1];
+ fftstate->Perm [k - 1] = -kk;
+ } while (kk != j);
+ k3 = kk;
+ } else {
+ fftstate->Perm [j - 1] = -j;
+ if (j == nn)
+ break; /* exit infinite loop */
+ }
+ }
+ max_factors *= inc;
+ /* reorder a and b, following the permutation cycles */
+ for (;;) {
+ j = k3 + 1;
+ nt -= ispan;
+ ii = nt - inc + 1;
+ if (nt < 0)
+ break; /* exit infinite loop */
+ do {
+ do {
+ j--;
+ } while (fftstate->Perm [j - 1] < 0);
+ jj = jc;
+ do {
+ kspan = jj;
+ if (jj > max_factors) {
+ kspan = max_factors;
+ }
+ jj -= kspan;
+ k = fftstate->Perm [j - 1];
+ kk = jc * k + ii + jj;
+ k1 = kk + kspan - 1;
+ k2 = 0;
+ do {
+ k2++;
+ Rtmp [k2 - 1] = Re [k1];
+ Itmp [k2 - 1] = Im [k1];
+ k1 -= inc;
+ } while (k1 != (kk-1));
+ do {
+ k1 = kk + kspan - 1;
+ k2 = k1 - jc * (k + fftstate->Perm [k - 1]);
+ k = -fftstate->Perm [k - 1];
+ do {
+ Re [k1] = Re [k2];
+ Im [k1] = Im [k2];
+ k1 -= inc;
+ k2 -= inc;
+ } while (k1 != (kk-1));
+ kk = k2 + 1;
+ } while (k != j);
+ k1 = kk + kspan - 1;
+ k2 = 0;
+ do {
+ k2++;
+ Re [k1] = Rtmp [k2 - 1];
+ Im [k1] = Itmp [k2 - 1];
+ k1 -= inc;
+ } while (k1 != (kk-1));
+ } while (jj);
+ } while (j != 1);
+ }
+ return 0; /* exit point here */
+}
+/* ---------------------- end-of-file (c source) ---------------------- */
+
diff --git a/src/modules/audio_coding/codecs/isac/main/source/fft.h b/src/modules/audio_coding/codecs/isac/main/source/fft.h
new file mode 100644
index 0000000..a42f57b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/fft.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*--------------------------------*-C-*---------------------------------*
+ * File:
+ * fftn.h
+ * ---------------------------------------------------------------------*
+ * Re[]: real value array
+ * Im[]: imaginary value array
+ * nTotal: total number of complex values
+ * nPass: number of elements involved in this pass of transform
+ * nSpan: nspan/nPass = number of bytes to increment pointer
+ * in Re[] and Im[]
+ * isign: exponent: +1 = forward -1 = reverse
+ * scaling: normalizing constant by which the final result is *divided*
+ * scaling == -1, normalize by total dimension of the transform
+ * scaling < -1, normalize by the square-root of the total dimension
+ *
+ * ----------------------------------------------------------------------
+ * See the comments in the code for correct usage!
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
+
+
+#include "structs.h"
+
+
+/* double precision routine */
+
+
+int WebRtcIsac_Fftns (unsigned int ndim, const int dims[], double Re[], double Im[],
+ int isign, double scaling, FFTstr *fftstate);
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/filter_functions.c b/src/modules/audio_coding/codecs/isac/main/source/filter_functions.c
new file mode 100644
index 0000000..33024a3
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/filter_functions.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+#include "pitch_estimator.h"
+#include "lpc_analysis.h"
+#include "codec.h"
+
+
+
+void WebRtcIsac_AllPoleFilter(double *InOut, double *Coef, int lengthInOut, int orderCoef){
+
+ /* the state of filter is assumed to be in InOut[-1] to InOut[-orderCoef] */
+ double scal;
+ double sum;
+ int n,k;
+
+ //if (fabs(Coef[0]-1.0)<0.001) {
+ if ( (Coef[0] > 0.9999) && (Coef[0] < 1.0001) )
+ {
+ for(n = 0; n < lengthInOut; n++)
+ {
+ sum = Coef[1] * InOut[-1];
+ for(k = 2; k <= orderCoef; k++){
+ sum += Coef[k] * InOut[-k];
+ }
+ *InOut++ -= sum;
+ }
+ }
+ else
+ {
+ scal = 1.0 / Coef[0];
+ for(n=0;n<lengthInOut;n++)
+ {
+ *InOut *= scal;
+ for(k=1;k<=orderCoef;k++){
+ *InOut -= scal*Coef[k]*InOut[-k];
+ }
+ InOut++;
+ }
+ }
+}
+
+
+void WebRtcIsac_AllZeroFilter(double *In, double *Coef, int lengthInOut, int orderCoef, double *Out){
+
+ /* the state of filter is assumed to be in In[-1] to In[-orderCoef] */
+
+ int n, k;
+ double tmp;
+
+ for(n = 0; n < lengthInOut; n++)
+ {
+ tmp = In[0] * Coef[0];
+
+ for(k = 1; k <= orderCoef; k++){
+ tmp += Coef[k] * In[-k];
+ }
+
+ *Out++ = tmp;
+ In++;
+ }
+}
+
+
+
+void WebRtcIsac_ZeroPoleFilter(double *In, double *ZeroCoef, double *PoleCoef, int lengthInOut, int orderCoef, double *Out){
+
+ /* the state of the zero section is assumed to be in In[-1] to In[-orderCoef] */
+ /* the state of the pole section is assumed to be in Out[-1] to Out[-orderCoef] */
+
+ WebRtcIsac_AllZeroFilter(In,ZeroCoef,lengthInOut,orderCoef,Out);
+ WebRtcIsac_AllPoleFilter(Out,PoleCoef,lengthInOut,orderCoef);
+}
+
+
+void WebRtcIsac_AutoCorr(
+ double *r,
+ const double *x,
+ int N,
+ int order
+ )
+{
+ int lag, n;
+ double sum, prod;
+ const double *x_lag;
+
+ for (lag = 0; lag <= order; lag++)
+ {
+ sum = 0.0f;
+ x_lag = &x[lag];
+ prod = x[0] * x_lag[0];
+ for (n = 1; n < N - lag; n++) {
+ sum += prod;
+ prod = x[n] * x_lag[n];
+ }
+ sum += prod;
+ r[lag] = sum;
+ }
+
+}
+
+
+void WebRtcIsac_BwExpand(double *out, double *in, double coef, short length) {
+ int i;
+ double chirp;
+
+ chirp = coef;
+
+ out[0] = in[0];
+ for (i = 1; i < length; i++) {
+ out[i] = chirp * in[i];
+ chirp *= coef;
+ }
+}
+
+void WebRtcIsac_WeightingFilter(const double *in, double *weiout, double *whiout, WeightFiltstr *wfdata) {
+
+ double tmpbuffer[PITCH_FRAME_LEN + PITCH_WLPCBUFLEN];
+ double corr[PITCH_WLPCORDER+1], rc[PITCH_WLPCORDER+1];
+ double apol[PITCH_WLPCORDER+1], apolr[PITCH_WLPCORDER+1];
+ double rho=0.9, *inp, *dp, *dp2;
+ double whoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER];
+ double weoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER];
+ double *weo, *who, opol[PITCH_WLPCORDER+1], ext[PITCH_WLPCWINLEN];
+ int k, n, endpos, start;
+
+ /* Set up buffer and states */
+ memcpy(tmpbuffer, wfdata->buffer, sizeof(double) * PITCH_WLPCBUFLEN);
+ memcpy(tmpbuffer+PITCH_WLPCBUFLEN, in, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(wfdata->buffer, tmpbuffer+PITCH_FRAME_LEN, sizeof(double) * PITCH_WLPCBUFLEN);
+
+ dp=weoutbuf;
+ dp2=whoutbuf;
+ for (k=0;k<PITCH_WLPCORDER;k++) {
+ *dp++ = wfdata->weostate[k];
+ *dp2++ = wfdata->whostate[k];
+ opol[k]=0.0;
+ }
+ opol[0]=1.0;
+ opol[PITCH_WLPCORDER]=0.0;
+ weo=dp;
+ who=dp2;
+
+ endpos=PITCH_WLPCBUFLEN + PITCH_SUBFRAME_LEN;
+ inp=tmpbuffer + PITCH_WLPCBUFLEN;
+
+ for (n=0; n<PITCH_SUBFRAMES; n++) {
+ /* Windowing */
+ start=endpos-PITCH_WLPCWINLEN;
+ for (k=0; k<PITCH_WLPCWINLEN; k++) {
+ ext[k]=wfdata->window[k]*tmpbuffer[start+k];
+ }
+
+ /* Get LPC polynomial */
+ WebRtcIsac_AutoCorr(corr, ext, PITCH_WLPCWINLEN, PITCH_WLPCORDER);
+ corr[0]=1.01*corr[0]+1.0; /* White noise correction */
+ WebRtcIsac_LevDurb(apol, rc, corr, PITCH_WLPCORDER);
+ WebRtcIsac_BwExpand(apolr, apol, rho, PITCH_WLPCORDER+1);
+
+ /* Filtering */
+ WebRtcIsac_ZeroPoleFilter(inp, apol, apolr, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, weo);
+ WebRtcIsac_ZeroPoleFilter(inp, apolr, opol, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, who);
+
+ inp+=PITCH_SUBFRAME_LEN;
+ endpos+=PITCH_SUBFRAME_LEN;
+ weo+=PITCH_SUBFRAME_LEN;
+ who+=PITCH_SUBFRAME_LEN;
+ }
+
+ /* Export filter states */
+ for (k=0;k<PITCH_WLPCORDER;k++) {
+ wfdata->weostate[k]=weoutbuf[PITCH_FRAME_LEN+k];
+ wfdata->whostate[k]=whoutbuf[PITCH_FRAME_LEN+k];
+ }
+
+ /* Export output data */
+ memcpy(weiout, weoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(whiout, whoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+}
+
+
+static const double APupper[ALLPASSSECTIONS] = {0.0347, 0.3826};
+static const double APlower[ALLPASSSECTIONS] = {0.1544, 0.744};
+
+
+
+void WebRtcIsac_AllpassFilterForDec(double *InOut,
+ const double *APSectionFactors,
+ int lengthInOut,
+ double *FilterState)
+{
+ //This performs all-pass filtering--a series of first order all-pass sections are used
+ //to filter the input in a cascade manner.
+ int n,j;
+ double temp;
+ for (j=0; j<ALLPASSSECTIONS; j++){
+ for (n=0;n<lengthInOut;n+=2){
+ temp = InOut[n]; //store input
+ InOut[n] = FilterState[j] + APSectionFactors[j]*temp;
+ FilterState[j] = -APSectionFactors[j]*InOut[n] + temp;
+ }
+ }
+}
+
+void WebRtcIsac_DecimateAllpass(const double *in,
+ double *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ int N, /* number of input samples */
+ double *out) /* array of size N/2 */
+{
+ int n;
+ double data_vec[PITCH_FRAME_LEN];
+
+ /* copy input */
+ memcpy(data_vec+1, in, sizeof(double) * (N-1));
+
+ data_vec[0] = state_in[2*ALLPASSSECTIONS]; //the z^(-1) state
+ state_in[2*ALLPASSSECTIONS] = in[N-1];
+
+ WebRtcIsac_AllpassFilterForDec(data_vec+1, APupper, N, state_in);
+ WebRtcIsac_AllpassFilterForDec(data_vec, APlower, N, state_in+ALLPASSSECTIONS);
+
+ for (n=0;n<N/2;n++)
+ out[n] = data_vec[2*n] + data_vec[2*n+1];
+
+}
+
+
+
+/* create high-pass filter ocefficients
+ * z = 0.998 * exp(j*2*pi*35/8000);
+ * p = 0.94 * exp(j*2*pi*140/8000);
+ * HP_b = [1, -2*real(z), abs(z)^2];
+ * HP_a = [1, -2*real(p), abs(p)^2]; */
+static const double a_coef[2] = { 1.86864659625574, -0.88360000000000};
+static const double b_coef[2] = {-1.99524591718270, 0.99600400000000};
+static const float a_coef_float[2] = { 1.86864659625574f, -0.88360000000000f};
+static const float b_coef_float[2] = {-1.99524591718270f, 0.99600400000000f};
+
+/* second order high-pass filter */
+void WebRtcIsac_Highpass(const double *in, double *out, double *state, int N)
+{
+ int k;
+
+ for (k=0; k<N; k++) {
+ *out = *in + state[1];
+ state[1] = state[0] + b_coef[0] * *in + a_coef[0] * *out;
+ state[0] = b_coef[1] * *in++ + a_coef[1] * *out++;
+ }
+}
+
+void WebRtcIsac_Highpass_float(const float *in, double *out, double *state, int N)
+{
+ int k;
+
+ for (k=0; k<N; k++) {
+ *out = (double)*in + state[1];
+ state[1] = state[0] + b_coef_float[0] * *in + a_coef_float[0] * *out;
+ state[0] = b_coef_float[1] * (double)*in++ + a_coef_float[1] * *out++;
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.c b/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.c
new file mode 100644
index 0000000..0f844af
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* filterbank_tables.c*/
+/* This file contains variables that are used in filterbanks.c*/
+
+#include "filterbank_tables.h"
+#include "settings.h"
+
+/* The composite all-pass filter factors */
+const float WebRtcIsac_kCompositeApFactorsFloat[4] = {
+ 0.03470000000000f, 0.15440000000000f, 0.38260000000000f, 0.74400000000000f};
+
+/* The upper channel all-pass filter factors */
+const float WebRtcIsac_kUpperApFactorsFloat[2] = {
+ 0.03470000000000f, 0.38260000000000f};
+
+/* The lower channel all-pass filter factors */
+const float WebRtcIsac_kLowerApFactorsFloat[2] = {
+ 0.15440000000000f, 0.74400000000000f};
+
+/* The matrix for transforming the backward composite state to upper channel state */
+const float WebRtcIsac_kTransform1Float[8] = {
+ -0.00158678506084f, 0.00127157815343f, -0.00104805672709f, 0.00084837248079f,
+ 0.00134467983258f, -0.00107756549387f, 0.00088814793277f, -0.00071893072525f};
+
+/* The matrix for transforming the backward composite state to lower channel state */
+const float WebRtcIsac_kTransform2Float[8] = {
+ -0.00170686041697f, 0.00136780109829f, -0.00112736532350f, 0.00091257055385f,
+ 0.00103094281812f, -0.00082615076557f, 0.00068092756088f, -0.00055119165484f};
diff --git a/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.h b/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.h
new file mode 100644
index 0000000..e8fda5e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/filterbank_tables.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.h
+ *
+ * Header file for variables that are defined in
+ * filterbank_tables.c.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_
+
+#include "structs.h"
+
+/********************* Coefficient Tables ************************/
+/* The number of composite all-pass filter factors */
+#define NUMBEROFCOMPOSITEAPSECTIONS 4
+
+/* The number of all-pass filter factors in an upper or lower channel*/
+#define NUMBEROFCHANNELAPSECTIONS 2
+
+/* The composite all-pass filter factors */
+extern const float WebRtcIsac_kCompositeApFactorsFloat[4];
+
+/* The upper channel all-pass filter factors */
+extern const float WebRtcIsac_kUpperApFactorsFloat[2];
+
+/* The lower channel all-pass filter factors */
+extern const float WebRtcIsac_kLowerApFactorsFloat[2];
+
+/* The matrix for transforming the backward composite state to upper channel state */
+extern const float WebRtcIsac_kTransform1Float[8];
+
+/* The matrix for transforming the backward composite state to lower channel state */
+extern const float WebRtcIsac_kTransform2Float[8];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/filterbanks.c b/src/modules/audio_coding/codecs/isac/main/source/filterbanks.c
new file mode 100644
index 0000000..671fd32
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/filterbanks.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function WebRtcIsac_AllPassFilter2Float,
+ * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "settings.h"
+#include "filterbank_tables.h"
+#include "codec.h"
+
+/* This function performs all-pass filtering--a series of first order all-pass
+ * sections are used to filter the input in a cascade manner.
+ * The input is overwritten!!
+ */
+static void WebRtcIsac_AllPassFilter2Float(float *InOut, const float *APSectionFactors,
+ int lengthInOut, int NumberOfSections,
+ float *FilterState)
+{
+ int n, j;
+ float temp;
+ for (j=0; j<NumberOfSections; j++){
+ for (n=0;n<lengthInOut;n++){
+ temp = FilterState[j] + APSectionFactors[j] * InOut[n];
+ FilterState[j] = -APSectionFactors[j] * temp + InOut[n];
+ InOut[n] = temp;
+ }
+ }
+}
+
+/* HPstcoeff_in = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefInFloat[4] =
+{-1.94895953203325f, 0.94984516000000f, -0.05101826139794f, 0.05015484000000f};
+
+/* Function WebRtcIsac_SplitAndFilter
+ * This function creates low-pass and high-pass decimated versions of part of
+ the input signal, and part of the signal in the input 'lookahead buffer'.
+
+ INPUTS:
+ in: a length FRAMESAMPLES array of input samples
+ prefiltdata: input data structure containing the filterbank states
+ and lookahead samples from the previous encoding
+ iteration.
+ OUTPUTS:
+ LP: a FRAMESAMPLES_HALF array of low-pass filtered samples that
+ have been phase equalized. The first QLOOKAHEAD samples are
+ based on the samples in the two prefiltdata->INLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+ HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that
+ have been phase equalized. The first QLOOKAHEAD samples are
+ based on the samples in the two prefiltdata->INLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+
+ LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples.
+ These samples are not phase equalized. They are computed
+ from the samples in the in[] array.
+ HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples
+ that are not phase equalized. They are computed from
+ the in[] vector.
+ prefiltdata: this input data structure's filterbank state and
+ lookahead sample buffers are updated for the next
+ encoding iteration.
+*/
+void WebRtcIsac_SplitAndFilterFloat(float *pin, float *LP, float *HP,
+ double *LP_la, double *HP_la,
+ PreFiltBankstr *prefiltdata)
+{
+ int k,n;
+ float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS];
+ float tempinoutvec[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float in[FRAMESAMPLES];
+ float ftmp;
+
+
+ /* High pass filter */
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] +
+ kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1];
+ ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] -
+ kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1];
+ prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0];
+ prefiltdata->HPstates_float[0] = ftmp;
+ }
+
+ /*
+ % backwards all-pass filtering to obtain zero-phase
+ [tmp1(N2+LA:-1:LA+1, 1), state1] = filter(Q.coef, Q.coef(end:-1:1), in(N:-2:2));
+ tmp1(LA:-1:1) = filter(Q.coef, Q.coef(end:-1:1), Q.LookAheadBuf1, state1);
+ Q.LookAheadBuf1 = in(N:-2:N-2*LA+2);
+ */
+ /*Backwards all-pass filter the odd samples of the input (upper channel)
+ to eventually obtain zero phase. The composite all-pass filter (comprised of both
+ the upper and lower channel all-pass filsters in series) is used for the
+ filtering. */
+
+ /* First Channel */
+
+ /*initial state of composite filter is zero */
+ for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
+ CompositeAPFilterState[k] = 0.0;
+ }
+ /* put every other sample of input into a temporary vector in reverse (backward) order*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempinoutvec[k] = in[FRAMESAMPLES-1-2*k];
+ }
+
+ /* now all-pass filter the backwards vector. Output values overwrite the input vector. */
+ WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ /* save the backwards filtered output for later forward filtering,
+ but write it in forward order*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempin_ch1[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k];
+ }
+
+ /* save the backwards filter state becaue it will be transformed
+ later into a forward state */
+ for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ ForTransform_CompositeAPFilterState[k] = CompositeAPFilterState[k];
+ }
+
+ /* now backwards filter the samples in the lookahead buffer. The samples were
+ placed there in the encoding of the previous frame. The output samples
+ overwrite the input samples */
+ WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF1_float,
+ WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,
+ NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ /* save the output, but write it in forward order */
+ /* write the lookahead samples for the next encoding iteration. Every other
+ sample at the end of the input frame is written in reverse order for the
+ lookahead length. Exported in the prefiltdata structure. */
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch1[QLOOKAHEAD-1-k]=prefiltdata->INLABUF1_float[k];
+ prefiltdata->INLABUF1_float[k]=in[FRAMESAMPLES-1-2*k];
+ }
+
+ /* Second Channel. This is exactly like the first channel, except that the
+ even samples are now filtered instead (lower channel). */
+ for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
+ CompositeAPFilterState[k] = 0.0;
+ }
+
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempinoutvec[k] = in[FRAMESAMPLES-2-2*k];
+ }
+
+ WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempin_ch2[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k];
+ }
+
+ for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k];
+ }
+
+
+ WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF2_float,
+ WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,NUMBEROFCOMPOSITEAPSECTIONS,
+ CompositeAPFilterState);
+
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch2[QLOOKAHEAD-1-k]=prefiltdata->INLABUF2_float[k];
+ prefiltdata->INLABUF2_float[k]=in[FRAMESAMPLES-2-2*k];
+ }
+
+ /* Transform filter states from backward to forward */
+ /*At this point, each of the states of the backwards composite filters for the
+ two channels are transformed into forward filtering states for the corresponding
+ forward channel filters. Each channel's forward filtering state from the previous
+ encoding iteration is added to the transformed state to get a proper forward state */
+
+ /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is multiplied by a
+ NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4) transform matrix to get the
+ new state that is added to the previous 2x1 input state */
+
+ for (k=0;k<NUMBEROFCHANNELAPSECTIONS;k++){ /* k is row variable */
+ for (n=0; n<NUMBEROFCOMPOSITEAPSECTIONS;n++){/* n is column variable */
+ prefiltdata->INSTAT1_float[k] += ForTransform_CompositeAPFilterState[n]*
+ WebRtcIsac_kTransform1Float[k*NUMBEROFCHANNELAPSECTIONS+n];
+ prefiltdata->INSTAT2_float[k] += ForTransform_CompositeAPFilterState2[n]*
+ WebRtcIsac_kTransform2Float[k*NUMBEROFCHANNELAPSECTIONS+n];
+ }
+ }
+
+ /*obtain polyphase components by forward all-pass filtering through each channel */
+ /* the backward filtered samples are now forward filtered with the corresponding channel filters */
+ /* The all pass filtering automatically updates the filter states which are exported in the
+ prefiltdata structure */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_float);
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+ for (k=0; k<FRAMESAMPLES_HALF; k++) {
+ LP[k] = 0.5f*(tempin_ch1[k] + tempin_ch2[k]);/* low pass signal*/
+ HP[k] = 0.5f*(tempin_ch1[k] - tempin_ch2[k]);/* high pass signal*/
+ }
+
+ /* Lookahead LP and HP signals */
+ /* now create low pass and high pass signals of the input vector. However, no
+ backwards filtering is performed, and hence no phase equalization is involved.
+ Also, the input contains some samples that are lookahead samples. The high pass
+ and low pass signals that are created are used outside this function for analysis
+ (not encoding) purposes */
+
+ /* set up input */
+ for (k=0; k<FRAMESAMPLES_HALF; k++) {
+ tempin_ch1[k]=in[2*k+1];
+ tempin_ch2[k]=in[2*k];
+ }
+
+ /* the input filter states are passed in and updated by the all-pass filtering routine and
+ exported in the prefiltdata structure*/
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA2_float);
+
+ for (k=0; k<FRAMESAMPLES_HALF; k++) {
+ LP_la[k] = (float)(0.5f*(tempin_ch1[k] + tempin_ch2[k])); /*low pass */
+ HP_la[k] = (double)(0.5f*(tempin_ch1[k] - tempin_ch2[k])); /* high pass */
+ }
+
+
+}/*end of WebRtcIsac_SplitAndFilter */
+
+
+/* Combining */
+
+/* HPstcoeff_out_1 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut1Float[4] =
+{-1.99701049409000f, 0.99714204490000f, 0.01701049409000f, -0.01704204490000f};
+
+/* HPstcoeff_out_2 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut2Float[4] =
+{-1.98645294509837f, 0.98672435560000f, 0.00645294509837f, -0.00662435560000f};
+
+
+/* Function WebRtcIsac_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+ length FRAMESAMPLES_HALF input low-pass and
+ high-pass signals and creates a reconstructed fullband
+ output signal of length FRAMESAMPLES. WebRtcIsac_FilterAndCombine
+ is the sibling function of WebRtcIsac_SplitAndFilter */
+/* INPUTS:
+ inLP: a length FRAMESAMPLES_HALF array of input low-pass
+ samples.
+ inHP: a length FRAMESAMPLES_HALF array of input high-pass
+ samples.
+ postfiltdata: input data structure containing the filterbank
+ states from the previous decoding iteration.
+ OUTPUTS:
+ Out: a length FRAMESAMPLES array of output reconstructed
+ samples (fullband) based on the input low-pass and
+ high-pass signals.
+ postfiltdata: the input data structure containing the filterbank
+ states is updated for the next decoding iteration */
+void WebRtcIsac_FilterAndCombineFloat(float *InLP,
+ float *InHP,
+ float *Out,
+ PostFiltBankstr *postfiltdata)
+{
+ int k;
+ float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float ftmp, ftmp2;
+
+ /* Form the polyphase signals*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/
+ tempin_ch2[k]=InLP[k]-InHP[k]; /* Construct a new lower channel signal*/
+ }
+
+
+ /* all-pass filter the new upper channel signal. HOWEVER, use the all-pass filter factors
+ that were used as a lower channel at the encoding side. So at the decoder, the
+ corresponding all-pass filter factors for each channel are swapped.*/
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_float);
+
+ /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors
+ at the decoder are swapped from the ones at the encoder, the 'upper' channel
+ all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new
+ lower channel signal */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
+
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ Out[2*k]=tempin_ch2[k];
+ Out[2*k+1]=tempin_ch1[k];
+ }
+
+
+ /* High pass filter */
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] +
+ kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
+ ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
+ kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
+ postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
+ postfiltdata->HPstates1_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] +
+ kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
+ ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
+ kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
+ postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
+ postfiltdata->HPstates2_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/intialize.c b/src/modules/audio_coding/codecs/isac/main/source/intialize.c
new file mode 100644
index 0000000..6df034d
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/intialize.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* encode.c - Encoding function for the iSAC coder */
+
+#include "structs.h"
+#include "codec.h"
+#include "pitch_estimator.h"
+
+#include <math.h>
+
+void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) {
+
+ int k;
+
+ for (k = 0; k < WINLEN; k++) {
+ maskdata->DataBufferLo[k] = 0.0;
+ maskdata->DataBufferHi[k] = 0.0;
+ }
+ for (k = 0; k < ORDERLO+1; k++) {
+ maskdata->CorrBufLo[k] = 0.0;
+ maskdata->PreStateLoF[k] = 0.0;
+ maskdata->PreStateLoG[k] = 0.0;
+ maskdata->PostStateLoF[k] = 0.0;
+ maskdata->PostStateLoG[k] = 0.0;
+ }
+ for (k = 0; k < ORDERHI+1; k++) {
+ maskdata->CorrBufHi[k] = 0.0;
+ maskdata->PreStateHiF[k] = 0.0;
+ maskdata->PreStateHiG[k] = 0.0;
+ maskdata->PostStateHiF[k] = 0.0;
+ maskdata->PostStateHiG[k] = 0.0;
+ }
+
+ maskdata->OldEnergy = 10.0;
+
+ /* fill tables for transforms */
+ WebRtcIsac_InitTransform();
+
+ return;
+}
+
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr *prefiltdata)
+{
+ int k;
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ prefiltdata->INLABUF1[k] = 0;
+ prefiltdata->INLABUF2[k] = 0;
+
+ prefiltdata->INLABUF1_float[k] = 0;
+ prefiltdata->INLABUF2_float[k] = 0;
+ }
+ for (k = 0; k < 2*(QORDER-1); k++) {
+ prefiltdata->INSTAT1[k] = 0;
+ prefiltdata->INSTAT2[k] = 0;
+ prefiltdata->INSTATLA1[k] = 0;
+ prefiltdata->INSTATLA2[k] = 0;
+
+ prefiltdata->INSTAT1_float[k] = 0;
+ prefiltdata->INSTAT2_float[k] = 0;
+ prefiltdata->INSTATLA1_float[k] = 0;
+ prefiltdata->INSTATLA2_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ prefiltdata->HPstates[0] = 0.0;
+ prefiltdata->HPstates[1] = 0.0;
+
+ prefiltdata->HPstates_float[0] = 0.0f;
+ prefiltdata->HPstates_float[1] = 0.0f;
+
+ return;
+}
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+ int k;
+
+ for (k = 0; k < 2*POSTQORDER; k++) {
+ postfiltdata->STATE_0_LOWER[k] = 0;
+ postfiltdata->STATE_0_UPPER[k] = 0;
+
+ postfiltdata->STATE_0_LOWER_float[k] = 0;
+ postfiltdata->STATE_0_UPPER_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ postfiltdata->HPstates1[0] = 0.0;
+ postfiltdata->HPstates1[1] = 0.0;
+
+ postfiltdata->HPstates2[0] = 0.0;
+ postfiltdata->HPstates2[1] = 0.0;
+
+ postfiltdata->HPstates1_float[0] = 0.0f;
+ postfiltdata->HPstates1_float[1] = 0.0f;
+
+ postfiltdata->HPstates2_float[0] = 0.0f;
+ postfiltdata->HPstates2_float[1] = 0.0f;
+
+ return;
+}
+
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr *pitchfiltdata)
+{
+ int k;
+
+ for (k = 0; k < PITCH_BUFFSIZE; k++) {
+ pitchfiltdata->ubuf[k] = 0.0;
+ }
+ pitchfiltdata->ystate[0] = 0.0;
+ for (k = 1; k < (PITCH_DAMPORDER); k++) {
+ pitchfiltdata->ystate[k] = 0.0;
+ }
+ pitchfiltdata->oldlagp[0] = 50.0;
+ pitchfiltdata->oldgainp[0] = 0.0;
+}
+
+void WebRtcIsac_InitWeightingFilter(WeightFiltstr *wfdata)
+{
+ int k;
+ double t, dtmp, dtmp2, denum, denum2;
+
+ for (k=0;k<PITCH_WLPCBUFLEN;k++)
+ wfdata->buffer[k]=0.0;
+
+ for (k=0;k<PITCH_WLPCORDER;k++) {
+ wfdata->istate[k]=0.0;
+ wfdata->weostate[k]=0.0;
+ wfdata->whostate[k]=0.0;
+ }
+
+ /* next part should be in Matlab, writing to a global table */
+ t = 0.5;
+ denum = 1.0 / ((double) PITCH_WLPCWINLEN);
+ denum2 = denum * denum;
+ for (k=0;k<PITCH_WLPCWINLEN;k++) {
+ dtmp = PITCH_WLPCASYM * t * denum + (1-PITCH_WLPCASYM) * t * t * denum2;
+ dtmp *= 3.14159265;
+ dtmp2 = sin(dtmp);
+ wfdata->window[k] = dtmp2 * dtmp2;
+ t++;
+ }
+}
+
+/* clear all buffers */
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct *State)
+{
+ int k;
+
+ for (k = 0; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k++)
+ State->dec_buffer[k] = 0.0;
+ for (k = 0; k < 2*ALLPASSSECTIONS+1; k++)
+ State->decimator_state[k] = 0.0;
+ for (k = 0; k < 2; k++)
+ State->hp_state[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->whitened_buf[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = 0.0;
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr_wght));
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr));
+
+ WebRtcIsac_InitWeightingFilter(&(State->Wghtstr));
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/isac.c b/src/modules/audio_coding/codecs/isac/main/source/isac.c
new file mode 100644
index 0000000..7c90334
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/isac.c
@@ -0,0 +1,2313 @@
+/*
+ * 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;
+ 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;
+ 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;
+ }
+ }
+ /* 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);
+
+ /* 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) {
+ WebRtcSpl_AnalysisQMF(speechIn, 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 3! 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.
+ *
+ * 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 length of the frame represented in the packet.
+ *
+ * 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->encoderSamplingRateKHz == kIsacWideband) {
+ return (instISAC->instLB.ISACencLB_obj.new_framelength);
+ } else {
+ return ((instISAC->instLB.ISACencLB_obj.new_framelength) << 1);
+ }
+}
+
+
+/****************************************************************************
+ * 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
+ * Sset 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.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if ((sampRate != kIsacWideband) &&
+ (sampRate != kIsacSuperWideband)) {
+ /* Sampling Frequency is not supported. */
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ } else if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ if (sampRate == kIsacWideband) {
+ instISAC->bandwidthKHz = isac8kHz;
+ } else {
+ instISAC->bandwidthKHz = isac16kHz;
+ }
+ instISAC->encoderSamplingRateKHz = sampRate;
+ return 0;
+ } 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 ((sampRate == 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 ((sampRate == 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, sampRate);
+ 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 = sampRate;
+ 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
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if ((sampRate != kIsacWideband) &&
+ (sampRate != kIsacSuperWideband)) {
+ /* Sampling Frequency is not supported. */
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ } else {
+ if ((instISAC->decoderSamplingRateKHz == kIsacWideband) &&
+ (sampRate == 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 = sampRate;
+ return 0;
+ }
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the encoder, the input audio
+ * is expected to be sampled at this rate.
+ *
+ */
+enum IsacSamplingRate WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ return instISAC->encoderSamplingRateKHz;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the decoder, i.e. the
+ * sampling rate of the decoded audio.
+ *
+ */
+enum IsacSamplingRate WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ return instISAC->decoderSamplingRateKHz;
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/isac.gypi b/src/modules/audio_coding/codecs/isac/main/source/isac.gypi
new file mode 100644
index 0000000..d30be55
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/isac.gypi
@@ -0,0 +1,91 @@
+# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'iSAC',
+ 'type': '<(library)',
+ 'dependencies': [
+ '<(webrtc_root)/common_audio/common_audio.gyp:signal_processing',
+ ],
+ 'include_dirs': [
+ '../interface',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../interface',
+ ],
+ },
+ 'sources': [
+ '../interface/isac.h',
+ 'arith_routines.c',
+ 'arith_routines_hist.c',
+ 'arith_routines_logist.c',
+ 'bandwidth_estimator.c',
+ 'crc.c',
+ 'decode.c',
+ 'decode_bwe.c',
+ 'encode.c',
+ 'encode_lpc_swb.c',
+ 'entropy_coding.c',
+ 'fft.c',
+ 'filter_functions.c',
+ 'filterbank_tables.c',
+ 'intialize.c',
+ 'isac.c',
+ 'filterbanks.c',
+ 'pitch_lag_tables.c',
+ 'lattice.c',
+ 'lpc_gain_swb_tables.c',
+ 'lpc_analysis.c',
+ 'lpc_shape_swb12_tables.c',
+ 'lpc_shape_swb16_tables.c',
+ 'lpc_tables.c',
+ 'pitch_estimator.c',
+ 'pitch_filter.c',
+ 'pitch_gain_tables.c',
+ 'spectrum_ar_model_tables.c',
+ 'transform.c',
+ 'arith_routines.h',
+ 'bandwidth_estimator.h',
+ 'codec.h',
+ 'crc.h',
+ 'encode_lpc_swb.h',
+ 'entropy_coding.h',
+ 'fft.h',
+ 'filterbank_tables.h',
+ 'lpc_gain_swb_tables.h',
+ 'lpc_analysis.h',
+ 'lpc_shape_swb12_tables.h',
+ 'lpc_shape_swb16_tables.h',
+ 'lpc_tables.h',
+ 'pitch_estimator.h',
+ 'pitch_gain_tables.h',
+ 'pitch_lag_tables.h',
+ 'settings.h',
+ 'spectrum_ar_model_tables.h',
+ 'structs.h',
+ 'os_specific_inline.h',
+ ],
+ 'conditions': [
+ ['OS!="win"', {
+ 'defines': [
+ 'WEBRTC_LINUX',
+ ],
+ }],
+ ],
+ },
+ ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lattice.c b/src/modules/audio_coding/codecs/isac/main/source/lattice.c
new file mode 100644
index 0000000..a46135a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lattice.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+#include "settings.h"
+#include "codec.h"
+
+#include <math.h>
+#include <memory.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+ float *stateF,
+ float *stateG,
+ float *lat_in,
+ double *filtcoeflo,
+ double *lat_out)
+{
+ int n,k,i,u,temp1;
+ int ord_1 = orderCoef+1;
+ float sth[MAX_AR_MODEL_ORDER];
+ float cth[MAX_AR_MODEL_ORDER];
+ float inv_cth[MAX_AR_MODEL_ORDER];
+ double a[MAX_AR_MODEL_ORDER+1];
+ float f[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], g[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ float gain1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ /* set the Direct Form coefficients */
+ temp1 = u*ord_1;
+ a[0] = 1;
+ memcpy(a+1, filtcoeflo+temp1+1, sizeof(double) * (ord_1-1));
+
+ /* compute lattice filter coefficients */
+ WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+ /* compute the gain */
+ gain1 = (float)filtcoeflo[temp1];
+ for (k=0;k<orderCoef;k++)
+ {
+ gain1 *= cth[k];
+ inv_cth[k] = 1/cth[k];
+ }
+
+ /* normalized lattice filter */
+ /*****************************/
+
+ /* initial conditions */
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ f[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+ g[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+ }
+
+ /* get the state of f&g for the first input, for all orders */
+ for (i=1;i<ord_1;i++)
+ {
+ f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+ g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+ }
+
+ /* filtering */
+ for(k=0;k<orderCoef;k++)
+ {
+ for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+ {
+ f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
+ g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
+ }
+ }
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ lat_out[n + u * HALF_SUBFRAMELEN] = gain1 * f[orderCoef][n];
+ }
+
+ /* save the states */
+ for (i=0;i<ord_1;i++)
+ {
+ stateF[i] = f[i][HALF_SUBFRAMELEN-1];
+ stateG[i] = g[i][HALF_SUBFRAMELEN-1];
+ }
+ /* process next frame */
+ }
+
+ return;
+}
+
+
+/*///////////////////AR filter ///////////////////////////////*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+ float *stateF,
+ float *stateG,
+ double *lat_in,
+ double *lo_filt_coef,
+ float *lat_out)
+{
+ int n,k,i,u,temp1;
+ int ord_1 = orderCoef+1;
+ float sth[MAX_AR_MODEL_ORDER];
+ float cth[MAX_AR_MODEL_ORDER];
+ double a[MAX_AR_MODEL_ORDER+1];
+ float ARf[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], ARg[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ float gain1,inv_gain1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ /* set the denominator and numerator of the Direct Form */
+ temp1 = u*ord_1;
+ a[0] = 1;
+
+ memcpy(a+1, lo_filt_coef+temp1+1, sizeof(double) * (ord_1-1));
+
+ WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+ gain1 = (float)lo_filt_coef[temp1];
+ for (k=0;k<orderCoef;k++)
+ {
+ gain1 = cth[k]*gain1;
+ }
+
+ /* initial conditions */
+ inv_gain1 = 1/gain1;
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ ARf[orderCoef][i] = (float)lat_in[i + u * HALF_SUBFRAMELEN]*inv_gain1;
+ }
+
+
+ for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
+ {
+ ARf[i][0] = cth[i]*ARf[i+1][0] - sth[i]*stateG[i];
+ ARg[i+1][0] = sth[i]*ARf[i+1][0] + cth[i]* stateG[i];
+ }
+ ARg[0][0] = ARf[0][0];
+
+ for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+ {
+ for(k=orderCoef-1;k>=0;k--)
+ {
+ ARf[k][n+1] = cth[k]*ARf[k+1][n+1] - sth[k]*ARg[k][n];
+ ARg[k+1][n+1] = sth[k]*ARf[k+1][n+1] + cth[k]* ARg[k][n];
+ }
+ ARg[0][n+1] = ARf[0][n+1];
+ }
+
+ memcpy(lat_out+u * HALF_SUBFRAMELEN, &(ARf[0][0]), sizeof(float) * HALF_SUBFRAMELEN);
+
+ /* cannot use memcpy in the following */
+ for (i=0;i<ord_1;i++)
+ {
+ stateF[i] = ARf[i][HALF_SUBFRAMELEN-1];
+ stateG[i] = ARg[i][HALF_SUBFRAMELEN-1];
+ }
+
+ }
+
+ return;
+}
+
+
+/* compute the reflection coefficients using the step-down procedure*/
+/* converts the direct form parameters to lattice form.*/
+/* a and b are vectors which contain the direct form coefficients,
+ according to
+ A(z) = a(1) + a(2)*z + a(3)*z^2 + ... + a(M+1)*z^M
+ B(z) = b(1) + b(2)*z + b(3)*z^2 + ... + b(M+1)*z^M
+*/
+
+void WebRtcIsac_Dir2Lat(double *a,
+ int orderCoef,
+ float *sth,
+ float *cth)
+{
+ int m, k;
+ float tmp[MAX_AR_MODEL_ORDER];
+ float tmp_inv, cth2;
+
+ sth[orderCoef-1] = (float)a[orderCoef];
+ cth2 = 1.0f - sth[orderCoef-1] * sth[orderCoef-1];
+ cth[orderCoef-1] = (float)sqrt(cth2);
+ for (m=orderCoef-1; m>0; m--)
+ {
+ tmp_inv = 1.0f / cth2;
+ for (k=1; k<=m; k++)
+ {
+ tmp[k] = ((float)a[k] - sth[m] * (float)a[m-k+1]) * tmp_inv;
+ }
+
+ for (k=1; k<m; k++)
+ {
+ a[k] = tmp[k];
+ }
+
+ sth[m-1] = tmp[m];
+ cth2 = 1 - sth[m-1] * sth[m-1];
+ cth[m-1] = (float)sqrt(cth2);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c b/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
new file mode 100644
index 0000000..854b2d7
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "lpc_analysis.h"
+#include "settings.h"
+#include "codec.h"
+#include "entropy_coding.h"
+
+#include <math.h>
+#include <string.h>
+
+#define LEVINSON_EPS 1.0e-10
+
+
+/* window */
+/* Matlab generation code:
+ * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ */
+static const double kLpcCorrWindow[WINLEN] = {
+ 0.00000000, 0.00000001, 0.00000004, 0.00000010, 0.00000020,
+ 0.00000035, 0.00000055, 0.00000083, 0.00000118, 0.00000163,
+ 0.00000218, 0.00000283, 0.00000361, 0.00000453, 0.00000558, 0.00000679,
+ 0.00000817, 0.00000973, 0.00001147, 0.00001342, 0.00001558,
+ 0.00001796, 0.00002058, 0.00002344, 0.00002657, 0.00002997,
+ 0.00003365, 0.00003762, 0.00004190, 0.00004651, 0.00005144, 0.00005673,
+ 0.00006236, 0.00006837, 0.00007476, 0.00008155, 0.00008875,
+ 0.00009636, 0.00010441, 0.00011290, 0.00012186, 0.00013128,
+ 0.00014119, 0.00015160, 0.00016252, 0.00017396, 0.00018594, 0.00019846,
+ 0.00021155, 0.00022521, 0.00023946, 0.00025432, 0.00026978,
+ 0.00028587, 0.00030260, 0.00031998, 0.00033802, 0.00035674,
+ 0.00037615, 0.00039626, 0.00041708, 0.00043863, 0.00046092, 0.00048396,
+ 0.00050775, 0.00053233, 0.00055768, 0.00058384, 0.00061080,
+ 0.00063858, 0.00066720, 0.00069665, 0.00072696, 0.00075813,
+ 0.00079017, 0.00082310, 0.00085692, 0.00089164, 0.00092728, 0.00096384,
+ 0.00100133, 0.00103976, 0.00107914, 0.00111947, 0.00116077,
+ 0.00120304, 0.00124630, 0.00129053, 0.00133577, 0.00138200,
+ 0.00142924, 0.00147749, 0.00152676, 0.00157705, 0.00162836, 0.00168070,
+ 0.00173408, 0.00178850, 0.00184395, 0.00190045, 0.00195799,
+ 0.00201658, 0.00207621, 0.00213688, 0.00219860, 0.00226137,
+ 0.00232518, 0.00239003, 0.00245591, 0.00252284, 0.00259079, 0.00265977,
+ 0.00272977, 0.00280078, 0.00287280, 0.00294582, 0.00301984,
+ 0.00309484, 0.00317081, 0.00324774, 0.00332563, 0.00340446,
+ 0.00348421, 0.00356488, 0.00364644, 0.00372889, 0.00381220, 0.00389636,
+ 0.00398135, 0.00406715, 0.00415374, 0.00424109, 0.00432920,
+ 0.00441802, 0.00450754, 0.00459773, 0.00468857, 0.00478001,
+ 0.00487205, 0.00496464, 0.00505775, 0.00515136, 0.00524542, 0.00533990,
+ 0.00543476, 0.00552997, 0.00562548, 0.00572125, 0.00581725,
+ 0.00591342, 0.00600973, 0.00610612, 0.00620254, 0.00629895,
+ 0.00639530, 0.00649153, 0.00658758, 0.00668341, 0.00677894, 0.00687413,
+ 0.00696891, 0.00706322, 0.00715699, 0.00725016, 0.00734266,
+ 0.00743441, 0.00752535, 0.00761540, 0.00770449, 0.00779254,
+ 0.00787947, 0.00796519, 0.00804963, 0.00813270, 0.00821431, 0.00829437,
+ 0.00837280, 0.00844949, 0.00852436, 0.00859730, 0.00866822,
+ 0.00873701, 0.00880358, 0.00886781, 0.00892960, 0.00898884,
+ 0.00904542, 0.00909923, 0.00915014, 0.00919805, 0.00924283, 0.00928436,
+ 0.00932252, 0.00935718, 0.00938821, 0.00941550, 0.00943890,
+ 0.00945828, 0.00947351, 0.00948446, 0.00949098, 0.00949294,
+ 0.00949020, 0.00948262, 0.00947005, 0.00945235, 0.00942938, 0.00940099,
+ 0.00936704, 0.00932738, 0.00928186, 0.00923034, 0.00917268,
+ 0.00910872, 0.00903832, 0.00896134, 0.00887763, 0.00878706,
+ 0.00868949, 0.00858478, 0.00847280, 0.00835343, 0.00822653, 0.00809199,
+ 0.00794970, 0.00779956, 0.00764145, 0.00747530, 0.00730103,
+ 0.00711857, 0.00692787, 0.00672888, 0.00652158, 0.00630597,
+ 0.00608208, 0.00584994, 0.00560962, 0.00536124, 0.00510493, 0.00484089,
+ 0.00456935, 0.00429062, 0.00400505, 0.00371310, 0.00341532,
+ 0.00311238, 0.00280511, 0.00249452, 0.00218184, 0.00186864,
+ 0.00155690, 0.00124918, 0.00094895, 0.00066112, 0.00039320, 0.00015881
+};
+
+double WebRtcIsac_LevDurb(double *a, double *k, double *r, int order)
+{
+
+ double sum, alpha;
+ int m, m_h, i;
+ alpha = 0; //warning -DH
+ a[0] = 1.0;
+ if (r[0] < LEVINSON_EPS) { /* if r[0] <= 0, set LPC coeff. to zero */
+ for (i = 0; i < order; i++) {
+ k[i] = 0;
+ a[i+1] = 0;
+ }
+ } else {
+ a[1] = k[0] = -r[1]/r[0];
+ alpha = r[0] + r[1] * k[0];
+ for (m = 1; m < order; m++){
+ sum = r[m + 1];
+ for (i = 0; i < m; i++){
+ sum += a[i+1] * r[m - i];
+ }
+ k[m] = -sum / alpha;
+ alpha += k[m] * sum;
+ m_h = (m + 1) >> 1;
+ for (i = 0; i < m_h; i++){
+ sum = a[i+1] + k[m] * a[m - i];
+ a[m - i] += k[m] * a[i+1];
+ a[i+1] = sum;
+ }
+ a[m+1] = k[m];
+ }
+ }
+ return alpha;
+}
+
+
+//was static before, but didn't work with MEX file
+void WebRtcIsac_GetVars(const double *input, const WebRtc_Word16 *pitchGains_Q12,
+ double *oldEnergy, double *varscale)
+{
+ double nrg[4], chng, pg;
+ int k;
+
+ double pitchGains[4]={0,0,0,0};;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES_QUARTER + QLOOKAHEAD) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF + QLOOKAHEAD) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4 + QLOOKAHEAD) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* Find average pitch gain */
+ pg = 0.0;
+ for (k=0; k<4; k++)
+ {
+ pitchGains[k] = ((float)pitchGains_Q12[k])/4096;
+ pg += pitchGains[k];
+ }
+ pg *= 0.25;
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = 0.0 + 1.0 * exp( -1.4 * exp(-200.0 * pg*pg*pg) / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+void
+WebRtcIsac_GetVarsUB(
+ const double* input,
+ double* oldEnergy,
+ double* varscale)
+{
+ double nrg[4], chng;
+ int k;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = 0; k < (FRAMESAMPLES_QUARTER) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = exp( -1.4 / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+ double signal_noise_ratio, const WebRtc_Word16 *pitchGains_Q12,
+ double *lo_coeff, double *hi_coeff)
+{
+ int k, n, j, pos1, pos2;
+ double varscale;
+
+ double DataLo[WINLEN], DataHi[WINLEN];
+ double corrlo[ORDERLO+2], corrlo2[ORDERLO+1];
+ double corrhi[ORDERHI+1];
+ double k_veclo[ORDERLO], k_vechi[ORDERHI];
+
+ double a_LO[ORDERLO+1], a_HI[ORDERHI+1];
+ double tmp, res_nrg;
+
+ double FwdA, FwdB;
+
+ /* hearing threshold level in dB; higher value gives more noise */
+ const double HearThresOffset = -28.0;
+
+ /* bandwdith expansion factors for low- and high band */
+ const double gammaLo = 0.9;
+ const double gammaHi = 0.8;
+
+ /* less-noise-at-low-frequencies factor */
+ double aa;
+
+
+ /* convert from dB to signal level */
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46; /* divide by sqrt(12) */
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVars(inLo, pitchGains_Q12, &(maskdata->OldEnergy), &varscale);
+
+ /* less-noise-at-low-frequencies factor */
+ aa = 0.35 * (0.5 + 0.5 * varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++)
+ maskdata->DataBufferLo[pos1 + WINLEN - QLOOKAHEAD] = inLo[pos1];
+
+ for (k = 0; k < SUBFRAMES; k++) {
+
+ /* Update input buffer and multiply signal with window */
+ for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 + UPDATE/2];
+ maskdata->DataBufferHi[pos1] = maskdata->DataBufferHi[pos1 + UPDATE/2];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = k * UPDATE/2;
+ for (n = 0; n < UPDATE/2; n++, pos1++) {
+ maskdata->DataBufferLo[pos1] = inLo[QLOOKAHEAD + pos2];
+ maskdata->DataBufferHi[pos1] = inHi[pos2++];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ WebRtcIsac_AutoCorr(corrlo, DataLo, WINLEN, ORDERLO+1); /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrhi, DataHi, WINLEN, ORDERHI);
+
+
+ /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+ corrlo2[0] = (1.0+aa*aa) * corrlo[0] - 2.0*aa * corrlo[1];
+ tmp = (1.0 + aa*aa);
+ for (n = 1; n <= ORDERLO; n++) {
+ corrlo2[n] = tmp * corrlo[n] - aa * (corrlo[n-1] + corrlo[n+1]);
+ }
+ tmp = (1.0+aa) * (1.0+aa);
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhi[n] = tmp * corrhi[n];
+ }
+
+ /* add white noise floor */
+ corrlo2[0] += 1e-6;
+ corrhi[0] += 1e-6;
+
+
+ FwdA = 0.01;
+ FwdB = 0.01;
+
+ /* recursive filtering of correlation over subframes */
+ for (n = 0; n <= ORDERLO; n++) {
+ maskdata->CorrBufLo[n] = FwdA * maskdata->CorrBufLo[n] + corrlo2[n];
+ corrlo2[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufLo[n] + (1.0-FwdB) * corrlo2[n];
+ }
+ for (n = 0; n <= ORDERHI; n++) {
+ maskdata->CorrBufHi[n] = FwdA * maskdata->CorrBufHi[n] + corrhi[n];
+ corrhi[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufHi[n] + (1.0-FwdB) * corrhi[n];
+ }
+
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(a_LO, k_veclo, corrlo2, ORDERLO);
+ WebRtcIsac_LevDurb(a_HI, k_vechi, corrhi, ORDERHI);
+
+ /* bandwidth expansion */
+ tmp = gammaLo;
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LO[n] *= tmp;
+ tmp *= gammaLo;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERLO; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_LO[j] * corrlo2[j-n] * a_LO[n];
+ }
+ for (n = j+1; n <= ORDERLO; n++) {
+ res_nrg += a_LO[j] * corrlo2[n-j] * a_LO[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ *lo_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERLO; n++) {
+ *lo_coeff++ = a_LO[n];
+ }
+
+
+ /* bandwidth expansion */
+ tmp = gammaHi;
+ for (n = 1; n <= ORDERHI; n++) {
+ a_HI[n] *= tmp;
+ tmp *= gammaHi;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERHI; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_HI[j] * corrhi[j-n] * a_HI[n];
+ }
+ for (n = j+1; n <= ORDERHI; n++) {
+ res_nrg += a_HI[j] * corrhi[n-j] * a_HI[n];
+ }
+ }
+
+ /* add hearing threshold and compute of the gain */
+ *hi_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERHI; n++) {
+ *hi_coeff++ = a_HI[n];
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcCoefUb()
+ *
+ * Compute LP coefficients and correlation coefficients. At 12 kHz LP
+ * coefficients of the first and the last sub-frame is computed. At 16 kHz
+ * LP coefficients of 4th, 8th and 12th sub-frames are computed. We always
+ * compute correlation coefficients of all sub-frames.
+ *
+ * Inputs:
+ * -inSignal : Input signal
+ * -maskdata : a structure keeping signal from previous frame.
+ * -bandwidth : specifies if the codec is in 0-16 kHz mode or
+ * 0-12 kHz mode.
+ *
+ * Outputs:
+ * -lpCoeff : pointer to a buffer where A-polynomials are
+ * written to (first coeff is 1 and it is not
+ * written)
+ * -corrMat : a matrix where correlation coefficients of each
+ * sub-frame are written to one row.
+ * -varscale : a scale used to compute LPC gains.
+ */
+void
+WebRtcIsac_GetLpcCoefUb(
+ double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corrMat[][UB_LPC_ORDER + 1],
+ double* varscale,
+ WebRtc_Word16 bandwidth)
+{
+ int frameCntr, activeFrameCntr, n, pos1, pos2;
+ WebRtc_Word16 criterion1;
+ WebRtc_Word16 criterion2;
+ WebRtc_Word16 numSubFrames = SUBFRAMES * (1 + (bandwidth == isac16kHz));
+ double data[WINLEN];
+ double corrSubFrame[UB_LPC_ORDER+2];
+ double reflecCoeff[UB_LPC_ORDER];
+
+ double aPolynom[UB_LPC_ORDER+1];
+ double tmp;
+
+ /* bandwdith expansion factors */
+ const double gamma = 0.9;
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVarsUB(inSignal, &(maskdata->OldEnergy), varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for(frameCntr = 0, activeFrameCntr = 0; frameCntr < numSubFrames;
+ frameCntr++)
+ {
+ if(frameCntr == SUBFRAMES)
+ {
+ // we are in 16 kHz
+ varscale++;
+ WebRtcIsac_GetVarsUB(&inSignal[FRAMESAMPLES_HALF],
+ &(maskdata->OldEnergy), varscale);
+ }
+ /* Update input buffer and multiply signal with window */
+ for(pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++)
+ {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 +
+ UPDATE/2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = frameCntr * UPDATE/2;
+ for(n = 0; n < UPDATE/2; n++, pos1++, pos2++)
+ {
+ maskdata->DataBufferLo[pos1] = inSignal[pos2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrSubFrame, data, WINLEN, UB_LPC_ORDER+1);
+ memcpy(corrMat[frameCntr], corrSubFrame,
+ (UB_LPC_ORDER+1)*sizeof(double));
+
+ criterion1 = ((frameCntr == 0) || (frameCntr == (SUBFRAMES - 1))) &&
+ (bandwidth == isac12kHz);
+ criterion2 = (((frameCntr+1) % 4) == 0) &&
+ (bandwidth == isac16kHz);
+ if(criterion1 || criterion2)
+ {
+ /* add noise */
+ corrSubFrame[0] += 1e-6;
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(aPolynom, reflecCoeff, corrSubFrame,
+ UB_LPC_ORDER);
+
+ /* bandwidth expansion */
+ tmp = gamma;
+ for (n = 1; n <= UB_LPC_ORDER; n++)
+ {
+ *lpCoeff++ = aPolynom[n] * tmp;
+ tmp *= gamma;
+ }
+ activeFrameCntr++;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcGain()
+ *
+ * Compute the LPC gains for each sub-frame, given the LPC of each sub-frame
+ * and the corresponding correlation coefficients.
+ *
+ * Inputs:
+ * -signal_noise_ratio : the desired SNR in dB.
+ * -numVecs : number of sub-frames
+ * -corrMat : a matrix of correlation coefficients where
+ * each row is a set of correlation coefficients of
+ * one sub-frame.
+ * -varscale : a scale computed when WebRtcIsac_GetLpcCoefUb()
+ * is called.
+ *
+ * Outputs:
+ * -gain : pointer to a buffer where LP gains are written.
+ *
+ */
+void
+WebRtcIsac_GetLpcGain(
+ double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrMat[][UB_LPC_ORDER + 1],
+ const double* varscale)
+{
+ WebRtc_Word16 j, n;
+ WebRtc_Word16 subFrameCntr;
+ double aPolynom[ORDERLO + 1];
+ double res_nrg;
+
+ const double HearThresOffset = -28.0;
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ /* divide by sqrt(12) = 3.46 */
+ const double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;
+
+ aPolynom[0] = 1;
+ for(subFrameCntr = 0; subFrameCntr < numVecs; subFrameCntr++)
+ {
+ if(subFrameCntr == SUBFRAMES)
+ {
+ // we are in second half of a SWB frame. use new varscale
+ varscale++;
+ }
+ memcpy(&aPolynom[1], &filtCoeffVecs[(subFrameCntr * (UB_LPC_ORDER + 1)) +
+ 1], sizeof(double) * UB_LPC_ORDER);
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for(j = 0; j <= UB_LPC_ORDER; j++)
+ {
+ for(n = 0; n <= j; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][j-n] *
+ aPolynom[n];
+ }
+ for(n = j+1; n <= UB_LPC_ORDER; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][n-j] *
+ aPolynom[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ gain[subFrameCntr] = S_N_R / (sqrt(res_nrg) / *varscale + H_T_H);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h b/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
new file mode 100644
index 0000000..4eafeac
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_analysis.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+
+#include "settings.h"
+#include "structs.h"
+
+double WebRtcIsac_LevDurb(double *a, double *k, double *r, int order);
+
+void WebRtcIsac_GetVars(const double *input, const WebRtc_Word16 *pitchGains_Q12,
+ double *oldEnergy, double *varscale);
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+ double signal_noise_ratio, const WebRtc_Word16 *pitchGains_Q12,
+ double *lo_coeff, double *hi_coeff);
+
+
+void WebRtcIsac_GetLpcGain(
+ double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrLo[][UB_LPC_ORDER + 1],
+ const double* varscale);
+
+void WebRtcIsac_GetLpcCoefUb(
+ double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corr[][UB_LPC_ORDER + 1],
+ double* varscale,
+ WebRtc_Word16 bandwidth);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYIS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c b/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
new file mode 100644
index 0000000..25c69cb
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.c
+ *
+ * This file defines tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#include "lpc_gain_swb_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+const double WebRtcIsac_kQSizeLpcGain = 0.100000;
+
+const double WebRtcIsac_kMeanLpcGain = -3.3822;
+
+/*
+* The smallest reconstruction points for quantiztion of
+* LPC gains.
+*/
+const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES] =
+{
+ -0.800000, -1.000000, -1.200000, -2.200000, -3.000000, -12.700000
+};
+
+/*
+* Number of reconstruction points of quantizers for LPC Gains.
+*/
+const WebRtc_Word16 WebRtcIsac_kNumQCellLpcGain[SUBFRAMES] =
+{
+ 17, 20, 25, 45, 77, 170
+};
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES] =
+{
+ 8, 10, 12, 22, 38, 85
+};
+
+/*
+* The following 6 vectors define CDF of 6 decorrelated LPC
+* gains.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec0[18] =
+{
+ 0, 10, 27, 83, 234, 568, 1601, 4683, 16830, 57534, 63437,
+ 64767, 65229, 65408, 65483, 65514, 65527, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec1[21] =
+{
+ 0, 15, 33, 84, 185, 385, 807, 1619, 3529, 7850, 19488,
+ 51365, 62437, 64548, 65088, 65304, 65409, 65484, 65507, 65522, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec2[26] =
+{
+ 0, 15, 29, 54, 89, 145, 228, 380, 652, 1493, 4260,
+ 12359, 34133, 50749, 57224, 60814, 62927, 64078, 64742, 65103, 65311, 65418,
+ 65473, 65509, 65521, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec3[46] =
+{
+ 0, 8, 12, 16, 26, 42, 56, 76, 111, 164, 247,
+ 366, 508, 693, 1000, 1442, 2155, 3188, 4854, 7387, 11249, 17617,
+ 30079, 46711, 56291, 60127, 62140, 63258, 63954, 64384, 64690, 64891, 65031,
+ 65139, 65227, 65293, 65351, 65399, 65438, 65467, 65492, 65504, 65510, 65518,
+ 65523, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec4[78] =
+{
+ 0, 17, 29, 39, 51, 70, 104, 154, 234, 324, 443,
+ 590, 760, 971, 1202, 1494, 1845, 2274, 2797, 3366, 4088, 4905,
+ 5899, 7142, 8683, 10625, 12983, 16095, 20637, 28216, 38859, 47237, 51537,
+ 54150, 56066, 57583, 58756, 59685, 60458, 61103, 61659, 62144, 62550, 62886,
+ 63186, 63480, 63743, 63954, 64148, 64320, 64467, 64600, 64719, 64837, 64939,
+ 65014, 65098, 65160, 65211, 65250, 65290, 65325, 65344, 65366, 65391, 65410,
+ 65430, 65447, 65460, 65474, 65487, 65494, 65501, 65509, 65513, 65518, 65520,
+ 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec5[171] =
+{
+ 0, 10, 12, 14, 16, 18, 23, 29, 35, 42, 51,
+ 58, 65, 72, 78, 87, 96, 103, 111, 122, 134, 150,
+ 167, 184, 202, 223, 244, 265, 289, 315, 346, 379, 414,
+ 450, 491, 532, 572, 613, 656, 700, 751, 802, 853, 905,
+ 957, 1021, 1098, 1174, 1250, 1331, 1413, 1490, 1565, 1647, 1730,
+ 1821, 1913, 2004, 2100, 2207, 2314, 2420, 2532, 2652, 2783, 2921,
+ 3056, 3189, 3327, 3468, 3640, 3817, 3993, 4171, 4362, 4554, 4751,
+ 4948, 5142, 5346, 5566, 5799, 6044, 6301, 6565, 6852, 7150, 7470,
+ 7797, 8143, 8492, 8835, 9181, 9547, 9919, 10315, 10718, 11136, 11566,
+ 12015, 12482, 12967, 13458, 13953, 14432, 14903, 15416, 15936, 16452, 16967,
+ 17492, 18024, 18600, 19173, 19736, 20311, 20911, 21490, 22041, 22597, 23157,
+ 23768, 24405, 25034, 25660, 26280, 26899, 27614, 28331, 29015, 29702, 30403,
+ 31107, 31817, 32566, 33381, 34224, 35099, 36112, 37222, 38375, 39549, 40801,
+ 42074, 43350, 44626, 45982, 47354, 48860, 50361, 51845, 53312, 54739, 56026,
+ 57116, 58104, 58996, 59842, 60658, 61488, 62324, 63057, 63769, 64285, 64779,
+ 65076, 65344, 65430, 65500, 65517, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LPC Gains
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES] =
+{
+ WebRtcIsac_kLpcGainCdfVec0, WebRtcIsac_kLpcGainCdfVec1,
+ WebRtcIsac_kLpcGainCdfVec2, WebRtcIsac_kLpcGainCdfVec3,
+ WebRtcIsac_kLpcGainCdfVec4, WebRtcIsac_kLpcGainCdfVec5
+};
+
+/*
+* A matrix to decorrellate LPC gains of subframes.
+*/
+const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES] =
+{
+ {-0.150860, 0.327872, 0.367220, 0.504613, 0.559270, 0.409234},
+ { 0.457128, -0.613591, -0.289283, -0.029734, 0.393760, 0.418240},
+ {-0.626043, 0.136489, -0.439118, -0.448323, 0.135987, 0.420869},
+ { 0.526617, 0.480187, 0.242552, -0.488754, -0.158713, 0.411331},
+ {-0.302587, -0.494953, 0.588112, -0.063035, -0.404290, 0.387510},
+ { 0.086378, 0.147714, -0.428875, 0.548300, -0.570121, 0.401391}
+};
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h b/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
new file mode 100644
index 0000000..1eba97c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.h
+ *
+ * This file declares tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+extern const double WebRtcIsac_kQSizeLpcGain;
+
+extern const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES];
+
+extern const WebRtc_Word16 WebRtcIsac_kNumQCellLpcGain[SUBFRAMES];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec0[18];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec1[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec2[26];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec3[46];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec4[78];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec5[171];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES];
+
+extern const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES];
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
new file mode 100644
index 0000000..695d583
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#include "lpc_shape_swb12_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER] =
+{
+ 0.03748928306641, 0.09453441192543, -0.01112522344398, 0.03800237516842
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.00075365493856, -0.05809964887743, -0.23397966154116, 0.97050367376411},
+ { 0.00625021257734, -0.17299965610679, 0.95977735920651, 0.22104179375008},
+ { 0.20543384258374, -0.96202143495696, -0.15301870801552, -0.09432375099565},
+ {-0.97865075648479, -0.20300322280841, -0.02581111653779, -0.01913568980258}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME] =
+{
+ { 0.70650597970460, -0.70770707262373},
+ {-0.70770707262373, -0.70650597970460}
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb12 = 0.150000;
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME] =
+{
+ -0.900000, -1.050000, -1.350000, -1.800000, -1.350000, -1.650000,
+ -2.250000, -3.450000
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 19, 27, 19, 24, 32, 48
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 9, 13, 9, 12, 16, 24
+};
+
+/*
+* The following 8 vectors define CDF of 8 decorrelated LAR
+* coefficients.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec0Ub12[14] =
+{
+ 0, 13, 95, 418, 1687, 6498, 21317, 44200, 59029, 63849, 65147,
+ 65449, 65525, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub12[16] =
+{
+ 0, 10, 59, 255, 858, 2667, 8200, 22609, 42988, 57202, 62947,
+ 64743, 65308, 65476, 65522, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub12[20] =
+{
+ 0, 18, 40, 118, 332, 857, 2017, 4822, 11321, 24330, 41279,
+ 54342, 60637, 63394, 64659, 65184, 65398, 65482, 65518, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub12[28] =
+{
+ 0, 21, 38, 90, 196, 398, 770, 1400, 2589, 4650, 8211,
+ 14933, 26044, 39592, 50814, 57452, 60971, 62884, 63995, 64621, 65019, 65273,
+ 65410, 65480, 65514, 65522, 65531, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub12[20] =
+{
+ 0, 7, 46, 141, 403, 969, 2132, 4649, 10633, 24902, 43254,
+ 54665, 59928, 62674, 64173, 64938, 65293, 65464, 65523, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub12[25] =
+{
+ 0, 7, 22, 72, 174, 411, 854, 1737, 3545, 6774, 13165,
+ 25221, 40980, 52821, 58714, 61706, 63472, 64437, 64989, 65287, 65430, 65503,
+ 65525, 65529, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub12[33] =
+{
+ 0, 11, 21, 36, 65, 128, 228, 401, 707, 1241, 2126,
+ 3589, 6060, 10517, 18853, 31114, 42477, 49770, 54271, 57467, 59838, 61569,
+ 62831, 63772, 64433, 64833, 65123, 65306, 65419, 65466, 65499, 65519, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub12[49] =
+{
+ 0, 14, 34, 67, 107, 167, 245, 326, 449, 645, 861,
+ 1155, 1508, 2003, 2669, 3544, 4592, 5961, 7583, 9887, 13256, 18765,
+ 26519, 34077, 40034, 44349, 47795, 50663, 53262, 55473, 57458, 59122, 60592,
+ 61742, 62690, 63391, 63997, 64463, 64794, 65045, 65207, 65309, 65394, 65443,
+ 65478, 65504, 65514, 65523, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ WebRtcIsac_kLpcShapeCdfVec0Ub12, WebRtcIsac_kLpcShapeCdfVec1Ub12,
+ WebRtcIsac_kLpcShapeCdfVec2Ub12, WebRtcIsac_kLpcShapeCdfVec3Ub12,
+ WebRtcIsac_kLpcShapeCdfVec4Ub12, WebRtcIsac_kLpcShapeCdfVec5Ub12,
+ WebRtcIsac_kLpcShapeCdfVec6Ub12, WebRtcIsac_kLpcShapeCdfVec7Ub12
+};
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
new file mode 100644
index 0000000..1e93847
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb12_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+extern const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kMeanLpcGain;
+
+extern const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb12;
+
+extern const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME];
+
+
+extern const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec0Ub12[14];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub12[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub12[20];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub12[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub12[20];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub12[25];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub12[33];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub12[49];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
new file mode 100644
index 0000000..89f4523
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB16_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#include "lpc_shape_swb16_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER] =
+{
+0.454978, 0.364747, 0.102999, 0.104523
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.020528, -0.085858, -0.002431, 0.996093},
+ {-0.033155, 0.036102, 0.998786, 0.004866},
+ { 0.202627, 0.974853, -0.028940, 0.088132},
+ {-0.978479, 0.202454, -0.039785, -0.002811}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME] =
+{
+ { 0.291675, -0.515786, 0.644927, 0.482658},
+ {-0.647220, 0.479712, 0.289556, 0.516856},
+ { 0.643084, 0.485489, -0.289307, 0.516763},
+ {-0.287185, -0.517823, -0.645389, 0.482553}
+};
+
+/*
+* The following 16 vectors define CDF of 16 decorrelated LAR
+* coefficients.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub16[14] =
+{
+ 0, 2, 20, 159, 1034, 5688, 20892, 44653,
+ 59849, 64485, 65383, 65518, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub16[16] =
+{
+ 0, 1, 7, 43, 276, 1496, 6681, 21653,
+ 43891, 58859, 64022, 65248, 65489, 65529, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub16[18] =
+{
+ 0, 1, 9, 54, 238, 933, 3192, 9461,
+ 23226, 42146, 56138, 62413, 64623, 65300, 65473, 65521,
+ 65533, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub16[30] =
+{
+ 0, 2, 4, 8, 17, 36, 75, 155,
+ 329, 683, 1376, 2662, 5047, 9508, 17526, 29027,
+ 40363, 48997, 55096, 59180, 61789, 63407, 64400, 64967,
+ 65273, 65429, 65497, 65526, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub16[16] =
+{
+ 0, 1, 10, 63, 361, 1785, 7407, 22242,
+ 43337, 58125, 63729, 65181, 65472, 65527, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub16[17] =
+{
+ 0, 1, 7, 29, 134, 599, 2443, 8590,
+ 22962, 42635, 56911, 63060, 64940, 65408, 65513, 65531,
+ 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub16[21] =
+{
+ 0, 1, 5, 16, 57, 191, 611, 1808,
+ 4847, 11755, 24612, 40910, 53789, 60698, 63729, 64924,
+ 65346, 65486, 65523, 65532, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub16[36] =
+{
+ 0, 1, 4, 12, 25, 55, 104, 184,
+ 314, 539, 926, 1550, 2479, 3861, 5892, 8845,
+ 13281, 20018, 29019, 38029, 45581, 51557, 56057, 59284,
+ 61517, 63047, 64030, 64648, 65031, 65261, 65402, 65480,
+ 65518, 65530, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec8Ub16[21] =
+{
+ 0, 1, 2, 7, 26, 103, 351, 1149,
+ 3583, 10204, 23846, 41711, 55361, 61917, 64382, 65186,
+ 65433, 65506, 65528, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub160[21] =
+{
+ 0, 6, 19, 63, 205, 638, 1799, 4784,
+ 11721, 24494, 40803, 53805, 60886, 63822, 64931, 65333,
+ 65472, 65517, 65530, 65533, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub161[28] =
+{
+ 0, 1, 3, 11, 31, 86, 221, 506,
+ 1101, 2296, 4486, 8477, 15356, 26079, 38941, 49952,
+ 57165, 61257, 63426, 64549, 65097, 65351, 65463, 65510,
+ 65526, 65532, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub162[55] =
+{
+ 0, 3, 12, 23, 42, 65, 89, 115,
+ 150, 195, 248, 327, 430, 580, 784, 1099,
+ 1586, 2358, 3651, 5899, 9568, 14312, 19158, 23776,
+ 28267, 32663, 36991, 41153, 45098, 48680, 51870, 54729,
+ 57141, 59158, 60772, 62029, 63000, 63761, 64322, 64728,
+ 65000, 65192, 65321, 65411, 65463, 65496, 65514, 65523,
+ 65527, 65529, 65531, 65532, 65533, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub163[26] =
+{
+ 0, 2, 4, 10, 21, 48, 114, 280,
+ 701, 1765, 4555, 11270, 24267, 41213, 54285, 61003,
+ 63767, 64840, 65254, 65421, 65489, 65514, 65526, 65532,
+ 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub164[28] =
+{
+ 0, 1, 3, 6, 15, 36, 82, 196,
+ 453, 1087, 2557, 5923, 13016, 25366, 40449, 52582,
+ 59539, 62896, 64389, 65033, 65316, 65442, 65494, 65519,
+ 65529, 65533, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub165[34] =
+{
+ 0, 2, 4, 8, 18, 35, 73, 146,
+ 279, 524, 980, 1789, 3235, 5784, 10040, 16998,
+ 27070, 38543, 48499, 55421, 59712, 62257, 63748, 64591,
+ 65041, 65278, 65410, 65474, 65508, 65522, 65530, 65533,
+ 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub166[71] =
+{
+ 0, 1, 2, 6, 13, 26, 55, 92,
+ 141, 191, 242, 296, 355, 429, 522, 636,
+ 777, 947, 1162, 1428, 1753, 2137, 2605, 3140,
+ 3743, 4409, 5164, 6016, 6982, 8118, 9451, 10993,
+ 12754, 14810, 17130, 19780, 22864, 26424, 30547, 35222,
+ 40140, 44716, 48698, 52056, 54850, 57162, 59068, 60643,
+ 61877, 62827, 63561, 64113, 64519, 64807, 65019, 65167,
+ 65272, 65343, 65399, 65440, 65471, 65487, 65500, 65509,
+ 65518, 65524, 65527, 65531, 65533, 65534, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] = {
+ WebRtcIsac_kLpcShapeCdfVec01Ub16,
+ WebRtcIsac_kLpcShapeCdfVec1Ub16,
+ WebRtcIsac_kLpcShapeCdfVec2Ub16,
+ WebRtcIsac_kLpcShapeCdfVec3Ub16,
+ WebRtcIsac_kLpcShapeCdfVec4Ub16,
+ WebRtcIsac_kLpcShapeCdfVec5Ub16,
+ WebRtcIsac_kLpcShapeCdfVec6Ub16,
+ WebRtcIsac_kLpcShapeCdfVec7Ub16,
+ WebRtcIsac_kLpcShapeCdfVec8Ub16,
+ WebRtcIsac_kLpcShapeCdfVec01Ub160,
+ WebRtcIsac_kLpcShapeCdfVec01Ub161,
+ WebRtcIsac_kLpcShapeCdfVec01Ub162,
+ WebRtcIsac_kLpcShapeCdfVec01Ub163,
+ WebRtcIsac_kLpcShapeCdfVec01Ub164,
+ WebRtcIsac_kLpcShapeCdfVec01Ub165,
+ WebRtcIsac_kLpcShapeCdfVec01Ub166
+};
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ -0.8250, -0.9750, -1.1250, -2.1750, -0.9750, -1.1250, -1.4250,
+ -2.6250, -1.4250, -1.2750, -1.8750, -3.6750, -1.7250, -1.8750,
+ -2.3250, -5.4750
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 17, 29, 15, 16, 20, 35, 20,
+ 20, 27, 54, 25, 27, 33, 70
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 8, 14, 7, 8, 10, 17, 10,
+ 10, 13, 27, 12, 13, 16, 35
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb16 = 0.150000;
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
new file mode 100644
index 0000000..68d08b2
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb16_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+
+extern const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub16[14];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub16[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub16[18];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub16[30];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub16[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub16[17];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub16[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub16[36];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec8Ub16[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub160[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub161[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub162[55];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub163[26];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub164[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub165[34];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub166[71];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb16;
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.c b/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
new file mode 100644
index 0000000..985e43c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
@@ -0,0 +1,601 @@
+/*
+ * 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.
+ */
+
+/* coding tables for the KLT coefficients */
+
+#include "lpc_tables.h"
+#include "settings.h"
+
+/* cdf array for model indicator */
+const WebRtc_UWord16 WebRtcIsac_kQKltModelCdf[4] = {
+ 0, 15434, 37548, 65535 };
+
+/* pointer to cdf array for model indicator */
+const WebRtc_UWord16 *WebRtcIsac_kQKltModelCdfPtr[1] = {
+ WebRtcIsac_kQKltModelCdf };
+
+/* initial cdf index for decoder of model indicator */
+const WebRtc_UWord16 WebRtcIsac_kQKltModelInitIndex[1] = { 1 };
+
+/* offset to go from rounded value to quantization index */
+const short WebRtcIsac_kQKltQuantMinGain[12] = {
+ 3, 6, 4, 6, 6, 9, 5, 16, 11, 34, 32, 47 };
+
+
+const short WebRtcIsac_kQKltQuantMinShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 4, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
+ 4, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 2, 3, 4, 4, 5, 7, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 6, 7, 11, 9, 13, 12, 26 };
+
+/* maximum quantization index */
+const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndGain[12] = {
+ 6, 12, 8, 14, 10, 19, 12, 31, 22, 56, 52, 138 };
+
+const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 2, 2, 2, 2, 4, 4, 5, 6, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 2, 2,
+ 2, 2, 3, 4, 5, 7, 0, 0, 0, 0,
+ 2, 0, 2, 2, 2, 2, 3, 2, 2, 4,
+ 4, 6, 6, 9, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 3, 2, 4, 4, 7, 7,
+ 9, 13, 0, 0, 2, 2, 2, 2, 2, 2,
+ 3, 4, 5, 4, 6, 8, 8, 10, 16, 25,
+ 0, 2, 2, 4, 5, 4, 4, 4, 7, 8,
+ 9, 10, 13, 19, 17, 23, 25, 49 };
+
+/* index offset */
+const WebRtc_UWord16 WebRtcIsac_kQKltOffsetGain[12] = {
+ 0, 7, 20, 29, 44, 55, 75, 88, 120, 143, 200, 253 };
+
+const WebRtc_UWord16 WebRtcIsac_kQKltOffsetShape[108] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 14, 17, 20, 23, 28, 33, 39, 46, 47,
+ 48, 49, 50, 52, 53, 54, 55, 56, 58, 61,
+ 64, 67, 70, 74, 79, 85, 93, 94, 95, 96,
+ 97, 100, 101, 104, 107, 110, 113, 117, 120, 123,
+ 128, 133, 140, 147, 157, 158, 159, 160, 161, 164,
+ 167, 170, 173, 176, 179, 183, 186, 191, 196, 204,
+ 212, 222, 236, 237, 238, 241, 244, 247, 250, 253,
+ 256, 260, 265, 271, 276, 283, 292, 301, 312, 329,
+ 355, 356, 359, 362, 367, 373, 378, 383, 388, 396,
+ 405, 415, 426, 440, 460, 478, 502, 528 };
+
+/* initial cdf index for KLT coefficients */
+const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexGain[12] = {
+ 3, 6, 4, 7, 5, 10, 6, 16, 11, 28, 26, 69};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 3, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 2, 1, 1, 2,
+ 2, 3, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 4, 4,
+ 5, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 3, 2, 3, 4, 4, 5, 8, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 5, 7, 10, 9, 12, 13, 25 };
+
+
+/* quantizer representation levels */
+const double WebRtcIsac_kQKltLevelsGain[392] = {
+ -2.78127126, -1.76745590, -0.77913790, -0.00437329, 0.79961206,
+ 1.81775776, 2.81389782, -5.78753143, -4.88384084, -3.89320940,
+ -2.88133610, -1.92859977, -0.86347396, 0.02003888, 0.86140400,
+ 1.89667156, 2.97134967, 3.98781964, 4.91727277, 5.82865898,
+ -4.11195874, -2.80898424, -1.87547977, -0.80943825, -0.00679084,
+ 0.79573851, 1.83953397, 2.67586037, 3.76274082, -6.10933968,
+ -4.93034581, -3.89281296, -2.91530625, -1.89684163, -0.85319130,
+ -0.02275767, 0.86862017, 1.91578276, 2.96107339, 3.96543056,
+ 4.91369908, 5.91058154, 6.83848343, 8.07136925, -5.87470395,
+ -4.84703049, -3.84284597, -2.86168446, -1.89290192, -0.82798145,
+ -0.00080013, 0.82594974, 1.85754329, 2.88351798, 3.96172628,
+ -8.85684885, -7.87387461, -6.97811862, -5.93256270, -4.94301439,
+ -3.95513701, -2.96041544, -1.94031192, -0.87961478, -0.00456201,
+ 0.89911505, 1.91723376, 2.94011511, 3.93302540, 4.97990967,
+ 5.93133404, 7.02181199, 7.92407762, 8.80155440, 10.04665814,
+ -4.82396678, -3.85612158, -2.89482244, -1.89558408, -0.90036978,
+ -0.00677823, 0.90607989, 1.90937981, 2.91175777, 3.91637730,
+ 4.97565723, 5.84771228, 7.11145863, -16.07879840, -15.03776309,
+ -13.93905670, -12.95671800, -11.89171202, -10.95820934, -9.95923714,
+ -8.94357334, -7.99068299, -6.97481009, -5.94826231, -4.96673988,
+ -3.97490466, -2.97846970, -1.95130435, -0.94215262, -0.01444043,
+ 0.96770704, 1.95848598, 2.94107862, 3.95666119, 4.97253085,
+ 5.97191122, 6.93277360, 7.96608727, 8.87958779, 10.00264269,
+ 10.86560820, 12.07449071, 13.04491775, 13.97507061, 14.91845261,
+ -10.85696295, -9.83365357, -9.01245635, -7.95915145, -6.95625003,
+ -5.95362618, -4.93468444, -3.98760978, -2.95044407, -1.97041277,
+ -0.97701799, -0.00840234, 0.97834289, 1.98361415, 2.97802439,
+ 3.96415871, 4.95369042, 5.94101770, 6.92756798, 7.94063998,
+ 8.85951828, 9.97077022, 11.00068503, -33.92030406, -32.81426422,
+ -32.00000000, -31.13243639, -30.11886909, -29.06017570, -28.12598824,
+ -27.22045482, -25.81215858, -25.07849962, -23.93018013, -23.02097643,
+ -21.89529725, -20.99091085, -19.98889048, -18.94327044, -17.96562071,
+ -16.96126218, -15.95054062, -14.98516200, -13.97101012, -13.02106500,
+ -11.98438006, -11.03216748, -9.95930286, -8.97043946, -7.98085082,
+ -6.98360995, -5.98998802, -4.98668173, -4.00032906, -3.00420619,
+ -1.98701132, -0.99324682, -0.00609324, 0.98297834, 1.99483076,
+ 3.00305044, 3.97142097, 4.97525759, 5.98612258, 6.97448236,
+ 7.97575900, 9.01086211, 9.98665542, 11.00541438, 11.98078628,
+ 12.92352471, 14.06849675, 14.99949430, 15.94904834, 16.97440321,
+ 18.04040916, 18.88987609, 20.05312391, 21.00000000, 21.79443341,
+ -31.98578825, -31.00000000, -29.89060567, -28.98555686, -27.97114102,
+ -26.84935410, -26.02402230, -24.94195278, -23.92336849, -22.95552382,
+ -21.97932836, -20.96055470, -19.99649553, -19.03436122, -17.96706525,
+ -17.01139515, -16.01363516, -14.99154248, -14.00298333, -12.99630613,
+ -11.99955519, -10.99000421, -10.00819092, -8.99763648, -7.98431793,
+ -7.01769025, -5.99604690, -4.99980697, -3.99334671, -3.01748192,
+ -2.02051217, -1.00848371, -0.01942358, 1.00477757, 1.95477872,
+ 2.98593031, 3.98779079, 4.96862849, 6.02694771, 6.93983733,
+ 7.89874717, 8.99615862, 10.02367921, 10.96293452, 11.84351528,
+ 12.92207187, 13.85122329, 15.05146877, 15.99371264, 17.00000000,
+ 18.00000000, 19.00000000, 19.82763573, -47.00000000, -46.00000000,
+ -44.87138498, -44.00000000, -43.00000000, -42.00000000, -41.00000000,
+ -39.88966612, -38.98913239, -37.80306486, -37.23584325, -35.94200288,
+ -34.99881301, -34.11361858, -33.06507360, -32.13129135, -30.90891364,
+ -29.81511907, -28.99250380, -28.04535391, -26.99767800, -26.04418164,
+ -24.95687851, -24.04865595, -23.03392645, -21.89366707, -20.93517364,
+ -19.99388660, -18.91620943, -18.03749683, -16.99532379, -15.98683813,
+ -15.06421479, -13.99359211, -12.99714098, -11.97022520, -10.98500279,
+ -9.98834422, -8.95729330, -8.01232284, -7.00253661, -5.99681626,
+ -5.01207817, -3.95914904, -3.01232178, -1.96615919, -0.97687670,
+ 0.01228030, 0.98412288, 2.01753544, 3.00580570, 3.97783510,
+ 4.98846894, 6.01321400, 7.00867732, 8.00416375, 9.01771966,
+ 9.98637729, 10.98255180, 11.99194163, 13.01807333, 14.00999545,
+ 15.00118556, 16.00089224, 17.00584148, 17.98251763, 18.99942091,
+ 19.96917690, 20.97839265, 21.98207297, 23.00171271, 23.99930737,
+ 24.99746061, 26.00936304, 26.98240132, 28.01126868, 29.01395915,
+ 29.98153507, 31.01376711, 31.99876818, 33.00475317, 33.99753994,
+ 34.99493913, 35.98933585, 36.95620160, 37.98428461, 38.99317544,
+ 40.01832073, 40.98048133, 41.95999283, 42.98232091, 43.96523612,
+ 44.99574268, 45.99524194, 47.05464025, 48.03821548, 48.99354366,
+ 49.96400411, 50.98017973, 51.95184408, 52.96291806, 54.00194392,
+ 54.96603783, 55.95623778, 57.03076595, 58.05889901, 58.99081551,
+ 59.97928121, 61.05071612, 62.03971580, 63.01286038, 64.01290338,
+ 65.02074503, 65.99454594, 67.00399425, 67.96571257, 68.95305727,
+ 69.92030664, 70.95594862, 71.98088567, 73.04764124, 74.00285480,
+ 75.02696330, 75.89837673, 76.93459997, 78.16266309, 78.83317543,
+ 80.00000000, 80.87251574, 82.09803524, 83.10671664, 84.00000000,
+ 84.77023523, 86.00000000, 87.00000000, 87.92946897, 88.69159118,
+ 90.00000000, 90.90535270 };
+
+const double WebRtcIsac_kQKltLevelsShape[578] = {
+ 0.00032397, 0.00008053, -0.00061202, -0.00012620, 0.00030437,
+ 0.00054764, -0.00027902, 0.00069360, 0.00029449, -0.80219239,
+ 0.00091089, -0.74514927, -0.00094283, 0.64030631, -0.60509119,
+ 0.00035575, 0.61851665, -0.62129957, 0.00375219, 0.60054900,
+ -0.61554359, 0.00054977, 0.63362016, -1.73118727, -0.65422341,
+ 0.00524568, 0.66165298, 1.76785515, -1.83182018, -0.65997434,
+ -0.00011887, 0.67524299, 1.79933938, -1.76344480, -0.72547708,
+ -0.00133017, 0.73104704, 1.75305377, 2.85164534, -2.80423916,
+ -1.71959639, -0.75419722, -0.00329945, 0.77196760, 1.72211069,
+ 2.87339653, 0.00031089, -0.00015311, 0.00018201, -0.00035035,
+ -0.77357251, 0.00154647, -0.00047625, -0.00045299, 0.00086590,
+ 0.00044762, -0.83383829, 0.00024787, -0.68526258, -0.00122472,
+ 0.64643255, -0.60904942, -0.00448987, 0.62309184, -0.59626442,
+ -0.00574132, 0.62296546, -0.63222115, 0.00013441, 0.63609545,
+ -0.66911055, -0.00369971, 0.66346095, 2.07281301, -1.77184694,
+ -0.67640425, -0.00010145, 0.64818392, 1.74948973, -1.69420224,
+ -0.71943894, -0.00004680, 0.75303493, 1.81075983, 2.80610041,
+ -2.80005755, -1.79866753, -0.77409777, -0.00084220, 0.80141293,
+ 1.78291081, 2.73954236, 3.82994169, 0.00015140, -0.00012766,
+ -0.00034241, -0.00119125, -0.76113497, 0.00069246, 0.76722027,
+ 0.00132862, -0.69107530, 0.00010656, 0.77061578, -0.78012970,
+ 0.00095947, 0.77828502, -0.64787758, 0.00217168, 0.63050167,
+ -0.58601125, 0.00306596, 0.59466308, -0.58603410, 0.00059779,
+ 0.64257970, 1.76512766, -0.61193600, -0.00259517, 0.59767574,
+ -0.61026273, 0.00315811, 0.61725479, -1.69169719, -0.65816029,
+ 0.00067575, 0.65576890, 2.00000000, -1.72689193, -0.69780808,
+ -0.00040990, 0.70668487, 1.74198458, -3.79028154, -3.00000000,
+ -1.73194459, -0.70179341, -0.00106695, 0.71302629, 1.76849782,
+ -2.89332364, -1.78585007, -0.78731491, -0.00132610, 0.79692976,
+ 1.75247009, 2.97828682, -5.26238694, -3.69559829, -2.87286122,
+ -1.84908818, -0.84434577, -0.01167975, 0.84641753, 1.84087672,
+ 2.87628156, 3.83556679, -0.00190204, 0.00092642, 0.00354385,
+ -0.00012982, -0.67742785, 0.00229509, 0.64935672, -0.58444751,
+ 0.00470733, 0.57299534, -0.58456202, -0.00097715, 0.64593607,
+ -0.64060330, -0.00638534, 0.59680157, -0.59287537, 0.00490772,
+ 0.58919707, -0.60306173, -0.00417464, 0.60562100, -1.75218757,
+ -0.63018569, -0.00225922, 0.63863300, -0.63949939, -0.00126421,
+ 0.64268914, -1.75851182, -0.68318060, 0.00510418, 0.69049211,
+ 1.88178506, -1.71136148, -0.72710534, -0.00815559, 0.73412917,
+ 1.79996711, -2.77111145, -1.73940498, -0.78212945, 0.01074476,
+ 0.77688916, 1.76873972, 2.87281379, 3.77554698, -3.75832725,
+ -2.95463235, -1.80451491, -0.80017226, 0.00149902, 0.80729206,
+ 1.78265046, 2.89391793, -3.78236148, -2.83640598, -1.82532067,
+ -0.88844327, -0.00620952, 0.88208030, 1.85757631, 2.81712391,
+ 3.88430176, 5.16179367, -7.00000000, -5.93805408, -4.87172597,
+ -3.87524433, -2.89399744, -1.92359563, -0.92136341, -0.00172725,
+ 0.93087018, 1.90528280, 2.89809686, 3.88085708, 4.89147740,
+ 5.89078692, -0.00239502, 0.00312564, -1.00000000, 0.00178325,
+ 1.00000000, -0.62198029, 0.00143254, 0.65344051, -0.59851220,
+ -0.00676987, 0.61510140, -0.58894151, 0.00385055, 0.59794203,
+ -0.59808568, -0.00038214, 0.57625703, -0.63009713, -0.01107985,
+ 0.61278758, -0.64206758, -0.00154369, 0.65480598, 1.80604162,
+ -1.80909286, -0.67810514, 0.00205762, 0.68571097, 1.79453891,
+ -3.22682422, -1.73808453, -0.71870305, -0.00738594, 0.71486172,
+ 1.73005326, -1.66891897, -0.73689615, -0.00616203, 0.74262409,
+ 1.73807899, -2.92417482, -1.73866741, -0.78133871, 0.00764425,
+ 0.80027264, 1.78668732, 2.74992588, -4.00000000, -2.75578740,
+ -1.83697516, -0.83117035, -0.00355191, 0.83527172, 1.82814700,
+ 2.77377675, 3.80718693, -3.81667698, -2.83575471, -1.83372350,
+ -0.86579471, 0.00547578, 0.87582281, 1.82858793, 2.87265007,
+ 3.91405377, -4.87521600, -3.78999094, -2.86437014, -1.86964365,
+ -0.90618018, 0.00128243, 0.91497811, 1.87374952, 2.83199819,
+ 3.91519130, 4.76632822, -6.68713448, -6.01252467, -4.94587936,
+ -3.88795368, -2.91299088, -1.92592211, -0.95504570, -0.00089980,
+ 0.94565200, 1.93239633, 2.91832808, 3.91363475, 4.88920034,
+ 5.96471415, 6.83905252, 7.86195009, 8.81571018,-12.96141759,
+ -11.73039516,-10.96459719, -9.97382433, -9.04414433, -7.89460619,
+ -6.96628608, -5.93236595, -4.93337924, -3.95479990, -2.96451499,
+ -1.96635876, -0.97271229, -0.00402238, 0.98343930, 1.98348291,
+ 2.96641164, 3.95456471, 4.95517089, 5.98975714, 6.90322073,
+ 7.90468849, 8.85639467, 9.97255498, 10.79006309, 11.81988596,
+ 0.04950500, -1.00000000, -0.01226628, 1.00000000, -0.59479469,
+ -0.10438305, 0.59822144, -2.00000000, -0.67109149, -0.09256692,
+ 0.65171621, 2.00000000, -3.00000000, -1.68391999, -0.76681039,
+ -0.03354151, 0.71509146, 1.77615472, -2.00000000, -0.68661511,
+ -0.02497881, 0.66478398, 2.00000000, -2.00000000, -0.67032784,
+ -0.00920582, 0.64892756, 2.00000000, -2.00000000, -0.68561894,
+ 0.03641869, 0.73021611, 1.68293863, -4.00000000, -2.72024184,
+ -1.80096059, -0.81696185, 0.03604685, 0.79232033, 1.70070730,
+ 3.00000000, -4.00000000, -2.71795670, -1.80482986, -0.86001162,
+ 0.03764903, 0.87723968, 1.79970771, 2.72685932, 3.67589143,
+ -5.00000000, -4.00000000, -2.85492548, -1.78996365, -0.83250358,
+ -0.01376828, 0.84195506, 1.78161105, 2.76754458, 4.00000000,
+ -6.00000000, -5.00000000, -3.82268811, -2.77563624, -1.82608163,
+ -0.86486114, -0.02671886, 0.86693165, 1.88422879, 2.86248347,
+ 3.95632216, -7.00000000, -6.00000000, -5.00000000, -3.77533988,
+ -2.86391432, -1.87052039, -0.90513658, 0.06271236, 0.91083620,
+ 1.85734756, 2.86031688, 3.82019418, 4.94420394, 6.00000000,
+ -11.00000000,-10.00000000, -9.00000000, -8.00000000, -6.91952415,
+ -6.00000000, -4.92044374, -3.87845165, -2.87392362, -1.88413020,
+ -0.91915740, 0.00318517, 0.91602800, 1.89664838, 2.88925058,
+ 3.84123856, 4.78988651, 5.94526812, 6.81953917, 8.00000000,
+ -9.00000000, -8.00000000, -7.03319143, -5.94530963, -4.86669720,
+ -3.92438007, -2.88620396, -1.92848070, -0.94365985, 0.01671855,
+ 0.97349410, 1.93419878, 2.89740109, 3.89662823, 4.83235583,
+ 5.88106535, 6.80328232, 8.00000000,-13.00000000,-12.00000000,
+ -11.00000000,-10.00000000, -9.00000000, -7.86033489, -6.83344055,
+ -5.89844215, -4.90811454, -3.94841298, -2.95820490, -1.98627966,
+ -0.99161468, -0.02286136, 0.96055651, 1.95052433, 2.93969396,
+ 3.94304346, 4.88522624, 5.87434241, 6.78309433, 7.87244101,
+ 9.00000000, 10.00000000,-12.09117356,-11.00000000,-10.00000000,
+ -8.84766108, -7.86934236, -6.98544896, -5.94233429, -4.95583292,
+ -3.95575986, -2.97085529, -1.98955811, -0.99359873, -0.00485413,
+ 0.98298870, 1.98093258, 2.96430203, 3.95540216, 4.96915010,
+ 5.96775124, 6.99236918, 7.96503302, 8.99864542, 9.85857723,
+ 10.96541926, 11.91647197, 12.71060069,-26.00000000,-25.00000000,
+ -24.00585596,-23.11642573,-22.14271284,-20.89800711,-19.87815799,
+ -19.05036354,-17.88555651,-16.86471209,-15.97711073,-14.94012359,
+ -14.02661226,-12.98243228,-11.97489256,-10.97402777, -9.96425624,
+ -9.01085220, -7.97372506, -6.98795002, -5.97271328, -5.00191694,
+ -3.98055849, -2.98458048, -1.99470442, -0.99656768, -0.00825666,
+ 1.00272004, 1.99922218, 2.99357669, 4.01407905, 5.01003897,
+ 5.98115528, 7.00018958, 8.00338125, 8.98981046, 9.98990318,
+ 10.96341479, 11.96866930, 12.99175139, 13.94580443, 14.95745083,
+ 15.98992869, 16.97484646, 17.99630043, 18.93396897, 19.88347741,
+ 20.96532482, 21.92191032, 23.22314702 };
+
+
+/* cdf tables for quantizer indices */
+const WebRtc_UWord16 WebRtcIsac_kQKltCdfGain[404] = {
+ 0, 13, 301, 3730, 61784, 65167, 65489, 65535, 0, 17,
+ 142, 314, 929, 2466, 7678, 56450, 63463, 64740, 65204, 65426,
+ 65527, 65535, 0, 8, 100, 724, 6301, 60105, 65125, 65510,
+ 65531, 65535, 0, 13, 117, 368, 1068, 3010, 11928, 53603,
+ 61177, 63404, 64505, 65108, 65422, 65502, 65531, 65535, 0, 4,
+ 17, 96, 410, 1859, 12125, 54361, 64103, 65305, 65497, 65535,
+ 0, 4, 88, 230, 469, 950, 1746, 3228, 6092, 16592,
+ 44756, 56848, 61256, 63308, 64325, 64920, 65309, 65460, 65502,
+ 65522, 65535, 0, 88, 352, 1675, 6339, 20749, 46686, 59284, 63525,
+ 64949, 65359, 65502, 65527, 65535, 0, 13, 38, 63, 117,
+ 234, 381, 641, 929, 1407, 2043, 2809, 4032, 5753, 8792,
+ 14407, 24308, 38941, 48947, 55403, 59293, 61411, 62688, 63630,
+ 64329, 64840, 65188, 65376, 65472, 65506, 65527, 65531, 65535,
+ 0, 8, 29, 75, 222, 615, 1327, 2801, 5623, 9931, 16094, 24966,
+ 34419, 43458, 50676, 56186, 60055, 62500, 63936, 64765, 65225,
+ 65435, 65514, 65535, 0, 8, 13, 15, 17, 21, 33, 59,
+ 71, 92, 151, 243, 360, 456, 674, 934, 1223, 1583,
+ 1989, 2504, 3031, 3617, 4354, 5154, 6163, 7411, 8780, 10747,
+ 12874, 15591, 18974, 23027, 27436, 32020, 36948, 41830, 46205,
+ 49797, 53042, 56094, 58418, 60360, 61763, 62818, 63559, 64103,
+ 64509, 64798, 65045, 65162, 65288, 65363, 65447, 65506, 65522,
+ 65531, 65533, 65535, 0, 4, 6, 25, 38, 71, 138, 264, 519, 808,
+ 1227, 1825, 2516, 3408, 4279, 5560, 7092, 9197, 11420, 14108,
+ 16947, 20300, 23926, 27459, 31164, 34827, 38575, 42178, 45540,
+ 48747, 51444, 54090, 56426, 58460, 60080, 61595, 62734, 63668,
+ 64275, 64673, 64936, 65112, 65217, 65334, 65426, 65464, 65477,
+ 65489, 65518, 65527, 65529, 65531, 65533, 65535, 0, 2, 4, 8, 10,
+ 12, 14, 16, 21, 33, 50, 71, 84, 92, 105, 138, 180, 255, 318,
+ 377, 435, 473, 511, 590, 682, 758, 913, 1097, 1256, 1449, 1671,
+ 1884, 2169, 2445, 2772, 3157, 3563, 3944, 4375, 4848, 5334, 5820,
+ 6448, 7101, 7716, 8378, 9102, 9956, 10752, 11648, 12707, 13670,
+ 14758, 15910, 17187, 18472, 19627, 20649, 21951, 23169, 24283,
+ 25552, 26862, 28227, 29391, 30764, 31882, 33213, 34432, 35600,
+ 36910, 38116, 39464, 40729, 41872, 43144, 44371, 45514, 46762,
+ 47813, 48968, 50069, 51032, 51974, 52908, 53737, 54603, 55445,
+ 56282, 56990, 57572, 58191, 58840, 59410, 59887, 60264, 60607,
+ 60946, 61269, 61516, 61771, 61960, 62198, 62408, 62558, 62776,
+ 62985, 63207, 63408, 63546, 63739, 63906, 64070, 64237, 64371,
+ 64551, 64677, 64836, 64999, 65095, 65213, 65284, 65338, 65380,
+ 65426, 65447, 65472, 65485, 65487, 65489, 65502, 65510, 65512,
+ 65514, 65516, 65518, 65522, 65531, 65533, 65535 };
+
+
+const WebRtc_UWord16 WebRtcIsac_kQKltCdfShape[686] = {
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4,
+ 65535, 0, 8, 65514, 65535, 0, 29, 65481, 65535, 0,
+ 121, 65439, 65535, 0, 239, 65284, 65535, 0, 8, 779,
+ 64999, 65527, 65535, 0, 8, 888, 64693, 65522, 65535, 0,
+ 29, 2604, 62843, 65497, 65531, 65535, 0, 25, 176, 4576,
+ 61164, 65275, 65527, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 4, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 4, 65535, 0, 33, 65502, 65535,
+ 0, 54, 65481, 65535, 0, 251, 65309, 65535, 0, 611,
+ 65074, 65535, 0, 1273, 64292, 65527, 65535, 0, 4, 1809,
+ 63940, 65518, 65535, 0, 88, 4392, 60603, 65426, 65531, 65535,
+ 0, 25, 419, 7046, 57756, 64961, 65514, 65531, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4, 65531,
+ 65535, 0, 65535, 0, 8, 65531, 65535, 0, 4, 65527,
+ 65535, 0, 17, 65510, 65535, 0, 42, 65481, 65535, 0,
+ 197, 65342, 65531, 65535, 0, 385, 65154, 65535, 0, 1005,
+ 64522, 65535, 0, 8, 1985, 63469, 65533, 65535, 0, 38,
+ 3119, 61884, 65514, 65535, 0, 4, 6, 67, 4961, 60804,
+ 65472, 65535, 0, 17, 565, 9182, 56538, 65087, 65514, 65535,
+ 0, 8, 63, 327, 2118, 14490, 52774, 63839, 65376, 65522,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 17, 65522, 65535, 0, 59, 65489, 65535, 0, 50, 65522,
+ 65535, 0, 54, 65489, 65535, 0, 310, 65179, 65535, 0,
+ 615, 64836, 65535, 0, 4, 1503, 63965, 65535, 0, 2780,
+ 63383, 65535, 0, 21, 3919, 61051, 65527, 65535, 0, 84,
+ 6674, 59929, 65435, 65535, 0, 4, 255, 7976, 55784, 65150,
+ 65518, 65531, 65535, 0, 4, 8, 582, 10726, 53465, 64949,
+ 65518, 65535, 0, 29, 339, 3006, 17555, 49517, 62956, 65200,
+ 65497, 65531, 65535, 0, 2, 33, 138, 565, 2324, 7670,
+ 22089, 45966, 58949, 63479, 64966, 65380, 65518, 65535, 0, 65535,
+ 0, 65535, 0, 2, 65533, 65535, 0, 46, 65514, 65535,
+ 0, 414, 65091, 65535, 0, 540, 64911, 65535, 0, 419,
+ 65162, 65535, 0, 976, 64790, 65535, 0, 2977, 62495, 65531,
+ 65535, 0, 4, 3852, 61034, 65527, 65535, 0, 4, 29,
+ 6021, 60243, 65468, 65535, 0, 84, 6711, 58066, 65418, 65535,
+ 0, 13, 281, 9550, 54917, 65125, 65506, 65535, 0, 2,
+ 63, 984, 12108, 52644, 64342, 65435, 65527, 65535, 0, 29,
+ 251, 2014, 14871, 47553, 62881, 65229, 65518, 65535, 0, 13,
+ 142, 749, 4220, 18497, 45200, 60913, 64823, 65426, 65527, 65535,
+ 0, 13, 71, 264, 1176, 3789, 10500, 24480, 43488, 56324,
+ 62315, 64493, 65242, 65464, 65514, 65522, 65531, 65535, 0, 4,
+ 13, 38, 109, 205, 448, 850, 1708, 3429, 6276, 11371,
+ 19221, 29734, 40955, 49391, 55411, 59460, 62102, 63793, 64656,
+ 65150, 65401, 65485, 65522, 65531, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 1160, 65476, 65535, 0, 2, 6640, 64763, 65533,
+ 65535, 0, 2, 38, 9923, 61009, 65527, 65535, 0, 2,
+ 4949, 63092, 65533, 65535, 0, 2, 3090, 63398, 65533, 65535,
+ 0, 2, 2520, 58744, 65510, 65535, 0, 2, 13, 544,
+ 8784, 51403, 65148, 65533, 65535, 0, 2, 25, 1017, 10412,
+ 43550, 63651, 65489, 65527, 65535, 0, 2, 4, 29, 783,
+ 13377, 52462, 64524, 65495, 65533, 65535, 0, 2, 4, 6,
+ 100, 1817, 18451, 52590, 63559, 65376, 65531, 65535, 0, 2,
+ 4, 6, 46, 385, 2562, 11225, 37416, 60488, 65026, 65487,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 42, 222, 971, 5221, 19811, 45048, 60312, 64486, 65294, 65474,
+ 65525, 65529, 65533, 65535, 0, 2, 4, 8, 71, 167,
+ 666, 2533, 7875, 19622, 38082, 54359, 62108, 64633, 65290, 65495,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 13,
+ 109, 586, 1930, 4949, 11600, 22641, 36125, 48312, 56899, 61495,
+ 63927, 64932, 65389, 65489, 65518, 65531, 65533, 65535, 0, 4,
+ 6, 8, 67, 209, 712, 1838, 4195, 8432, 14432, 22834,
+ 31723, 40523, 48139, 53929, 57865, 60657, 62403, 63584, 64363,
+ 64907, 65167, 65372, 65472, 65514, 65535, 0, 2, 4, 13, 25,
+ 42, 46, 50, 75, 113, 147, 281, 448, 657, 909,
+ 1185, 1591, 1976, 2600, 3676, 5317, 7398, 9914, 12941, 16169,
+ 19477, 22885, 26464, 29851, 33360, 37228, 41139, 44802, 48654,
+ 52058, 55181, 57676, 59581, 61022, 62190, 63107, 63676, 64199,
+ 64547, 64924, 65158, 65313, 65430, 65481, 65518, 65535 };
+
+
+/* pointers to cdf tables for quantizer indices */
+const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrGain[12] = {
+ WebRtcIsac_kQKltCdfGain +0 +0, WebRtcIsac_kQKltCdfGain +0 +8,
+ WebRtcIsac_kQKltCdfGain +0 +22, WebRtcIsac_kQKltCdfGain +0 +32,
+ WebRtcIsac_kQKltCdfGain +0 +48, WebRtcIsac_kQKltCdfGain +0 +60,
+ WebRtcIsac_kQKltCdfGain +0 +81, WebRtcIsac_kQKltCdfGain +0 +95,
+ WebRtcIsac_kQKltCdfGain +0 +128, WebRtcIsac_kQKltCdfGain +0 +152,
+ WebRtcIsac_kQKltCdfGain +0 +210, WebRtcIsac_kQKltCdfGain +0 +264 };
+
+const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrShape[108] = {
+ WebRtcIsac_kQKltCdfShape +0 +0, WebRtcIsac_kQKltCdfShape +0 +2,
+ WebRtcIsac_kQKltCdfShape +0 +4, WebRtcIsac_kQKltCdfShape +0 +6,
+ WebRtcIsac_kQKltCdfShape +0 +8, WebRtcIsac_kQKltCdfShape +0 +10,
+ WebRtcIsac_kQKltCdfShape +0 +12, WebRtcIsac_kQKltCdfShape +0 +14,
+ WebRtcIsac_kQKltCdfShape +0 +16, WebRtcIsac_kQKltCdfShape +0 +18,
+ WebRtcIsac_kQKltCdfShape +0 +21, WebRtcIsac_kQKltCdfShape +0 +25,
+ WebRtcIsac_kQKltCdfShape +0 +29, WebRtcIsac_kQKltCdfShape +0 +33,
+ WebRtcIsac_kQKltCdfShape +0 +37, WebRtcIsac_kQKltCdfShape +0 +43,
+ WebRtcIsac_kQKltCdfShape +0 +49, WebRtcIsac_kQKltCdfShape +0 +56,
+ WebRtcIsac_kQKltCdfShape +0 +64, WebRtcIsac_kQKltCdfShape +0 +66,
+ WebRtcIsac_kQKltCdfShape +0 +68, WebRtcIsac_kQKltCdfShape +0 +70,
+ WebRtcIsac_kQKltCdfShape +0 +72, WebRtcIsac_kQKltCdfShape +0 +75,
+ WebRtcIsac_kQKltCdfShape +0 +77, WebRtcIsac_kQKltCdfShape +0 +79,
+ WebRtcIsac_kQKltCdfShape +0 +81, WebRtcIsac_kQKltCdfShape +0 +83,
+ WebRtcIsac_kQKltCdfShape +0 +86, WebRtcIsac_kQKltCdfShape +0 +90,
+ WebRtcIsac_kQKltCdfShape +0 +94, WebRtcIsac_kQKltCdfShape +0 +98,
+ WebRtcIsac_kQKltCdfShape +0 +102, WebRtcIsac_kQKltCdfShape +0 +107,
+ WebRtcIsac_kQKltCdfShape +0 +113, WebRtcIsac_kQKltCdfShape +0 +120,
+ WebRtcIsac_kQKltCdfShape +0 +129, WebRtcIsac_kQKltCdfShape +0 +131,
+ WebRtcIsac_kQKltCdfShape +0 +133, WebRtcIsac_kQKltCdfShape +0 +135,
+ WebRtcIsac_kQKltCdfShape +0 +137, WebRtcIsac_kQKltCdfShape +0 +141,
+ WebRtcIsac_kQKltCdfShape +0 +143, WebRtcIsac_kQKltCdfShape +0 +147,
+ WebRtcIsac_kQKltCdfShape +0 +151, WebRtcIsac_kQKltCdfShape +0 +155,
+ WebRtcIsac_kQKltCdfShape +0 +159, WebRtcIsac_kQKltCdfShape +0 +164,
+ WebRtcIsac_kQKltCdfShape +0 +168, WebRtcIsac_kQKltCdfShape +0 +172,
+ WebRtcIsac_kQKltCdfShape +0 +178, WebRtcIsac_kQKltCdfShape +0 +184,
+ WebRtcIsac_kQKltCdfShape +0 +192, WebRtcIsac_kQKltCdfShape +0 +200,
+ WebRtcIsac_kQKltCdfShape +0 +211, WebRtcIsac_kQKltCdfShape +0 +213,
+ WebRtcIsac_kQKltCdfShape +0 +215, WebRtcIsac_kQKltCdfShape +0 +217,
+ WebRtcIsac_kQKltCdfShape +0 +219, WebRtcIsac_kQKltCdfShape +0 +223,
+ WebRtcIsac_kQKltCdfShape +0 +227, WebRtcIsac_kQKltCdfShape +0 +231,
+ WebRtcIsac_kQKltCdfShape +0 +235, WebRtcIsac_kQKltCdfShape +0 +239,
+ WebRtcIsac_kQKltCdfShape +0 +243, WebRtcIsac_kQKltCdfShape +0 +248,
+ WebRtcIsac_kQKltCdfShape +0 +252, WebRtcIsac_kQKltCdfShape +0 +258,
+ WebRtcIsac_kQKltCdfShape +0 +264, WebRtcIsac_kQKltCdfShape +0 +273,
+ WebRtcIsac_kQKltCdfShape +0 +282, WebRtcIsac_kQKltCdfShape +0 +293,
+ WebRtcIsac_kQKltCdfShape +0 +308, WebRtcIsac_kQKltCdfShape +0 +310,
+ WebRtcIsac_kQKltCdfShape +0 +312, WebRtcIsac_kQKltCdfShape +0 +316,
+ WebRtcIsac_kQKltCdfShape +0 +320, WebRtcIsac_kQKltCdfShape +0 +324,
+ WebRtcIsac_kQKltCdfShape +0 +328, WebRtcIsac_kQKltCdfShape +0 +332,
+ WebRtcIsac_kQKltCdfShape +0 +336, WebRtcIsac_kQKltCdfShape +0 +341,
+ WebRtcIsac_kQKltCdfShape +0 +347, WebRtcIsac_kQKltCdfShape +0 +354,
+ WebRtcIsac_kQKltCdfShape +0 +360, WebRtcIsac_kQKltCdfShape +0 +368,
+ WebRtcIsac_kQKltCdfShape +0 +378, WebRtcIsac_kQKltCdfShape +0 +388,
+ WebRtcIsac_kQKltCdfShape +0 +400, WebRtcIsac_kQKltCdfShape +0 +418,
+ WebRtcIsac_kQKltCdfShape +0 +445, WebRtcIsac_kQKltCdfShape +0 +447,
+ WebRtcIsac_kQKltCdfShape +0 +451, WebRtcIsac_kQKltCdfShape +0 +455,
+ WebRtcIsac_kQKltCdfShape +0 +461, WebRtcIsac_kQKltCdfShape +0 +468,
+ WebRtcIsac_kQKltCdfShape +0 +474, WebRtcIsac_kQKltCdfShape +0 +480,
+ WebRtcIsac_kQKltCdfShape +0 +486, WebRtcIsac_kQKltCdfShape +0 +495,
+ WebRtcIsac_kQKltCdfShape +0 +505, WebRtcIsac_kQKltCdfShape +0 +516,
+ WebRtcIsac_kQKltCdfShape +0 +528, WebRtcIsac_kQKltCdfShape +0 +543,
+ WebRtcIsac_kQKltCdfShape +0 +564, WebRtcIsac_kQKltCdfShape +0 +583,
+ WebRtcIsac_kQKltCdfShape +0 +608, WebRtcIsac_kQKltCdfShape +0 +635 };
+
+
+/* left KLT transforms */
+const double WebRtcIsac_kKltT1Gain[4] = {
+ -0.79742827, 0.60341375, 0.60341375, 0.79742827 };
+
+const double WebRtcIsac_kKltT1Shape[324] = {
+ 0.00159597, 0.00049320, 0.00513821, 0.00021066, 0.01338581,
+ -0.00422367, -0.00272072, 0.00935107, 0.02047622, 0.02691189,
+ 0.00478236, 0.03969702, 0.00886698, 0.04877604, -0.10898362,
+ -0.05930891, -0.03415047, 0.98889721, 0.00293558, -0.00035282,
+ 0.01156321, -0.00195341, -0.00937631, 0.01052213, -0.02551163,
+ 0.01644059, 0.03189927, 0.07754773, -0.08742313, -0.03026338,
+ 0.05136248, -0.14395974, 0.17725040, 0.22664856, 0.93380230,
+ 0.07076411, 0.00557890, -0.00222834, 0.01377569, 0.01466808,
+ 0.02847361, -0.00603178, 0.02382480, -0.01210452, 0.03797267,
+ -0.02371480, 0.11260335, -0.07366682, 0.00453436, -0.04136941,
+ -0.07912843, -0.95031418, 0.25295337, -0.05302216, -0.00617554,
+ -0.00044040, -0.00653778, 0.01097838, 0.01529174, 0.01374431,
+ -0.00748512, -0.00020034, 0.02432713, 0.11101570, -0.08556891,
+ 0.09282249, -0.01029446, 0.67556443, -0.67454300, 0.06910063,
+ 0.20866865, -0.10318050, 0.00932175, 0.00524058, 0.00803610,
+ -0.00594676, -0.01082578, 0.01069906, 0.00546768, 0.01565291,
+ 0.06816200, 0.10201227, 0.16812734, 0.22984074, 0.58213170,
+ -0.54138651, -0.51379962, 0.06847390, -0.01920037, -0.04592324,
+ -0.00467394, 0.00328858, 0.00377424, -0.00987448, 0.08222096,
+ -0.00377301, 0.04551941, -0.02592517, 0.16317082, 0.13077530,
+ 0.22702921, -0.31215289, -0.69645962, -0.38047101, -0.39339411,
+ 0.11124777, 0.02508035, -0.00708074, 0.00400344, 0.00040331,
+ 0.01142402, 0.01725406, 0.01635170, 0.14285366, 0.03949233,
+ -0.05905676, 0.05877154, -0.17497577, -0.32479440, 0.80754464,
+ -0.38085603, -0.17055430, -0.03168622, -0.07531451, 0.02942002,
+ -0.02148095, -0.00754114, -0.00322372, 0.00567812, -0.01701521,
+ -0.12358320, 0.11473564, 0.09070136, 0.06533068, -0.22560802,
+ 0.19209022, 0.81605094, 0.36592275, -0.09919829, 0.16667122,
+ 0.16300725, 0.04803807, 0.06739263, -0.00156752, -0.01685302,
+ -0.00905240, -0.02297836, -0.00469939, 0.06310613, -0.16391930,
+ 0.10919511, 0.12529293, 0.85581322, -0.32145522, 0.24539076,
+ 0.07181839, 0.07289591, 0.14066759, 0.10406711, 0.05815518,
+ 0.01072680, -0.00759339, 0.00053486, -0.00044865, 0.03407361,
+ 0.01645348, 0.08758579, 0.27722240, 0.53665485, -0.74853376,
+ -0.01118192, -0.19805430, 0.06130619, -0.09675299, 0.08978480,
+ 0.03405255, -0.00706867, 0.05102045, 0.03250746, 0.01849966,
+ -0.01216314, -0.01184187, -0.01579288, 0.00114807, 0.11376166,
+ 0.88342114, -0.36425379, 0.13863190, 0.12524180, -0.13553892,
+ 0.04715856, -0.12341103, 0.04531568, 0.01899360, -0.00206897,
+ 0.00567768, -0.01444163, 0.00411946, -0.00855896, 0.00381663,
+ -0.01664861, -0.05534280, 0.21328278, 0.20161162, 0.72360394,
+ 0.59130708, -0.08043791, 0.08757349, -0.13893918, -0.05147377,
+ 0.02680690, -0.01144070, 0.00625162, -0.00634215, -0.01248947,
+ -0.00329455, -0.00609625, -0.00136305, -0.05097048, -0.01029851,
+ 0.25065384, -0.16856837, -0.07123372, 0.15992623, -0.39487617,
+ -0.79972301, 0.18118185, -0.04826639, -0.01805578, -0.02927253,
+ -0.16400618, 0.07472763, 0.10376449, 0.01705406, 0.01065801,
+ -0.01500498, 0.02039914, 0.37776349, -0.84484186, 0.10434286,
+ 0.15616990, 0.13474456, -0.00906238, -0.25238368, -0.03820885,
+ -0.10650905, -0.03880833, -0.03660028, -0.09640894, 0.00583314,
+ 0.01922097, 0.01489911, -0.02431117, -0.09372217, 0.39404721,
+ -0.84786223, -0.31277121, 0.03193850, 0.01974060, 0.01887901,
+ 0.00337911, -0.11359599, -0.02792521, -0.03220184, -0.01533311,
+ 0.00015962, -0.04225043, -0.00933965, 0.00675311, 0.00206060,
+ 0.15926771, 0.40199829, -0.80792558, -0.35591604, -0.17169764,
+ 0.02830436, 0.02459982, -0.03438589, 0.00718705, -0.01798329,
+ -0.01594508, -0.00702430, -0.00952419, -0.00962701, -0.01307212,
+ -0.01749740, 0.01299602, 0.00587270, -0.36103108, -0.82039266,
+ -0.43092844, -0.08500097, -0.04361674, -0.00333482, 0.01250434,
+ -0.02538295, -0.00921797, 0.01645071, -0.01400872, 0.00317607,
+ 0.00003277, -0.01617646, -0.00616863, -0.00882661, 0.00466157,
+ 0.00353237, 0.91803104, -0.39503305, -0.02048964, 0.00060125,
+ 0.01980634, 0.00300109, 0.00313880, 0.00657337, 0.00715163,
+ 0.00000261, 0.00854276, -0.00154825, -0.00516128, 0.00909527,
+ 0.00095609, 0.00701196, -0.00221867, -0.00156741 };
+
+/* right KLT transforms */
+const double WebRtcIsac_kKltT2Gain[36] = {
+ 0.14572837, -0.45446306, 0.61990621, -0.52197033, 0.32145074,
+ -0.11026900, -0.20698282, 0.48962182, -0.27127933, -0.33627476,
+ 0.65094037, -0.32715751, 0.40262573, -0.47844405, -0.33876075,
+ 0.44130653, 0.37383966, -0.39964662, -0.51730480, 0.06611973,
+ 0.49030187, 0.47512886, -0.02141226, -0.51129451, -0.58578569,
+ -0.39132064, -0.13187771, 0.15649421, 0.40735596, 0.54396897,
+ 0.40381276, 0.40904942, 0.41179766, 0.41167576, 0.40840251,
+ 0.40468132 };
+
+const double WebRtcIsac_kKltT2Shape[36] = {
+ 0.13427386, -0.35132558, 0.52506528, -0.59419077, 0.45075085,
+ -0.16312057, 0.29857439, -0.58660147, 0.34265431, 0.20879510,
+ -0.56063262, 0.30238345, 0.43308283, -0.41186999, -0.35288681,
+ 0.42768996, 0.36094634, -0.45284910, -0.47116680, 0.02893449,
+ 0.54326135, 0.45249040, -0.06264420, -0.52283830, 0.57137758,
+ 0.44298139, 0.12617554, -0.20819946, -0.42324603, -0.48876443,
+ 0.39597050, 0.40713935, 0.41389880, 0.41512486, 0.41130400,
+ 0.40575001 };
+
+/* means of log gains and LAR coefficients*/
+const double WebRtcIsac_kLpcMeansGain[12] = {
+ -6.86881911, -5.35075273, -6.86792680, -5.36200897, -6.86401538,
+ -5.36921533, -6.86802969, -5.36893966, -6.86538097, -5.36315063,
+ -6.85535304, -5.35155315 };
+
+const double WebRtcIsac_kLpcMeansShape[108] = {
+ -0.91232981, 0.26258634, -0.33716701, 0.08477430, -0.03378426,
+ 0.14423909, 0.07036185, 0.06155019, 0.01490385, 0.04138740,
+ 0.01427317, 0.01288970, 0.83872106, 0.25750199, 0.07988929,
+ -0.01957923, 0.00831390, 0.01770300, -0.90957164, 0.25732216,
+ -0.33385344, 0.08735740, -0.03715332, 0.14584917, 0.06998990,
+ 0.06131968, 0.01504379, 0.04067339, 0.01428039, 0.01406460,
+ 0.83846243, 0.26169862, 0.08109025, -0.01767055, 0.00970539,
+ 0.01954310, -0.90490803, 0.24656405, -0.33578607, 0.08843286,
+ -0.03749139, 0.14443959, 0.07214669, 0.06170993, 0.01449947,
+ 0.04134309, 0.01314762, 0.01413471, 0.83895203, 0.26748062,
+ 0.08197507, -0.01781298, 0.00885967, 0.01922394, -0.90922472,
+ 0.24495889, -0.33921540, 0.08877169, -0.03581332, 0.14199172,
+ 0.07444032, 0.06185940, 0.01502054, 0.04185113, 0.01276579,
+ 0.01355457, 0.83645358, 0.26631720, 0.08119697, -0.01835449,
+ 0.00788512, 0.01846446, -0.90482253, 0.24658310, -0.34019734,
+ 0.08281090, -0.03486038, 0.14359248, 0.07401336, 0.06001471,
+ 0.01528421, 0.04254560, 0.01321472, 0.01240799, 0.83857127,
+ 0.26281654, 0.08174380, -0.02099842, 0.00755176, 0.01699448,
+ -0.90132307, 0.25174308, -0.33838268, 0.07883863, -0.02877906,
+ 0.14105407, 0.07220290, 0.06000352, 0.01684879, 0.04226844,
+ 0.01331331, 0.01269244, 0.83832138, 0.25467485, 0.08118028,
+ -0.02120528, 0.00747832, 0.01567212 };
diff --git a/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.h b/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
new file mode 100644
index 0000000..c217804
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+
+#include "structs.h"
+
+#include "settings.h"
+
+#define KLT_STEPSIZE 1.00000000
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_GAIN_SCALE 4.000f
+#define LPC_LOBAND_SCALE 2.100f
+#define LPC_LOBAND_ORDER ORDERLO
+#define LPC_HIBAND_SCALE 0.450f
+#define LPC_HIBAND_ORDER ORDERHI
+#define LPC_GAIN_ORDER 2
+
+#define LPC_SHAPE_ORDER (LPC_LOBAND_ORDER + LPC_HIBAND_ORDER)
+
+#define KLT_ORDER_GAIN (LPC_GAIN_ORDER * SUBFRAMES)
+#define KLT_ORDER_SHAPE (LPC_SHAPE_ORDER * SUBFRAMES)
+
+/* cdf array for model indicator */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltModelCdf[KLT_NUM_MODELS+1];
+
+/* pointer to cdf array for model indicator */
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const short WebRtcIsac_kQKltQuantMinGain[12];
+
+extern const short WebRtcIsac_kQKltQuantMinShape[108];
+
+/* maximum quantization index */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndShape[108];
+
+/* index offset */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOffsetGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOffsetShape[108];
+
+/* initial cdf index for KLT coefficients */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexShape[108];
+
+/* quantizer representation levels */
+extern const double WebRtcIsac_kQKltLevelsGain[392];
+
+extern const double WebRtcIsac_kQKltLevelsShape[578];
+
+/* cdf tables for quantizer indices */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltCdfGain[404];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltCdfShape[686];
+
+/* pointers to cdf tables for quantizer indices */
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrGain[12];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrShape[108];
+
+/* left KLT transforms */
+extern const double WebRtcIsac_kKltT1Gain[4];
+
+extern const double WebRtcIsac_kKltT1Shape[324];
+
+/* right KLT transforms */
+extern const double WebRtcIsac_kKltT2Gain[36];
+
+extern const double WebRtcIsac_kKltT2Shape[36];
+
+/* means of log gains and LAR coefficients */
+extern const double WebRtcIsac_kLpcMeansGain[12];
+
+extern const double WebRtcIsac_kLpcMeansShape[108];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h b/src/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
new file mode 100644
index 0000000..c469c2e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+
+#include <math.h>
+#include "typedefs.h"
+
+// TODO(turaj): switch to WEBRTC_POSIX when available
+#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
+#define WebRtcIsac_lrint lrint
+#elif (defined(WEBRTC_ARCH_X86) && defined(WIN32))
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+
+ __asm {
+ fld x_dbl
+ fistp x_int
+ };
+
+ return x_int;
+}
+#else // Do a slow but correct implementation of lrint
+
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+ x_int = (long int)floor(x_dbl + 0.499999999999);
+ return x_int;
+}
+
+#endif
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c b/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c
new file mode 100644
index 0000000..75525f6
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_estimator.h"
+
+#include <math.h>
+#include <memory.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+static const double kInterpolWin[8] = {-0.00067556028640, 0.02184247643159, -0.12203175715679, 0.60086484101160,
+ 0.60086484101160, -0.12203175715679, 0.02184247643159, -0.00067556028640};
+
+/* interpolation filter */
+__inline static void IntrepolFilter(double *data_ptr, double *intrp)
+{
+ *intrp = kInterpolWin[0] * data_ptr[-3];
+ *intrp += kInterpolWin[1] * data_ptr[-2];
+ *intrp += kInterpolWin[2] * data_ptr[-1];
+ *intrp += kInterpolWin[3] * data_ptr[0];
+ *intrp += kInterpolWin[4] * data_ptr[1];
+ *intrp += kInterpolWin[5] * data_ptr[2];
+ *intrp += kInterpolWin[6] * data_ptr[3];
+ *intrp += kInterpolWin[7] * data_ptr[4];
+}
+
+
+/* 2D parabolic interpolation */
+/* probably some 0.5 factors can be eliminated, and the square-roots can be removed from the Cholesky fact. */
+__inline static void Intrpol2D(double T[3][3], double *x, double *y, double *peak_val)
+{
+ double c, b[2], A[2][2];
+ double t1, t2, d;
+ double delta1, delta2;
+
+
+ // double T[3][3] = {{-1.25, -.25,-.25}, {-.25, .75, .75}, {-.25, .75, .75}};
+ // should result in: delta1 = 0.5; delta2 = 0.0; peak_val = 1.0
+
+ c = T[1][1];
+ b[0] = 0.5 * (T[1][2] + T[2][1] - T[0][1] - T[1][0]);
+ b[1] = 0.5 * (T[1][0] + T[2][1] - T[0][1] - T[1][2]);
+ A[0][1] = -0.5 * (T[0][1] + T[2][1] - T[1][0] - T[1][2]);
+ t1 = 0.5 * (T[0][0] + T[2][2]) - c;
+ t2 = 0.5 * (T[2][0] + T[0][2]) - c;
+ d = (T[0][1] + T[1][2] + T[1][0] + T[2][1]) - 4.0 * c - t1 - t2;
+ A[0][0] = -t1 - 0.5 * d;
+ A[1][1] = -t2 - 0.5 * d;
+
+ /* deal with singularities or ill-conditioned cases */
+ if ( (A[0][0] < 1e-7) || ((A[0][0] * A[1][1] - A[0][1] * A[0][1]) < 1e-7) ) {
+ *peak_val = T[1][1];
+ return;
+ }
+
+ /* Cholesky decomposition: replace A by upper-triangular factor */
+ A[0][0] = sqrt(A[0][0]);
+ A[0][1] = A[0][1] / A[0][0];
+ A[1][1] = sqrt(A[1][1] - A[0][1] * A[0][1]);
+
+ /* compute [x; y] = -0.5 * inv(A) * b */
+ t1 = b[0] / A[0][0];
+ t2 = (b[1] - t1 * A[0][1]) / A[1][1];
+ delta2 = t2 / A[1][1];
+ delta1 = 0.5 * (t1 - delta2 * A[0][1]) / A[0][0];
+ delta2 *= 0.5;
+
+ /* limit norm */
+ t1 = delta1 * delta1 + delta2 * delta2;
+ if (t1 > 1.0) {
+ delta1 /= t1;
+ delta2 /= t1;
+ }
+
+ *peak_val = 0.5 * (b[0] * delta1 + b[1] * delta2) + c;
+
+ *x += delta1;
+ *y += delta2;
+}
+
+
+static void PCorr(const double *in, double *outcorr)
+{
+ double sum, ysum, prod;
+ const double *x, *inptr;
+ int k, n;
+
+ //ysum = 1e-6; /* use this with float (i.s.o. double)! */
+ ysum = 1e-13;
+ sum = 0.0;
+ x = in + PITCH_MAX_LAG/2 + 2;
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ ysum += in[n] * in[n];
+ sum += x[n] * in[n];
+ }
+
+ outcorr += PITCH_LAG_SPAN2 - 1; /* index of last element in array */
+ *outcorr = sum / sqrt(ysum);
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ ysum -= in[k-1] * in[k-1];
+ ysum += in[PITCH_CORR_LEN2 + k - 1] * in[PITCH_CORR_LEN2 + k - 1];
+ sum = 0.0;
+ inptr = &in[k];
+ prod = x[0] * inptr[0];
+ for (n = 1; n < PITCH_CORR_LEN2; n++) {
+ sum += prod;
+ prod = x[n] * inptr[n];
+ }
+ sum += prod;
+ outcorr--;
+ *outcorr = sum / sqrt(ysum);
+ }
+}
+
+
+void WebRtcIsac_InitializePitch(const double *in,
+ const double old_lag,
+ const double old_gain,
+ PitchAnalysisStruct *State,
+ double *lags)
+{
+ double buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+ double ratio, log_lag, gain_bias;
+ double bias;
+ double corrvec1[PITCH_LAG_SPAN2];
+ double corrvec2[PITCH_LAG_SPAN2];
+ int m, k;
+ // Allocating 10 extra entries at the begining of the CorrSurf
+ double corrSurfBuff[10 + (2*PITCH_BW+3)*(PITCH_LAG_SPAN2+4)];
+ double* CorrSurf[2*PITCH_BW+3];
+ double *CorrSurfPtr1, *CorrSurfPtr2;
+ double LagWin[3] = {0.2, 0.5, 0.98};
+ int ind1, ind2, peaks_ind, peak, max_ind;
+ int peaks[PITCH_MAX_NUM_PEAKS];
+ double adj, gain_tmp;
+ double corr, corr_max;
+ double intrp_a, intrp_b, intrp_c, intrp_d;
+ double peak_vals[PITCH_MAX_NUM_PEAKS];
+ double lags1[PITCH_MAX_NUM_PEAKS];
+ double lags2[PITCH_MAX_NUM_PEAKS];
+ double T[3][3];
+ int row;
+
+ for(k = 0; k < 2*PITCH_BW+3; k++)
+ {
+ CorrSurf[k] = &corrSurfBuff[10 + k * (PITCH_LAG_SPAN2+4)];
+ }
+ /* reset CorrSurf matrix */
+ memset(corrSurfBuff, 0, sizeof(double) * (10 + (2*PITCH_BW+3) * (PITCH_LAG_SPAN2+4)));
+
+ //warnings -DH
+ max_ind = 0;
+ peak = 0;
+
+ /* copy old values from state buffer */
+ memcpy(buf_dec, State->dec_buffer, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* decimation; put result after the old values */
+ WebRtcIsac_DecimateAllpass(in, State->decimator_state, PITCH_FRAME_LEN,
+ &buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+ /* low-pass filtering */
+ for (k = PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2; k++)
+ buf_dec[k] += 0.75 * buf_dec[k-1] - 0.25 * buf_dec[k-2];
+
+ /* copy end part back into state buffer */
+ memcpy(State->dec_buffer, buf_dec+PITCH_FRAME_LEN/2, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* compute correlation for first and second half of the frame */
+ PCorr(buf_dec, corrvec1);
+ PCorr(buf_dec + PITCH_CORR_STEP2, corrvec2);
+
+ /* bias towards pitch lag of previous frame */
+ log_lag = log(0.5 * old_lag);
+ gain_bias = 4.0 * old_gain * old_gain;
+ if (gain_bias > 0.8) gain_bias = 0.8;
+ for (k = 0; k < PITCH_LAG_SPAN2; k++)
+ {
+ ratio = log((double) (k + (PITCH_MIN_LAG/2-2))) - log_lag;
+ bias = 1.0 + gain_bias * exp(-5.0 * ratio * ratio);
+ corrvec1[k] *= bias;
+ }
+
+ /* taper correlation functions */
+ for (k = 0; k < 3; k++) {
+ gain_tmp = LagWin[k];
+ corrvec1[k] *= gain_tmp;
+ corrvec2[k] *= gain_tmp;
+ corrvec1[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ corrvec2[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ }
+
+ corr_max = 0.0;
+ /* fill middle row of correlation surface */
+ ind1 = 0;
+ ind2 = 0;
+ CorrSurfPtr1 = &CorrSurf[PITCH_BW][2];
+ for (k = 0; k < PITCH_LAG_SPAN2; k++) {
+ corr = corrvec1[ind1++] + corrvec2[ind2++];
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill first and last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW;
+ CorrSurfPtr1 = &CorrSurf[0][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW][PITCH_BW+2];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.2 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill second and next to last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW-1;
+ CorrSurfPtr1 = &CorrSurf[1][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-1][PITCH_BW+1];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+1; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.9 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill remainder of correlation surface */
+ for (m = 2; m < PITCH_BW; m++) {
+ ind1 = 0;
+ ind2 = PITCH_BW - m; /* always larger than ind1 */
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-m][PITCH_BW+2-m];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+m; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ }
+
+ /* threshold value to qualify as a peak */
+ corr_max *= 0.6;
+
+ peaks_ind = 0;
+ /* find peaks */
+ for (m = 1; m < PITCH_BW+1; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2; k < PITCH_LAG_SPAN2-PITCH_BW-2+m; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+ for (m = PITCH_BW+1; m < 2*PITCH_BW; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2+m-PITCH_BW; k < PITCH_LAG_SPAN2-2; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+
+ if (peaks_ind > 0) {
+ /* examine each peak */
+ CorrSurfPtr1 = &CorrSurf[0][0];
+ for (k = 0; k < peaks_ind; k++) {
+ peak = peaks[k];
+
+ /* compute four interpolated values around current peak */
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)], &intrp_a);
+ IntrepolFilter(&CorrSurfPtr1[peak - 1 ], &intrp_b);
+ IntrepolFilter(&CorrSurfPtr1[peak ], &intrp_c);
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)], &intrp_d);
+
+ /* determine maximum of the interpolated values */
+ corr = CorrSurfPtr1[peak];
+ corr_max = intrp_a;
+ if (intrp_b > corr_max) corr_max = intrp_b;
+ if (intrp_c > corr_max) corr_max = intrp_c;
+ if (intrp_d > corr_max) corr_max = intrp_d;
+
+ /* determine where the peak sits and fill a 3x3 matrix around it */
+ row = peak / (PITCH_LAG_SPAN2+4);
+ lags1[k] = (double) ((peak - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[k] = (double) (lags1[k] + PITCH_BW - row);
+ if ( corr > corr_max ) {
+ T[0][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][1] = corr;
+ T[0][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][0] = intrp_a;
+ T[0][1] = intrp_b;
+ T[2][1] = intrp_c;
+ T[1][2] = intrp_d;
+ } else {
+ if (intrp_a == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] += 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - 2*(PITCH_LAG_SPAN2+5)], &T[0][0]);
+ IntrepolFilter(&CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)], &T[2][0]);
+ T[1][1] = intrp_a;
+ T[0][2] = intrp_b;
+ T[2][2] = intrp_c;
+ T[1][0] = CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)];
+ T[0][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][2] = corr;
+ } else if (intrp_b == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] -= 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+6)], &T[0][0]);
+ T[2][0] = intrp_a;
+ T[1][1] = intrp_b;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+3)], &T[0][2]);
+ T[2][2] = intrp_d;
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[0][1] = CorrSurfPtr1[peak - 1];
+ T[2][1] = corr;
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ } else if (intrp_c == corr_max) {
+ lags1[k] += 0.5;
+ lags2[k] += 0.5;
+ T[0][0] = intrp_a;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)], &T[2][0]);
+ T[1][1] = intrp_c;
+ T[0][2] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)], &T[2][2]);
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[0][1] = corr;
+ T[2][1] = CorrSurfPtr1[peak + 1];
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ } else {
+ lags1[k] += 0.5;
+ lags2[k] -= 0.5;
+ T[0][0] = intrp_b;
+ T[2][0] = intrp_c;
+ T[1][1] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + 2*(PITCH_LAG_SPAN2+4)], &T[0][2]);
+ IntrepolFilter(&CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)], &T[2][2]);
+ T[1][0] = corr;
+ T[0][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][2] = CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)];
+ }
+ }
+
+ /* 2D parabolic interpolation gives more accurate lags and peak value */
+ Intrpol2D(T, &lags1[k], &lags2[k], &peak_vals[k]);
+ }
+
+ /* determine the highest peak, after applying a bias towards short lags */
+ corr_max = 0.0;
+ for (k = 0; k < peaks_ind; k++) {
+ corr = peak_vals[k] * pow(PITCH_PEAK_DECAY, log(lags1[k] + lags2[k]));
+ if (corr > corr_max) {
+ corr_max = corr;
+ peak = k;
+ }
+ }
+
+ lags1[peak] *= 2.0;
+ lags2[peak] *= 2.0;
+
+ if (lags1[peak] < (double) PITCH_MIN_LAG) lags1[peak] = (double) PITCH_MIN_LAG;
+ if (lags2[peak] < (double) PITCH_MIN_LAG) lags2[peak] = (double) PITCH_MIN_LAG;
+ if (lags1[peak] > (double) PITCH_MAX_LAG) lags1[peak] = (double) PITCH_MAX_LAG;
+ if (lags2[peak] > (double) PITCH_MAX_LAG) lags2[peak] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[peak];
+ lags[1] = lags1[peak];
+ lags[2] = lags2[peak];
+ lags[3] = lags2[peak];
+ }
+ else
+ {
+ row = max_ind / (PITCH_LAG_SPAN2+4);
+ lags1[0] = (double) ((max_ind - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[0] = (double) (lags1[0] + PITCH_BW - row);
+
+ if (lags1[0] < (double) PITCH_MIN_LAG) lags1[0] = (double) PITCH_MIN_LAG;
+ if (lags2[0] < (double) PITCH_MIN_LAG) lags2[0] = (double) PITCH_MIN_LAG;
+ if (lags1[0] > (double) PITCH_MAX_LAG) lags1[0] = (double) PITCH_MAX_LAG;
+ if (lags2[0] > (double) PITCH_MAX_LAG) lags2[0] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[0];
+ lags[1] = lags1[0];
+ lags[2] = lags2[0];
+ lags[3] = lags2[0];
+ }
+}
+
+
+
+/* create weighting matrix by orthogonalizing a basis of polynomials of increasing order
+ * t = (0:4)';
+ * A = [t.^0, t.^1, t.^2, t.^3, t.^4];
+ * [Q, dummy] = qr(A);
+ * P.Weight = Q * diag([0, .1, .5, 1, 1]) * Q'; */
+static const double kWeight[5][5] = {
+ { 0.29714285714286, -0.30857142857143, -0.05714285714286, 0.05142857142857, 0.01714285714286},
+ {-0.30857142857143, 0.67428571428571, -0.27142857142857, -0.14571428571429, 0.05142857142857},
+ {-0.05714285714286, -0.27142857142857, 0.65714285714286, -0.27142857142857, -0.05714285714286},
+ { 0.05142857142857, -0.14571428571429, -0.27142857142857, 0.67428571428571, -0.30857142857143},
+ { 0.01714285714286, 0.05142857142857, -0.05714285714286, -0.30857142857143, 0.29714285714286}
+};
+
+
+void WebRtcIsac_PitchAnalysis(const double *in, /* PITCH_FRAME_LEN samples */
+ double *out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ double *lags,
+ double *gains)
+{
+ double HPin[PITCH_FRAME_LEN];
+ double Weighted[PITCH_FRAME_LEN];
+ double Whitened[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double inbuf[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double out_G[PITCH_FRAME_LEN + QLOOKAHEAD]; // could be removed by using out instead
+ double out_dG[4][PITCH_FRAME_LEN + QLOOKAHEAD];
+ double old_lag, old_gain;
+ double nrg_wht, tmp;
+ double Wnrg, Wfluct, Wgain;
+ double H[4][4];
+ double grad[4];
+ double dG[4];
+ int k, m, n, iter;
+
+ /* high pass filtering using second order pole-zero filter */
+ WebRtcIsac_Highpass(in, HPin, State->hp_state, PITCH_FRAME_LEN);
+
+ /* copy from state into buffer */
+ memcpy(Whitened, State->whitened_buf, sizeof(double) * QLOOKAHEAD);
+
+ /* compute weighted and whitened signals */
+ WebRtcIsac_WeightingFilter(HPin, &Weighted[0], &Whitened[QLOOKAHEAD], &(State->Wghtstr));
+
+ /* copy from buffer into state */
+ memcpy(State->whitened_buf, Whitened+PITCH_FRAME_LEN, sizeof(double) * QLOOKAHEAD);
+
+ old_lag = State->PFstr_wght.oldlagp[0];
+ old_gain = State->PFstr_wght.oldgainp[0];
+
+ /* inital pitch estimate */
+ WebRtcIsac_InitializePitch(Weighted, old_lag, old_gain, State, lags);
+
+
+ /* Iterative optimization of lags - to be done */
+
+ /* compute energy of whitened signal */
+ nrg_wht = 0.0;
+ for (k = 0; k < PITCH_FRAME_LEN + QLOOKAHEAD; k++)
+ nrg_wht += Whitened[k] * Whitened[k];
+
+
+ /* Iterative optimization of gains */
+
+ /* set weights for energy, gain fluctiation, and spectral gain penalty functions */
+ Wnrg = 1.0 / nrg_wht;
+ Wgain = 0.005;
+ Wfluct = 3.0;
+
+ /* set initial gains */
+ for (k = 0; k < 4; k++)
+ gains[k] = PITCH_MAX_GAIN_06;
+
+ /* two iterations should be enough */
+ for (iter = 0; iter < 2; iter++) {
+ /* compute Jacobian of pre-filter output towards gains */
+ WebRtcIsac_PitchfilterPre_gains(Whitened, out_G, out_dG, &(State->PFstr_wght), lags, gains);
+
+ /* gradient and approximate Hessian (lower triangle) for minimizing the filter's output power */
+ for (k = 0; k < 4; k++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_G[n] * out_dG[k][n];
+ grad[k] = tmp * Wnrg;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_dG[m][n] * out_dG[k][n];
+ H[k][m] = tmp * Wnrg;
+ }
+ }
+
+ /* add gradient and Hessian (lower triangle) for dampening fast gain changes */
+ for (k = 0; k < 4; k++) {
+ tmp = kWeight[k+1][0] * old_gain;
+ for (m = 0; m < 4; m++)
+ tmp += kWeight[k+1][m+1] * gains[m];
+ grad[k] += tmp * Wfluct;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ H[k][m] += kWeight[k+1][m+1] * Wfluct;
+ }
+ }
+
+ /* add gradient and Hessian for dampening gain */
+ for (k = 0; k < 3; k++) {
+ tmp = 1.0 / (1 - gains[k]);
+ grad[k] += tmp * tmp * Wgain;
+ H[k][k] += 2.0 * tmp * (tmp * tmp * Wgain);
+ }
+ tmp = 1.0 / (1 - gains[3]);
+ grad[3] += 1.33 * (tmp * tmp * Wgain);
+ H[3][3] += 2.66 * tmp * (tmp * tmp * Wgain);
+
+
+ /* compute Cholesky factorization of Hessian
+ * by overwritting the upper triangle; scale factors on diagonal
+ * (for non pc-platforms store the inverse of the diagonals seperately to minimize divisions) */
+ H[0][1] = H[1][0] / H[0][0];
+ H[0][2] = H[2][0] / H[0][0];
+ H[0][3] = H[3][0] / H[0][0];
+ H[1][1] -= H[0][0] * H[0][1] * H[0][1];
+ H[1][2] = (H[2][1] - H[0][1] * H[2][0]) / H[1][1];
+ H[1][3] = (H[3][1] - H[0][1] * H[3][0]) / H[1][1];
+ H[2][2] -= H[0][0] * H[0][2] * H[0][2] + H[1][1] * H[1][2] * H[1][2];
+ H[2][3] = (H[3][2] - H[0][2] * H[3][0] - H[1][2] * H[1][1] * H[1][3]) / H[2][2];
+ H[3][3] -= H[0][0] * H[0][3] * H[0][3] + H[1][1] * H[1][3] * H[1][3] + H[2][2] * H[2][3] * H[2][3];
+
+ /* Compute update as delta_gains = -inv(H) * grad */
+ /* copy and negate */
+ for (k = 0; k < 4; k++)
+ dG[k] = -grad[k];
+ /* back substitution */
+ dG[1] -= dG[0] * H[0][1];
+ dG[2] -= dG[0] * H[0][2] + dG[1] * H[1][2];
+ dG[3] -= dG[0] * H[0][3] + dG[1] * H[1][3] + dG[2] * H[2][3];
+ /* scale */
+ for (k = 0; k < 4; k++)
+ dG[k] /= H[k][k];
+ /* back substitution */
+ dG[2] -= dG[3] * H[2][3];
+ dG[1] -= dG[3] * H[1][3] + dG[2] * H[1][2];
+ dG[0] -= dG[3] * H[0][3] + dG[2] * H[0][2] + dG[1] * H[0][1];
+
+ /* update gains and check range */
+ for (k = 0; k < 4; k++) {
+ gains[k] += dG[k];
+ if (gains[k] > PITCH_MAX_GAIN)
+ gains[k] = PITCH_MAX_GAIN;
+ else if (gains[k] < 0.0)
+ gains[k] = 0.0;
+ }
+ }
+
+ /* update state for next frame */
+ WebRtcIsac_PitchfilterPre(Whitened, out, &(State->PFstr_wght), lags, gains);
+
+ /* concatenate previous input's end and current input */
+ memcpy(inbuf, State->inbuf, sizeof(double) * QLOOKAHEAD);
+ memcpy(inbuf+QLOOKAHEAD, in, sizeof(double) * PITCH_FRAME_LEN);
+
+ /* lookahead pitch filtering for masking analysis */
+ WebRtcIsac_PitchfilterPre_la(inbuf, out, &(State->PFstr), lags, gains);
+
+ /* store last part of input */
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = inbuf[k + PITCH_FRAME_LEN];
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h b/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h
new file mode 100644
index 0000000..f5d9356
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+
+#include "structs.h"
+
+
+
+void WebRtcIsac_PitchAnalysis(const double *in, /* PITCH_FRAME_LEN samples */
+ double *out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_InitializePitch(const double *in,
+ const double old_lag,
+ const double old_gain,
+ PitchAnalysisStruct *State,
+ double *lags);
+
+void WebRtcIsac_PitchfilterPre(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPost(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPre_la(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPre_gains(double *indat,
+ double *outdat,
+ double out_dG[][PITCH_FRAME_LEN + QLOOKAHEAD],
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_WeightingFilter(const double *in, double *weiout, double *whiout, WeightFiltstr *wfdata);
+
+void WebRtcIsac_Highpass(const double *in, double *out, double *state, int N);
+
+void WebRtcIsac_DecimateAllpass(const double *in,
+ double *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ int N, /* number of input samples */
+ double *out); /* array of size N/2 */
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_filter.c b/src/modules/audio_coding/codecs/isac/main/source/pitch_filter.c
new file mode 100644
index 0000000..f03d230
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_filter.c
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+#include "pitch_estimator.h"
+
+#include <math.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#include "os_specific_inline.h"
+
+/*
+ * We are implementing the following filters;
+ *
+ * Pre-filtering:
+ * y(z) = x(z) + damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
+ *
+ * Post-filtering:
+ * y(z) = x(z) - damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
+ *
+ * Note that |lag| is a floating number so we perform an interpolation to
+ * obtain the correct |lag|.
+ *
+ */
+
+static const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25,
+ -0.07};
+
+/* interpolation coefficients; generated by design_pitch_filter.m */
+static const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+ {-0.02239172458614, 0.06653315052934, -0.16515880017569, 0.60701333734125,
+ 0.64671399919202, -0.20249000396417, 0.09926548334755, -0.04765933793109,
+ 0.01754159521746},
+ {-0.01985640750434, 0.05816126837866, -0.13991265473714, 0.44560418147643,
+ 0.79117042386876, -0.20266133815188, 0.09585268418555, -0.04533310458084,
+ 0.01654127246314},
+ {-0.01463300534216, 0.04229888475060, -0.09897034715253, 0.28284326017787,
+ 0.90385267956632, -0.16976950138649, 0.07704272393639, -0.03584218578311,
+ 0.01295781500709},
+ {-0.00764851320885, 0.02184035544377, -0.04985561057281, 0.13083306574393,
+ 0.97545011664662, -0.10177807997561, 0.04400901776474, -0.02010737175166,
+ 0.00719783432422},
+ {-0.00000000000000, 0.00000000000000, -0.00000000000001, 0.00000000000001,
+ 0.99999999999999, 0.00000000000001, -0.00000000000001, 0.00000000000000,
+ -0.00000000000000},
+ {0.00719783432422, -0.02010737175166, 0.04400901776474, -0.10177807997562,
+ 0.97545011664663, 0.13083306574393, -0.04985561057280, 0.02184035544377,
+ -0.00764851320885},
+ {0.01295781500710, -0.03584218578312, 0.07704272393640, -0.16976950138650,
+ 0.90385267956634, 0.28284326017785, -0.09897034715252, 0.04229888475059,
+ -0.01463300534216},
+ {0.01654127246315, -0.04533310458085, 0.09585268418557, -0.20266133815190,
+ 0.79117042386878, 0.44560418147640, -0.13991265473712, 0.05816126837865,
+ -0.01985640750433}
+};
+
+/*
+ * Enumerating the operation of the filter.
+ * iSAC has 4 different pitch-filter which are very similar in their structure.
+ *
+ * kPitchFilterPre : In this mode the filter is operating as pitch
+ * pre-filter. This is used at the encoder.
+ * kPitchFilterPost : In this mode the filter is operating as pitch
+ * post-filter. This is the inverse of pre-filter and used
+ * in the decoder.
+ * kPitchFilterPreLa : This is, in structure, similar to pre-filtering but
+ * utilizing 3 millisecond lookahead. It is used to
+ * obtain the signal for LPC analysis.
+ * kPitchFilterPreGain : This is, in structure, similar to pre-filtering but
+ * differential changes in gain is considered. This is
+ * used to find the optimal gain.
+ */
+typedef enum {
+ kPitchFilterPre, kPitchFilterPost, kPitchFilterPreLa, kPitchFilterPreGain
+} PitchFilterOperation;
+
+/*
+ * Structure with parameters used for pitch-filtering.
+ * buffer : a buffer where the sum of previous inputs and outputs
+ * are stored.
+ * damper_state : the state of the damping filter. The filter is defined by
+ * |kDampFilter|.
+ * interpol_coeff : pointer to a set of coefficient which are used to utilize
+ * fractional pitch by interpolation.
+ * gain : pitch-gain to be applied to the current segment of input.
+ * lag : pitch-lag for the current segment of input.
+ * lag_offset : the offset of lag w.r.t. current sample.
+ * sub_frame : sub-frame index, there are 4 pitch sub-frames in an iSAC
+ * frame.
+ * This specifies the usage of the filter. See
+ * 'PitchFilterOperation' for operational modes.
+ * num_samples : number of samples to be processed in each segment.
+ * index : index of the input and output sample.
+ * damper_state_dg : state of damping filter for different trial gains.
+ * gain_mult : differential changes to gain.
+ */
+typedef struct {
+ double buffer[PITCH_INTBUFFSIZE + QLOOKAHEAD];
+ double damper_state[PITCH_DAMPORDER];
+ const double *interpol_coeff;
+ double gain;
+ double lag;
+ int lag_offset;
+
+ int sub_frame;
+ PitchFilterOperation mode;
+ int num_samples;
+ int index;
+
+ double damper_state_dg[4][PITCH_DAMPORDER];
+ double gain_mult[4];
+} PitchFilterParam;
+
+/**********************************************************************
+ * FilterSegment()
+ * Filter one segment, a quarter of a frame.
+ *
+ * Inputs
+ * in_data : pointer to the input signal of 30 ms at 8 kHz sample-rate.
+ * filter_param : pitch filter parameters.
+ *
+ * Outputs
+ * out_data : pointer to a buffer where the filtered signal is written to.
+ * out_dg : [only used in kPitchFilterPreGain] pointer to a buffer
+ * where the output of different gain values (differential
+ * change to gain) is written.
+ */
+static void FilterSegment(const double* in_data, PitchFilterParam* parameters,
+ double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
+ int n;
+ int m;
+ int j;
+ double sum;
+ double sum2;
+ /* Index of |parameters->buffer| where the output is written to. */
+ int pos = parameters->index + PITCH_BUFFSIZE;
+ /* Index of |parameters->buffer| where samples are read for fractional-lag
+ * computation. */
+ int pos_lag = pos - parameters->lag_offset;
+
+ for (n = 0; n < parameters->num_samples; ++n) {
+ /* Shift low pass filter states. */
+ for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
+ parameters->damper_state[m] = parameters->damper_state[m - 1];
+ }
+ /* Filter to get fractional pitch. */
+ sum = 0.0;
+ for (m = 0; m < PITCH_FRACORDER; ++m) {
+ sum += parameters->buffer[pos_lag + m] * parameters->interpol_coeff[m];
+ }
+ /* Multiply with gain. */
+ parameters->damper_state[0] = parameters->gain * sum;
+
+ if (parameters->mode == kPitchFilterPreGain) {
+ int lag_index = parameters->index - parameters->lag_offset;
+ int m_tmp = (lag_index < 0) ? -lag_index : 0;
+ /* Update the damper state for the new sample. */
+ for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
+ for (j = 0; j < 4; ++j) {
+ parameters->damper_state_dg[j][m] =
+ parameters->damper_state_dg[j][m - 1];
+ }
+ }
+
+ for (j = 0; j < parameters->sub_frame + 1; ++j) {
+ /* Filter for fractional pitch. */
+ sum2 = 0.0;
+ for (m = PITCH_FRACORDER-1; m >= m_tmp; --m) {
+ /* |lag_index + m| is always larger than or equal to zero, see how
+ * m_tmp is computed. This is equivalent to assume samples outside
+ * |out_dg[j]| are zero. */
+ sum2 += out_dg[j][lag_index + m] * parameters->interpol_coeff[m];
+ }
+ /* Add the contribution of differential gain change. */
+ parameters->damper_state_dg[j][0] = parameters->gain_mult[j] * sum +
+ parameters->gain * sum2;
+ }
+
+ /* Filter with damping filter, and store the results. */
+ for (j = 0; j < parameters->sub_frame + 1; ++j) {
+ sum = 0.0;
+ for (m = 0; m < PITCH_DAMPORDER; ++m) {
+ sum -= parameters->damper_state_dg[j][m] * kDampFilter[m];
+ }
+ out_dg[j][parameters->index] = sum;
+ }
+ }
+ /* Filter with damping filter. */
+ sum = 0.0;
+ for (m = 0; m < PITCH_DAMPORDER; ++m) {
+ sum += parameters->damper_state[m] * kDampFilter[m];
+ }
+
+ /* Subtract from input and update buffer. */
+ out_data[parameters->index] = in_data[parameters->index] - sum;
+ parameters->buffer[pos] = in_data[parameters->index] +
+ out_data[parameters->index];
+
+ ++parameters->index;
+ ++pos;
+ ++pos_lag;
+ }
+ return;
+}
+
+/* Update filter parameters based on the pitch-gains and pitch-lags. */
+static void Update(PitchFilterParam* parameters) {
+ double fraction;
+ int fraction_index;
+ /* Compute integer lag-offset. */
+ parameters->lag_offset = WebRtcIsac_lrint(parameters->lag + PITCH_FILTDELAY +
+ 0.5);
+ /* Find correct set of coefficients for computing fractional pitch. */
+ fraction = parameters->lag_offset - (parameters->lag + PITCH_FILTDELAY);
+ fraction_index = WebRtcIsac_lrint(PITCH_FRACS * fraction - 0.5);
+ parameters->interpol_coeff = kIntrpCoef[fraction_index];
+
+ if (parameters->mode == kPitchFilterPreGain) {
+ /* If in this mode make a differential change to pitch gain. */
+ parameters->gain_mult[parameters->sub_frame] += 0.2;
+ if (parameters->gain_mult[parameters->sub_frame] > 1.0) {
+ parameters->gain_mult[parameters->sub_frame] = 1.0;
+ }
+ if (parameters->sub_frame > 0) {
+ parameters->gain_mult[parameters->sub_frame - 1] -= 0.2;
+ }
+ }
+}
+
+/******************************************************************************
+ * FilterFrame()
+ * Filter a frame of 30 millisecond, given pitch-lags and pitch-gains.
+ *
+ * Inputs
+ * in_data : pointer to the input signal of 30 ms at 8 kHz sample-rate.
+ * lags : pointer to pitch-lags, 4 lags per frame.
+ * gains : pointer to pitch-gians, 4 gains per frame.
+ * mode : defining the functionality of the filter. It takes the
+ * following values.
+ * kPitchFilterPre: Pitch pre-filter, used at encoder.
+ * kPitchFilterPost: Pitch post-filter, used at decoder.
+ * kPitchFilterPreLa: Pitch pre-filter with lookahead.
+ * kPitchFilterPreGain: Pitch pre-filter used to otain optimal
+ * pitch-gains.
+ *
+ * Outputs
+ * out_data : pointer to a buffer where the filtered signal is written to.
+ * out_dg : [only used in kPitchFilterPreGain] pointer to a buffer
+ * where the output of different gain values (differential
+ * change to gain) is written.
+ */
+static void FilterFrame(const double* in_data, PitchFiltstr* filter_state,
+ double* lags, double* gains, PitchFilterOperation mode,
+ double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
+ PitchFilterParam filter_parameters;
+ double gain_delta, lag_delta;
+ double old_lag, old_gain;
+ int n;
+ int m;
+ const double kEnhancer = 1.3;
+
+ /* Set up buffer and states. */
+ filter_parameters.index = 0;
+ filter_parameters.lag_offset = 0;
+ filter_parameters.mode = mode;
+ /* Copy states to local variables. */
+ memcpy(filter_parameters.buffer, filter_state->ubuf,
+ sizeof(filter_state->ubuf));
+ memcpy(filter_parameters.damper_state, filter_state->ystate,
+ sizeof(filter_state->ystate));
+
+ if (mode == kPitchFilterPreGain) {
+ /* Clear buffers. */
+ memset(filter_parameters.gain_mult, 0, sizeof(filter_parameters.gain_mult));
+ memset(filter_parameters.damper_state_dg, 0,
+ sizeof(filter_parameters.damper_state_dg));
+ for (n = 0; n < PITCH_SUBFRAMES; ++n) {
+ //memset(out_dg[n], 0, sizeof(double) * (PITCH_FRAME_LEN + QLOOKAHEAD));
+ memset(out_dg[n], 0, sizeof(out_dg[n]));
+ }
+ } else if (mode == kPitchFilterPost) {
+ /* Make output more periodic. Negative sign is to change the structure
+ * of the filter. */
+ for (n = 0; n < PITCH_SUBFRAMES; ++n) {
+ gains[n] *= -kEnhancer;
+ }
+ }
+
+ old_lag = *filter_state->oldlagp;
+ old_gain = *filter_state->oldgainp;
+
+ /* No interpolation if pitch lag step is big. */
+ if ((lags[0] > (PITCH_UPSTEP * old_lag)) ||
+ (lags[0] < (PITCH_DOWNSTEP * old_lag))) {
+ old_lag = lags[0];
+ old_gain = gains[0];
+
+ if (mode == kPitchFilterPreGain) {
+ filter_parameters.gain_mult[0] = 1.0;
+ }
+ }
+
+ filter_parameters.num_samples = PITCH_UPDATE;
+ for (m = 0; m < PITCH_SUBFRAMES; ++m) {
+ /* Set the sub-frame value. */
+ filter_parameters.sub_frame = m;
+ /* Calculate interpolation steps for pitch-lag and pitch-gain. */
+ lag_delta = (lags[m] - old_lag) / PITCH_GRAN_PER_SUBFRAME;
+ filter_parameters.lag = old_lag;
+ gain_delta = (gains[m] - old_gain) / PITCH_GRAN_PER_SUBFRAME;
+ filter_parameters.gain = old_gain;
+ /* Store for the next sub-frame. */
+ old_lag = lags[m];
+ old_gain = gains[m];
+
+ for (n = 0; n < PITCH_GRAN_PER_SUBFRAME; ++n) {
+ /* Step-wise interpolation of pitch gains and lags. As pitch-lag changes,
+ * some parameters of filter need to be update. */
+ filter_parameters.gain += gain_delta;
+ filter_parameters.lag += lag_delta;
+ /* Update parameters according to new lag value. */
+ Update(&filter_parameters);
+ /* Filter a segment of input. */
+ FilterSegment(in_data, &filter_parameters, out_data, out_dg);
+ }
+ }
+
+ if (mode != kPitchFilterPreGain) {
+ /* Export buffer and states. */
+ memcpy(filter_state->ubuf, &filter_parameters.buffer[PITCH_FRAME_LEN],
+ sizeof(filter_state->ubuf));
+ memcpy(filter_state->ystate, filter_parameters.damper_state,
+ sizeof(filter_state->ystate));
+
+ /* Store for the next frame. */
+ *filter_state->oldlagp = old_lag;
+ *filter_state->oldgainp = old_gain;
+ }
+
+ if ((mode == kPitchFilterPreGain) || (mode == kPitchFilterPreLa)) {
+ /* Filter the lookahead segment, this is treated as the last sub-frame. So
+ * set |pf_param| to last sub-frame. */
+ filter_parameters.sub_frame = PITCH_SUBFRAMES - 1;
+ filter_parameters.num_samples = QLOOKAHEAD;
+ FilterSegment(in_data, &filter_parameters, out_data, out_dg);
+ }
+}
+
+void WebRtcIsac_PitchfilterPre(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPre, out_data, NULL);
+}
+
+void WebRtcIsac_PitchfilterPre_la(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreLa, out_data,
+ NULL);
+}
+
+void WebRtcIsac_PitchfilterPre_gains(
+ double* in_data, double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD], PitchFiltstr *pf_state,
+ double* lags, double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreGain, out_data,
+ out_dg);
+}
+
+void WebRtcIsac_PitchfilterPost(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPost, out_data, NULL);
+}
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c b/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
new file mode 100644
index 0000000..5d998a2
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_gain_tables.h"
+
+#include "settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+const WebRtc_UWord16 WebRtcIsac_kQPitchGainCdf[255] = {
+ 0, 2, 4, 6, 64, 901, 903, 905, 16954, 16956,
+ 16961, 17360, 17362, 17364, 17366, 17368, 17370, 17372, 17374, 17411,
+ 17514, 17516, 17583, 18790, 18796, 18802, 20760, 20777, 20782, 21722,
+ 21724, 21728, 21738, 21740, 21742, 21744, 21746, 21748, 22224, 22227,
+ 22230, 23214, 23229, 23239, 25086, 25108, 25120, 26088, 26094, 26098,
+ 26175, 26177, 26179, 26181, 26183, 26185, 26484, 26507, 26522, 27705,
+ 27731, 27750, 29767, 29799, 29817, 30866, 30883, 30885, 31025, 31029,
+ 31031, 31033, 31035, 31037, 31114, 31126, 31134, 32687, 32722, 32767,
+ 35718, 35742, 35757, 36943, 36952, 36954, 37115, 37128, 37130, 37132,
+ 37134, 37136, 37143, 37145, 37152, 38843, 38863, 38897, 47458, 47467,
+ 47474, 49040, 49061, 49063, 49145, 49157, 49159, 49161, 49163, 49165,
+ 49167, 49169, 49171, 49757, 49770, 49782, 61333, 61344, 61346, 62860,
+ 62883, 62885, 62887, 62889, 62891, 62893, 62895, 62897, 62899, 62901,
+ 62903, 62905, 62907, 62909, 65496, 65498, 65500, 65521, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kIndexLowerLimitGain[3] = {
+ -7, -2, -1};
+
+const WebRtc_Word16 WebRtcIsac_kIndexUpperLimitGain[3] = {
+ 0, 3, 1};
+
+const WebRtc_UWord16 WebRtcIsac_kIndexMultsGain[2] = {
+ 18, 3};
+
+/* size of cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQCdfTableSizeGain[1] = {
+ 256};
+
+///////////////////////////FIXED POINT
+/* mean values of pitch filter gains in FIXED point */
+const WebRtc_Word16 WebRtcIsac_kQMeanGain1Q12[144] = {
+ 843, 1092, 1336, 1222, 1405, 1656, 1500, 1815, 1843, 1838, 1839, 1843, 1843, 1843, 1843, 1843,
+ 1843, 1843, 814, 846, 1092, 1013, 1174, 1383, 1391, 1511, 1584, 1734, 1753, 1843, 1843, 1843,
+ 1843, 1843, 1843, 1843, 524, 689, 777, 845, 947, 1069, 1090, 1263, 1380, 1447, 1559, 1676,
+ 1645, 1749, 1843, 1843, 1843, 1843, 81, 477, 563, 611, 706, 806, 849, 1012, 1192, 1128,
+ 1330, 1489, 1425, 1576, 1826, 1741, 1843, 1843, 0, 290, 305, 356, 488, 575, 602, 741,
+ 890, 835, 1079, 1196, 1182, 1376, 1519, 1506, 1680, 1843, 0, 47, 97, 69, 289, 381,
+ 385, 474, 617, 664, 803, 1079, 935, 1160, 1269, 1265, 1506, 1741, 0, 0, 0, 0,
+ 112, 120, 190, 283, 442, 343, 526, 809, 684, 935, 1134, 1020, 1265, 1506, 0, 0,
+ 0, 0, 0, 0, 0, 111, 256, 87, 373, 597, 430, 684, 935, 770, 1020, 1265};
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain2Q12[144] = {
+ 1760, 1525, 1285, 1747, 1671, 1393, 1843, 1826, 1555, 1843, 1784, 1606, 1843, 1843, 1711, 1843,
+ 1843, 1814, 1389, 1275, 1040, 1564, 1414, 1252, 1610, 1495, 1343, 1753, 1592, 1405, 1804, 1720,
+ 1475, 1843, 1814, 1581, 1208, 1061, 856, 1349, 1148, 994, 1390, 1253, 1111, 1495, 1343, 1178,
+ 1770, 1465, 1234, 1814, 1581, 1342, 1040, 793, 713, 1053, 895, 737, 1128, 1003, 861, 1277,
+ 1094, 981, 1475, 1192, 1019, 1581, 1342, 1098, 855, 570, 483, 833, 648, 540, 948, 744,
+ 572, 1009, 844, 636, 1234, 934, 685, 1342, 1217, 984, 537, 318, 124, 603, 423, 350,
+ 687, 479, 322, 791, 581, 430, 987, 671, 488, 1098, 849, 597, 283, 27, 0, 397,
+ 222, 38, 513, 271, 124, 624, 325, 157, 737, 484, 233, 849, 597, 343, 27, 0,
+ 0, 141, 0, 0, 256, 69, 0, 370, 87, 0, 484, 229, 0, 597, 343, 87};
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain3Q12[144] = {
+ 1843, 1843, 1711, 1843, 1818, 1606, 1843, 1827, 1511, 1814, 1639, 1393, 1760, 1525, 1285, 1656,
+ 1419, 1176, 1835, 1718, 1475, 1841, 1650, 1387, 1648, 1498, 1287, 1600, 1411, 1176, 1522, 1299,
+ 1040, 1419, 1176, 928, 1773, 1461, 1128, 1532, 1355, 1202, 1429, 1260, 1115, 1398, 1151, 1025,
+ 1172, 1080, 790, 1176, 928, 677, 1475, 1147, 1019, 1276, 1096, 922, 1214, 1010, 901, 1057,
+ 893, 800, 1040, 796, 734, 928, 677, 424, 1137, 897, 753, 1120, 830, 710, 875, 751,
+ 601, 795, 642, 583, 790, 544, 475, 677, 474, 140, 987, 750, 482, 697, 573, 450,
+ 691, 487, 303, 661, 394, 332, 537, 303, 220, 424, 168, 0, 737, 484, 229, 624,
+ 348, 153, 441, 261, 136, 397, 166, 51, 283, 27, 0, 168, 0, 0, 484, 229,
+ 0, 370, 57, 0, 256, 43, 0, 141, 0, 0, 27, 0, 0, 0, 0, 0};
+
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain4Q12[144] = {
+ 1843, 1843, 1843, 1843, 1841, 1843, 1500, 1821, 1843, 1222, 1434, 1656, 843, 1092, 1336, 504,
+ 757, 1007, 1843, 1843, 1843, 1838, 1791, 1843, 1265, 1505, 1599, 965, 1219, 1425, 730, 821,
+ 1092, 249, 504, 757, 1783, 1819, 1843, 1351, 1567, 1727, 1096, 1268, 1409, 805, 961, 1131,
+ 444, 670, 843, 0, 249, 504, 1425, 1655, 1743, 1096, 1324, 1448, 822, 1019, 1199, 490,
+ 704, 867, 81, 450, 555, 0, 0, 249, 1247, 1428, 1530, 881, 1073, 1283, 610, 759,
+ 939, 278, 464, 645, 0, 200, 270, 0, 0, 0, 935, 1163, 1410, 528, 790, 1068,
+ 377, 499, 717, 173, 240, 274, 0, 43, 62, 0, 0, 0, 684, 935, 1182, 343,
+ 551, 735, 161, 262, 423, 0, 55, 27, 0, 0, 0, 0, 0, 0, 430, 684,
+ 935, 87, 377, 597, 0, 46, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h b/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
new file mode 100644
index 0000000..f958f5d
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include "typedefs.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kIndexLowerLimitGain[3];
+
+extern const WebRtc_Word16 WebRtcIsac_kIndexUpperLimitGain[3];
+extern const WebRtc_UWord16 WebRtcIsac_kIndexMultsGain[2];
+
+/* mean values of pitch filter gains */
+//(Y)
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain1Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain2Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain3Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain4Q12[144];
+//(Y)
+
+/* size of cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQCdfTableSizeGain[1];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c b/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
new file mode 100644
index 0000000..72a031e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_lag_tables.h"
+#include "settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Lo[127] = {
+ 0, 134, 336, 549, 778, 998, 1264, 1512, 1777, 2070,
+ 2423, 2794, 3051, 3361, 3708, 3979, 4315, 4610, 4933, 5269,
+ 5575, 5896, 6155, 6480, 6816, 7129, 7477, 7764, 8061, 8358,
+ 8718, 9020, 9390, 9783, 10177, 10543, 10885, 11342, 11795, 12213,
+ 12680, 13096, 13524, 13919, 14436, 14903, 15349, 15795, 16267, 16734,
+ 17266, 17697, 18130, 18632, 19080, 19447, 19884, 20315, 20735, 21288,
+ 21764, 22264, 22723, 23193, 23680, 24111, 24557, 25022, 25537, 26082,
+ 26543, 27090, 27620, 28139, 28652, 29149, 29634, 30175, 30692, 31273,
+ 31866, 32506, 33059, 33650, 34296, 34955, 35629, 36295, 36967, 37726,
+ 38559, 39458, 40364, 41293, 42256, 43215, 44231, 45253, 46274, 47359,
+ 48482, 49678, 50810, 51853, 53016, 54148, 55235, 56263, 57282, 58363,
+ 59288, 60179, 61076, 61806, 62474, 63129, 63656, 64160, 64533, 64856,
+ 65152, 65535, 65535, 65535, 65535, 65535, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Lo[20] = {
+ 0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
+ 42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Lo[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Lo[10] = {
+ 0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrLo[4] = {WebRtcIsac_kQPitchLagCdf1Lo, WebRtcIsac_kQPitchLagCdf2Lo, WebRtcIsac_kQPitchLagCdf3Lo, WebRtcIsac_kQPitchLagCdf4Lo};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeLo[1] = {128};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagLo[4] = {
+-140, -9, 0, -4};
+
+const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagLo[4] = {
+-20, 9, 0, 4};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagLo[3] = {
+ 10, 1, 5};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Lo[19] = {
+-17.21385070, -15.82678944, -14.07123081, -12.03003877, -10.01311864, -8.00794627, -5.91162987, -3.89231876, -1.90220980, -0.01879275,
+ 1.89144232, 3.88123171, 5.92146992, 7.96435361, 9.98923648, 11.98266347, 13.96101002, 15.74855713, 17.10976611};
+
+const double WebRtcIsac_kQMeanLag3Lo[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Lo[9] = {
+-7.76246496, -5.92083980, -3.94095226, -1.89502305, 0.03724681, 1.93054221, 3.96443467, 5.91726366, 7.78434291};
+
+const double WebRtcIsac_kQPitchLagStepsizeLo = 2.000000;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Mid[255] = {
+ 0, 28, 61, 88, 121, 149, 233, 331, 475, 559,
+ 624, 661, 689, 712, 745, 791, 815, 843, 866, 922,
+ 959, 1024, 1061, 1117, 1178, 1238, 1280, 1350, 1453, 1513,
+ 1564, 1625, 1671, 1741, 1788, 1904, 2072, 2421, 2626, 2770,
+ 2840, 2900, 2942, 3012, 3068, 3115, 3147, 3194, 3254, 3319,
+ 3366, 3520, 3678, 3780, 3850, 3911, 3957, 4032, 4106, 4185,
+ 4292, 4474, 4683, 4842, 5019, 5191, 5321, 5428, 5540, 5675,
+ 5763, 5847, 5959, 6127, 6304, 6564, 6839, 7090, 7263, 7421,
+ 7556, 7728, 7872, 7984, 8142, 8361, 8580, 8743, 8938, 9227,
+ 9409, 9539, 9674, 9795, 9930, 10060, 10177, 10382, 10614, 10861,
+ 11038, 11271, 11415, 11629, 11792, 12044, 12193, 12416, 12574, 12821,
+ 13007, 13235, 13445, 13654, 13901, 14134, 14488, 15000, 15703, 16285,
+ 16504, 16797, 17086, 17328, 17579, 17807, 17998, 18268, 18538, 18836,
+ 19087, 19274, 19474, 19716, 19935, 20270, 20833, 21303, 21532, 21741,
+ 21978, 22207, 22523, 22770, 23054, 23613, 23943, 24204, 24399, 24651,
+ 24832, 25074, 25270, 25549, 25759, 26015, 26150, 26424, 26713, 27048,
+ 27342, 27504, 27681, 27854, 28021, 28207, 28412, 28664, 28859, 29064,
+ 29278, 29548, 29748, 30107, 30377, 30656, 30856, 31164, 31452, 31755,
+ 32011, 32328, 32626, 32919, 33319, 33789, 34329, 34925, 35396, 35973,
+ 36443, 36964, 37551, 38156, 38724, 39357, 40023, 40908, 41587, 42602,
+ 43924, 45037, 45810, 46597, 47421, 48291, 49092, 50051, 51448, 52719,
+ 53440, 54241, 54944, 55977, 56676, 57299, 57872, 58389, 59059, 59688,
+ 60237, 60782, 61094, 61573, 61890, 62290, 62658, 63030, 63217, 63454,
+ 63622, 63882, 64003, 64273, 64427, 64529, 64581, 64697, 64758, 64902,
+ 65414, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Mid[36] = {
+ 0, 71, 335, 581, 836, 1039, 1323, 1795, 2258, 2608,
+ 3005, 3591, 4243, 5344, 7163, 10583, 16848, 28078, 49448, 57007,
+ 60357, 61850, 62837, 63437, 63872, 64188, 64377, 64614, 64774, 64949,
+ 65039, 65115, 65223, 65360, 65474, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Mid[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Mid[20] = {
+ 0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
+ 44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrMid[4] = {WebRtcIsac_kQPitchLagCdf1Mid, WebRtcIsac_kQPitchLagCdf2Mid, WebRtcIsac_kQPitchLagCdf3Mid, WebRtcIsac_kQPitchLagCdf4Mid};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeMid[1] = {256};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagMid[4] = {
+-280, -17, 0, -9};
+
+const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagMid[4] = {
+-40, 17, 0, 9};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagMid[3] = {
+ 18, 1, 10};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Mid[35] = {
+-16.89183900, -15.86949778, -15.05476653, -14.00664348, -13.02793036, -12.07324237, -11.00542532, -10.11250602, -8.90792971, -8.02474753,
+-7.00426767, -5.94055287, -4.98251338, -3.91053158, -2.98820425, -1.93524245, -0.92978085, -0.01722509, 0.91317387, 1.92973955,
+ 2.96908851, 3.93728974, 4.96308471, 5.92244151, 7.08673497, 8.00993708, 9.04656316, 9.98538742, 10.97851694, 11.94772884,
+ 13.02426166, 14.00039951, 15.01347042, 15.80758023, 16.94086895};
+
+const double WebRtcIsac_kQMeanLag3Mid[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Mid[19] = {
+-8.60409403, -7.89198395, -7.03450280, -5.86260421, -4.93822322, -3.93078706, -2.91302322, -1.91824007, -0.87003282, 0.02822649,
+ 0.89951758, 1.87495484, 2.91802604, 3.96874074, 5.06571703, 5.93618227, 7.00520185, 7.88497726, 8.64160364};
+
+const double WebRtcIsac_kQPitchLagStepsizeMid = 1.000000;
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Hi[511] = {
+ 0, 7, 18, 33, 69, 105, 156, 228, 315, 612,
+ 680, 691, 709, 724, 735, 738, 742, 746, 749, 753,
+ 756, 760, 764, 774, 782, 785, 789, 796, 800, 803,
+ 807, 814, 818, 822, 829, 832, 847, 854, 858, 869,
+ 876, 883, 898, 908, 934, 977, 1010, 1050, 1060, 1064,
+ 1075, 1078, 1086, 1089, 1093, 1104, 1111, 1122, 1133, 1136,
+ 1151, 1162, 1183, 1209, 1252, 1281, 1339, 1364, 1386, 1401,
+ 1411, 1415, 1426, 1430, 1433, 1440, 1448, 1455, 1462, 1477,
+ 1487, 1495, 1502, 1506, 1509, 1516, 1524, 1531, 1535, 1542,
+ 1553, 1556, 1578, 1589, 1611, 1625, 1639, 1643, 1654, 1665,
+ 1672, 1687, 1694, 1705, 1708, 1719, 1730, 1744, 1752, 1759,
+ 1791, 1795, 1820, 1867, 1886, 1915, 1936, 1943, 1965, 1987,
+ 2041, 2099, 2161, 2175, 2200, 2211, 2226, 2233, 2244, 2251,
+ 2266, 2280, 2287, 2298, 2309, 2316, 2331, 2342, 2356, 2378,
+ 2403, 2418, 2447, 2497, 2544, 2602, 2863, 2895, 2903, 2935,
+ 2950, 2971, 3004, 3011, 3018, 3029, 3040, 3062, 3087, 3127,
+ 3152, 3170, 3199, 3243, 3293, 3322, 3340, 3377, 3402, 3427,
+ 3474, 3518, 3543, 3579, 3601, 3637, 3659, 3706, 3731, 3760,
+ 3818, 3847, 3869, 3901, 3920, 3952, 4068, 4169, 4220, 4271,
+ 4524, 4571, 4604, 4632, 4672, 4730, 4777, 4806, 4857, 4904,
+ 4951, 5002, 5031, 5060, 5107, 5150, 5212, 5266, 5331, 5382,
+ 5432, 5490, 5544, 5610, 5700, 5762, 5812, 5874, 5972, 6022,
+ 6091, 6163, 6232, 6305, 6402, 6540, 6685, 6880, 7090, 7271,
+ 7379, 7452, 7542, 7625, 7687, 7770, 7843, 7911, 7966, 8024,
+ 8096, 8190, 8252, 8320, 8411, 8501, 8585, 8639, 8751, 8842,
+ 8918, 8986, 9066, 9127, 9203, 9269, 9345, 9406, 9464, 9536,
+ 9612, 9667, 9735, 9844, 9931, 10036, 10119, 10199, 10260, 10358,
+ 10441, 10514, 10666, 10734, 10872, 10951, 11053, 11125, 11223, 11324,
+ 11516, 11664, 11737, 11816, 11892, 12008, 12120, 12200, 12280, 12392,
+ 12490, 12576, 12685, 12812, 12917, 13003, 13108, 13210, 13300, 13384,
+ 13470, 13579, 13673, 13771, 13879, 13999, 14136, 14201, 14368, 14614,
+ 14759, 14867, 14958, 15030, 15121, 15189, 15280, 15385, 15461, 15555,
+ 15653, 15768, 15884, 15971, 16069, 16145, 16210, 16279, 16380, 16463,
+ 16539, 16615, 16688, 16818, 16919, 17017, 18041, 18338, 18523, 18649,
+ 18790, 18917, 19047, 19167, 19315, 19460, 19601, 19731, 19858, 20068,
+ 20173, 20318, 20466, 20625, 20741, 20911, 21045, 21201, 21396, 21588,
+ 21816, 22022, 22305, 22547, 22786, 23072, 23322, 23600, 23879, 24168,
+ 24433, 24769, 25120, 25511, 25895, 26289, 26792, 27219, 27683, 28077,
+ 28566, 29094, 29546, 29977, 30491, 30991, 31573, 32105, 32594, 33173,
+ 33788, 34497, 35181, 35833, 36488, 37255, 37921, 38645, 39275, 39894,
+ 40505, 41167, 41790, 42431, 43096, 43723, 44385, 45134, 45858, 46607,
+ 47349, 48091, 48768, 49405, 49955, 50555, 51167, 51985, 52611, 53078,
+ 53494, 53965, 54435, 54996, 55601, 56125, 56563, 56838, 57244, 57566,
+ 57967, 58297, 58771, 59093, 59419, 59647, 59886, 60143, 60461, 60693,
+ 60917, 61170, 61416, 61634, 61891, 62122, 62310, 62455, 62632, 62839,
+ 63103, 63436, 63639, 63805, 63906, 64015, 64192, 64355, 64475, 64558,
+ 64663, 64742, 64811, 64865, 64916, 64956, 64981, 65025, 65068, 65115,
+ 65195, 65314, 65419, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Hi[68] = {
+ 0, 7, 11, 22, 37, 52, 56, 59, 81, 85,
+ 89, 96, 115, 130, 137, 152, 170, 181, 193, 200,
+ 207, 233, 237, 259, 289, 318, 363, 433, 592, 992,
+ 1607, 3062, 6149, 12206, 25522, 48368, 58223, 61918, 63640, 64584,
+ 64943, 65098, 65206, 65268, 65294, 65335, 65350, 65372, 65387, 65402,
+ 65413, 65420, 65428, 65435, 65439, 65450, 65454, 65468, 65472, 65476,
+ 65483, 65491, 65498, 65505, 65516, 65520, 65528, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Hi[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Hi[35] = {
+ 0, 7, 19, 30, 41, 48, 63, 74, 82, 96,
+ 122, 152, 215, 330, 701, 2611, 10931, 48106, 61177, 64341,
+ 65112, 65238, 65309, 65338, 65364, 65379, 65401, 65427, 65453, 65465,
+ 65476, 65490, 65509, 65528, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrHi[4] = {WebRtcIsac_kQPitchLagCdf1Hi, WebRtcIsac_kQPitchLagCdf2Hi, WebRtcIsac_kQPitchLagCdf3Hi, WebRtcIsac_kQPitchLagCdf4Hi};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeHi[1] = {512};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQindexLowerLimitLagHi[4] = {
+-552, -34, 0, -16};
+
+const WebRtc_Word16 WebRtcIsac_kQindexUpperLimitLagHi[4] = {
+-80, 32, 0, 17};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagHi[3] = {
+ 34, 1, 18};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Hi[67] = {
+-17.07263295, -16.50000000, -15.83966081, -15.55613708, -14.96948007, -14.50000000, -14.00000000, -13.48377986, -13.00000000, -12.50000000,
+-11.93199636, -11.44530414, -11.04197641, -10.39910301, -10.15202337, -9.51322461, -8.93357741, -8.46456632, -8.10270672, -7.53751847,
+-6.98686404, -6.50000000, -6.08463150, -5.46872991, -5.00864717, -4.50163760, -4.01382410, -3.43856708, -2.96898001, -2.46554810,
+-1.96861004, -1.47106701, -0.97197237, -0.46561654, -0.00531409, 0.45767857, 0.96777907, 1.47507903, 1.97740425, 2.46695420,
+ 3.00695774, 3.47167185, 4.02712538, 4.49280007, 5.01087640, 5.48191963, 6.04916550, 6.51511058, 6.97297819, 7.46565499,
+ 8.01489405, 8.39912001, 8.91819757, 9.50000000, 10.11654065, 10.50000000, 11.03712583, 11.50000000, 12.00000000, 12.38964346,
+ 12.89466127, 13.43657881, 13.96013840, 14.46279912, 15.00000000, 15.39412269, 15.96662441};
+
+const double WebRtcIsac_kQMeanLag3Hi[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Hi[34] = {
+-7.98331221, -7.47988769, -7.03626557, -6.52708003, -6.06982173, -5.51856292, -5.05827033, -4.45909878, -3.99125864, -3.45308135,
+-3.02328139, -2.47297273, -1.94341995, -1.44699056, -0.93612243, -0.43012406, 0.01120357, 0.44054812, 0.93199883, 1.45669587,
+ 1.97218322, 2.50187419, 2.98748690, 3.49343202, 4.01660147, 4.50984306, 5.01402683, 5.58936797, 5.91787793, 6.59998900,
+ 6.85034315, 7.53503316, 7.87711194, 8.53631648};
+
+const double WebRtcIsac_kQPitchLagStepsizeHi = 0.500000;
+
+/* transform matrix */
+const double WebRtcIsac_kTransform[4][4] = {
+{-0.50000000, -0.50000000, -0.50000000, -0.50000000},
+{ 0.67082039, 0.22360680, -0.22360680, -0.67082039},
+{ 0.50000000, -0.50000000, -0.50000000, 0.50000000},
+{ 0.22360680, -0.67082039, 0.67082039, -0.22360680}};
+
+/* transpose transform matrix */
+const double WebRtcIsac_kTransformTranspose[4][4] = {
+{-0.50000000, 0.67082039, 0.50000000, 0.22360680},
+{-0.50000000, 0.22360680, -0.50000000, -0.67082039},
+{-0.50000000, -0.22360680, -0.50000000, 0.67082039},
+{-0.50000000, -0.67082039, 0.50000000, -0.22360680}};
+
diff --git a/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h b/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
new file mode 100644
index 0000000..67b02e5
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+
+#include "typedefs.h"
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Lag Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Lo[127];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Lo[20];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Lo[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Lo[10];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrLo[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeLo[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagLo[4];
+extern const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagLo[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagLo[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Lo[19];
+extern const double WebRtcIsac_kQMeanLag3Lo[1];
+extern const double WebRtcIsac_kQMeanLag4Lo[9];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeLo;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Mid[255];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Mid[36];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Mid[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Mid[20];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrMid[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeMid[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagMid[4];
+extern const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagMid[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagMid[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Mid[35];
+extern const double WebRtcIsac_kQMeanLag3Mid[1];
+extern const double WebRtcIsac_kQMeanLag4Mid[19];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeMid;
+
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Hi[511];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Hi[68];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Hi[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Hi[35];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrHi[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeHi[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQindexLowerLimitLagHi[4];
+extern const WebRtc_Word16 WebRtcIsac_kQindexUpperLimitLagHi[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagHi[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Hi[67];
+extern const double WebRtcIsac_kQMeanLag3Hi[1];
+extern const double WebRtcIsac_kQMeanLag4Hi[34];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeHi;
+
+/* transform matrix */
+extern const double WebRtcIsac_kTransform[4][4];
+
+/* transpose transform matrix */
+extern const double WebRtcIsac_kTransformTranspose[4][4];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/settings.h b/src/modules/audio_coding/codecs/isac/main/source/settings.h
new file mode 100644
index 0000000..9c1ec1e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/settings.h
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+
+/* sampling frequency (Hz) */
+#define FS 16000
+
+/* number of samples per frame (either 320 (20ms), 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+
+#define MAXFFTSIZE 2048
+#define NFACTOR 11
+
+
+
+/* do not modify the following; this will have to be modified if we
+ * have a 20ms framesize option */
+/**********************************************************************/
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder, 480 */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+#define FRAMESAMPLES_QUARTER 120
+/**********************************************************************/
+
+
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+#define MAX_SWBFRAMESAMPLES (MAX_FRAMESAMPLES * 2)
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms ((10*FS)/1000)
+#define SWBFRAMESAMPLES_10ms (FRAMESAMPLES_10ms * 2)
+/* number of samples in 30 ms frame */
+#define FRAMESAMPLES_30ms 480
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN (UPDATE/2)
+/* samples of look ahead (in a half-band, so actually
+ * half the samples of look ahead @ FS) */
+#define QLOOKAHEAD 24 /* 3 ms */
+/* order of AR model in spectral entropy coder */
+#define AR_ORDER 6
+/* order of LP model in spectral entropy coder */
+#define LP_ORDER 0
+
+/* window length (masking analysis) */
+#define WINLEN 256
+/* order of low-band pole filter used to approximate masking curve */
+#define ORDERLO 12
+/* order of hi-band pole filter used to approximate masking curve */
+#define ORDERHI 6
+
+#define UB_LPC_ORDER 4
+#define UB_LPC_VEC_PER_FRAME 2
+#define UB16_LPC_VEC_PER_FRAME 4
+#define UB_ACTIVE_SUBFRAMES 2
+#define UB_MAX_LPC_ORDER 6
+#define UB_INTERPOL_SEGMENTS 1
+#define UB16_INTERPOL_SEGMENTS 3
+#define LB_TOTAL_DELAY_SAMPLES 48
+enum ISACBandwidth {isac8kHz = 8, isac12kHz = 12, isac16kHz = 16};
+enum ISACBand {kIsacLowerBand = 0, kIsacUpperBand12 = 1, kIsacUpperBand16 = 2};
+#define UB_LPC_GAIN_DIM SUBFRAMES
+#define FB_STATE_SIZE_WORD32 6
+
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* another order */
+#define QORDER_ALL (POSTQORDER+QORDER-1)
+/* for decimator */
+#define ALLPASSSECTIONS 2
+
+
+/* array size for byte stream in number of bytes. */
+/* The old maximum size still needed for the decoding */
+#define STREAM_SIZE_MAX 600
+#define STREAM_SIZE_MAX_30 200 /* 200 bytes=53.4 kbps @ 30 ms.framelength */
+#define STREAM_SIZE_MAX_60 400 /* 400 bytes=53.4 kbps @ 60 ms.framelength */
+
+/* storage size for bit counts */
+#define BIT_COUNTER_SIZE 30
+/* maximum order of any AR model or filter */
+#define MAX_AR_MODEL_ORDER 12//50
+
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN (FRAMESAMPLES_HALF) /* 30 ms */
+#define PITCH_MAX_LAG 140 /* 57 Hz */
+#define PITCH_MIN_LAG 20 /* 400 Hz */
+#define PITCH_MAX_GAIN 0.45
+#define PITCH_MAX_GAIN_06 0.27 /* PITCH_MAX_GAIN*0.6 */
+#define PITCH_MAX_GAIN_Q12 1843
+#define PITCH_LAG_SPAN2 (PITCH_MAX_LAG/2-PITCH_MIN_LAG/2+5)
+#define PITCH_CORR_LEN2 60 /* 15 ms */
+#define PITCH_CORR_STEP2 (PITCH_FRAME_LEN/4)
+#define PITCH_BW 11 /* half the band width of correlation surface */
+#define PITCH_SUBFRAMES 4
+#define PITCH_GRAN_PER_SUBFRAME 5
+#define PITCH_SUBFRAME_LEN (PITCH_FRAME_LEN/PITCH_SUBFRAMES)
+#define PITCH_UPDATE (PITCH_SUBFRAME_LEN/PITCH_GRAN_PER_SUBFRAME)
+/* maximum number of peaks to be examined in correlation surface */
+#define PITCH_MAX_NUM_PEAKS 10
+#define PITCH_PEAK_DECAY 0.85
+/* For weighting filter */
+#define PITCH_WLPCORDER 6
+#define PITCH_WLPCWINLEN PITCH_FRAME_LEN
+#define PITCH_WLPCASYM 0.3 /* asymmetry parameter */
+#define PITCH_WLPCBUFLEN PITCH_WLPCWINLEN
+/* For pitch filter */
+/* Extra 50 for fraction and LP filters */
+#define PITCH_BUFFSIZE (PITCH_MAX_LAG + 50)
+#define PITCH_INTBUFFSIZE (PITCH_FRAME_LEN+PITCH_BUFFSIZE)
+/* Max rel. step for interpolation */
+#define PITCH_UPSTEP 1.5
+/* Max rel. step for interpolation */
+#define PITCH_DOWNSTEP 0.67
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+#define PITCH_FILTDELAY 1.5f
+/* stepsize for quantization of the pitch Gain */
+#define PITCH_GAIN_STEPSIZE 0.125
+
+
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+/* some mathematical constants */
+/* log2(exp) */
+#define LOG2EXP 1.44269504088896
+#define PI 3.14159265358979
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 5
+
+/* Redundant Coding */
+#define RCU_BOTTLENECK_BPS 16000
+#define RCU_TRANSCODING_SCALE 0.40f
+#define RCU_TRANSCODING_SCALE_INVERSE 2.5f
+
+#define RCU_TRANSCODING_SCALE_UB 0.50f
+#define RCU_TRANSCODING_SCALE_UB_INVERSE 2.0f
+
+
+/* Define Error codes */
+/* 6000 General */
+#define ISAC_MEMORY_ALLOCATION_FAILED 6010
+#define ISAC_MODE_MISMATCH 6020
+#define ISAC_DISALLOWED_BOTTLENECK 6030
+#define ISAC_DISALLOWED_FRAME_LENGTH 6040
+#define ISAC_UNSUPPORTED_SAMPLING_FREQUENCY 6050
+
+/* 6200 Bandwidth estimator */
+#define ISAC_RANGE_ERROR_BW_ESTIMATOR 6240
+/* 6400 Encoder */
+#define ISAC_ENCODER_NOT_INITIATED 6410
+#define ISAC_DISALLOWED_CODING_MODE 6420
+#define ISAC_DISALLOWED_FRAME_MODE_ENCODER 6430
+#define ISAC_DISALLOWED_BITSTREAM_LENGTH 6440
+#define ISAC_PAYLOAD_LARGER_THAN_LIMIT 6450
+#define ISAC_DISALLOWED_ENCODER_BANDWIDTH 6460
+/* 6600 Decoder */
+#define ISAC_DECODER_NOT_INITIATED 6610
+#define ISAC_EMPTY_PACKET 6620
+#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
+#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
+#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650
+#define ISAC_RANGE_ERROR_DECODE_PITCH_GAIN 6660
+#define ISAC_RANGE_ERROR_DECODE_PITCH_LAG 6670
+#define ISAC_RANGE_ERROR_DECODE_LPC 6680
+#define ISAC_RANGE_ERROR_DECODE_SPECTRUM 6690
+#define ISAC_LENGTH_MISMATCH 6730
+#define ISAC_RANGE_ERROR_DECODE_BANDWITH 6740
+#define ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER 6750
+#define ISAC_DISALLOWED_LPC_MODEL 6760
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c b/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000..92b9c4d
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "spectrum_ar_model_tables.h"
+#include "settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc1Cdf[12] = {
+ 0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 2 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc2Cdf[12] = {
+ 0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 3 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc3Cdf[12] = {
+ 0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 4 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc4Cdf[12] = {
+ 0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 5 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc5Cdf[12] = {
+ 0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 6 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc6Cdf[12] = {
+ 0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
+ 65533, 65535};
+
+/* representation levels for quantized reflection coefficient 1 */
+const WebRtc_Word16 WebRtcIsac_kQArRc1Levels[11] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const WebRtc_Word16 WebRtcIsac_kQArRc2Levels[11] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const WebRtc_Word16 WebRtcIsac_kQArRc3Levels[11] = {
+-32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const WebRtc_Word16 WebRtcIsac_kQArRc4Levels[11] = {
+-32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const WebRtc_Word16 WebRtcIsac_kQArRc5Levels[11] = {
+-32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const WebRtc_Word16 WebRtcIsac_kQArRc6Levels[11] = {
+-32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const WebRtc_Word16 WebRtcIsac_kQArBoundaryLevels[12] = {
+-32768, -31441, -27566, -21458, -13612, -4663, 4663, 13612, 21458, 27566, 31441, 32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const WebRtc_UWord16 WebRtcIsac_kQArRcInitIndex[6] = {
+ 5, 5, 5, 5, 5, 5};
+
+/* pointers to AR cdf tables */
+const WebRtc_UWord16 *WebRtcIsac_kQArRcCdfPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Cdf, WebRtcIsac_kQArRc2Cdf, WebRtcIsac_kQArRc3Cdf,
+ WebRtcIsac_kQArRc4Cdf, WebRtcIsac_kQArRc5Cdf, WebRtcIsac_kQArRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const WebRtc_Word16 *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Levels, WebRtcIsac_kQArRc2Levels, WebRtcIsac_kQArRc3Levels,
+ WebRtcIsac_kQArRc4Levels, WebRtcIsac_kQArRc5Levels, WebRtcIsac_kQArRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+const WebRtc_UWord16 WebRtcIsac_kQGainCdf[19] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 1172,
+ 11119, 29411, 51699, 64445, 65527, 65529, 65531, 65533, 65535};
+
+/* representation levels for quantized squared Gain coefficient */
+const WebRtc_Word32 WebRtcIsac_kQGain2Levels[18] = {
+// 17, 28, 46, 76, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+ 128, 128, 128, 128, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+/* quantization boundary levels for squared Gain coefficient */
+const WebRtc_Word32 WebRtcIsac_kQGain2BoundaryLevels[19] = {
+0, 21, 35, 59, 99, 166, 280, 475, 815, 1414, 2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF};
+
+/* pointers to Gain cdf table */
+const WebRtc_UWord16 *WebRtcIsac_kQGainCdf_ptr[1] = {WebRtcIsac_kQGainCdf};
+
+/* Gain initial index for gain quantizer and cdf table search */
+const WebRtc_UWord16 WebRtcIsac_kQGainInitIndex[1] = {11};
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+const WebRtc_Word16 WebRtcIsac_kCos[6][60] = {
+{512, 512, 511, 510, 508, 507, 505, 502, 499, 496, 493, 489, 485, 480, 476, 470, 465, 459, 453, 447,
+440, 433, 426, 418, 410, 402, 394, 385, 376, 367, 357, 348, 338, 327, 317, 306, 295, 284, 273, 262,
+250, 238, 226, 214, 202, 190, 177, 165, 152, 139, 126, 113, 100, 87, 73, 60, 47, 33, 20, 7},
+{512, 510, 508, 503, 498, 491, 483, 473, 462, 450, 437, 422, 406, 389, 371, 352, 333, 312, 290, 268,
+244, 220, 196, 171, 145, 120, 93, 67, 40, 13, -13, -40, -67, -93, -120, -145, -171, -196, -220, -244,
+-268, -290, -312, -333, -352, -371, -389, -406, -422, -437, -450, -462, -473, -483, -491, -498, -503, -508, -510, -512},
+{512, 508, 502, 493, 480, 465, 447, 426, 402, 376, 348, 317, 284, 250, 214, 177, 139, 100, 60, 20,
+-20, -60, -100, -139, -177, -214, -250, -284, -317, -348, -376, -402, -426, -447, -465, -480, -493, -502, -508, -512,
+-512, -508, -502, -493, -480, -465, -447, -426, -402, -376, -348, -317, -284, -250, -214, -177, -139, -100, -60, -20},
+{511, 506, 495, 478, 456, 429, 398, 362, 322, 279, 232, 183, 133, 80, 27, -27, -80, -133, -183, -232,
+-279, -322, -362, -398, -429, -456, -478, -495, -506, -511, -511, -506, -495, -478, -456, -429, -398, -362, -322, -279,
+-232, -183, -133, -80, -27, 27, 80, 133, 183, 232, 279, 322, 362, 398, 429, 456, 478, 495, 506, 511},
+{511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33, -33, -100, -165, -226, -284, -338, -385, -426,
+-459, -485, -502, -511, -511, -502, -485, -459, -426, -385, -338, -284, -226, -165, -100, -33, 33, 100, 165, 226,
+284, 338, 385, 426, 459, 485, 502, 511, 511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33},
+{510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510,
+-510, -498, -473, -437, -389, -333, -268, -196, -120, -40, 40, 120, 196, 268, 333, 389, 437, 473, 498, 510,
+510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510}
+};
diff --git a/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h b/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000..159245b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include "structs.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc1Cdf[12];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc2Cdf[12];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc3Cdf[12];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc4Cdf[12];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc5Cdf[12];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc6Cdf[12];
+
+/* quantization boundary levels for reflection coefficients */
+extern const WebRtc_Word16 WebRtcIsac_kQArBoundaryLevels[12];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRcInitIndex[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const WebRtc_UWord16 *WebRtcIsac_kQArRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const WebRtc_Word16 *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER];
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const WebRtc_UWord16 WebRtcIsac_kQGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsac_kQGain2Levels[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsac_kQGain2BoundaryLevels[19];
+
+/* pointer to Gain cdf table */
+extern const WebRtc_UWord16 *WebRtcIsac_kQGainCdf_ptr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsac_kQGainInitIndex[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const WebRtc_Word16 WebRtcIsac_kCos[6][60];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/structs.h b/src/modules/audio_coding/codecs/isac/main/source/structs.h
new file mode 100644
index 0000000..96cef30
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/structs.h
@@ -0,0 +1,477 @@
+/*
+ * 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.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+
+
+#include "typedefs.h"
+#include "settings.h"
+#include "isac.h"
+
+typedef struct Bitstreamstruct {
+
+ WebRtc_UWord8 stream[STREAM_SIZE_MAX];
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 streamval;
+ WebRtc_UWord32 stream_index;
+
+} Bitstr;
+
+typedef struct {
+
+ double DataBufferLo[WINLEN];
+ double DataBufferHi[WINLEN];
+
+ double CorrBufLo[ORDERLO+1];
+ double CorrBufHi[ORDERHI+1];
+
+ float PreStateLoF[ORDERLO+1];
+ float PreStateLoG[ORDERLO+1];
+ float PreStateHiF[ORDERHI+1];
+ float PreStateHiG[ORDERHI+1];
+ float PostStateLoF[ORDERLO+1];
+ float PostStateLoG[ORDERLO+1];
+ float PostStateHiF[ORDERHI+1];
+ float PostStateHiG[ORDERHI+1];
+
+ double OldEnergy;
+
+} MaskFiltstr;
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+ double INSTAT1[2*(QORDER-1)];
+ double INSTAT2[2*(QORDER-1)];
+ double INSTATLA1[2*(QORDER-1)];
+ double INSTATLA2[2*(QORDER-1)];
+ double INLABUF1[QLOOKAHEAD];
+ double INLABUF2[QLOOKAHEAD];
+
+ float INSTAT1_float[2*(QORDER-1)];
+ float INSTAT2_float[2*(QORDER-1)];
+ float INSTATLA1_float[2*(QORDER-1)];
+ float INSTATLA2_float[2*(QORDER-1)];
+ float INLABUF1_float[QLOOKAHEAD];
+ float INLABUF2_float[QLOOKAHEAD];
+
+ /* High pass filter */
+ double HPstates[HPORDER];
+ float HPstates_float[HPORDER];
+
+} PreFiltBankstr;
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+ double STATE_0_LOWER[2*POSTQORDER];
+ double STATE_0_UPPER[2*POSTQORDER];
+
+ /* High pass filter */
+ double HPstates1[HPORDER];
+ double HPstates2[HPORDER];
+
+ float STATE_0_LOWER_float[2*POSTQORDER];
+ float STATE_0_UPPER_float[2*POSTQORDER];
+
+ float HPstates1_float[HPORDER];
+ float HPstates2_float[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+
+ //data buffer for pitch filter
+ double ubuf[PITCH_BUFFSIZE];
+
+ //low pass state vector
+ double ystate[PITCH_DAMPORDER];
+
+ //old lag and gain
+ double oldlagp[1];
+ double oldgainp[1];
+
+} PitchFiltstr;
+
+typedef struct {
+
+ //data buffer
+ double buffer[PITCH_WLPCBUFLEN];
+
+ //state vectors
+ double istate[PITCH_WLPCORDER];
+ double weostate[PITCH_WLPCORDER];
+ double whostate[PITCH_WLPCORDER];
+
+ //LPC window -> should be a global array because constant
+ double window[PITCH_WLPCWINLEN];
+
+} WeightFiltstr;
+
+typedef struct {
+
+ //for inital estimator
+ double dec_buffer[PITCH_CORR_LEN2 + PITCH_CORR_STEP2 +
+ PITCH_MAX_LAG/2 - PITCH_FRAME_LEN/2+2];
+ double decimator_state[2*ALLPASSSECTIONS+1];
+ double hp_state[2];
+
+ double whitened_buf[QLOOKAHEAD];
+
+ double inbuf[QLOOKAHEAD];
+
+ PitchFiltstr PFstr_wght;
+ PitchFiltstr PFstr;
+ WeightFiltstr Wghtstr;
+
+} PitchAnalysisStruct;
+
+
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+
+ /* Previous frame length (in ms) */
+ WebRtc_Word32 prev_frame_length;
+
+ /* Previous RTP timestamp from received
+ packet (in samples relative beginning) */
+ WebRtc_Word32 prev_rec_rtp_number;
+
+ /* Send timestamp for previous packet (in ms using timeGetTime()) */
+ WebRtc_UWord32 prev_rec_send_ts;
+
+ /* Arrival time for previous packet (in ms using timeGetTime()) */
+ WebRtc_UWord32 prev_rec_arr_ts;
+
+ /* rate of previous packet, derived from RTP timestamps (in bits/s) */
+ float prev_rec_rtp_rate;
+
+ /* Time sinse the last update of the BN estimate (in ms) */
+ WebRtc_UWord32 last_update_ts;
+
+ /* Time sinse the last reduction (in ms) */
+ WebRtc_UWord32 last_reduction_ts;
+
+ /* How many times the estimate was update in the beginning */
+ WebRtc_Word32 count_tot_updates_rec;
+
+ /* The estimated bottle neck rate from there to here (in bits/s) */
+ WebRtc_Word32 rec_bw;
+ float rec_bw_inv;
+ float rec_bw_avg;
+ float rec_bw_avg_Q;
+
+ /* The estimated mean absolute jitter value,
+ as seen on this side (in ms) */
+ float rec_jitter;
+ float rec_jitter_short_term;
+ float rec_jitter_short_term_abs;
+ float rec_max_delay;
+ float rec_max_delay_avg_Q;
+
+ /* (assumed) bitrate for headers (bps) */
+ float rec_header_rate;
+
+ /* The estimated bottle neck rate from here to there (in bits/s) */
+ float send_bw_avg;
+
+ /* The estimated mean absolute jitter value, as seen on
+ the other siee (in ms) */
+ float send_max_delay_avg;
+
+ // number of packets received since last update
+ int num_pkts_rec;
+
+ int num_consec_rec_pkts_over_30k;
+
+ // flag for marking that a high speed network has been
+ // detected downstream
+ int hsn_detect_rec;
+
+ int num_consec_snt_pkts_over_30k;
+
+ // flag for marking that a high speed network has
+ // been detected upstream
+ int hsn_detect_snd;
+
+ WebRtc_UWord32 start_wait_period;
+
+ int in_wait_period;
+
+ int change_to_WB;
+
+ WebRtc_UWord32 senderTimestamp;
+ WebRtc_UWord32 receiverTimestamp;
+ //enum IsacSamplingRate incomingStreamSampFreq;
+ WebRtc_UWord16 numConsecLatePkts;
+ float consecLatency;
+ WebRtc_Word16 inWaitLatePkts;
+} BwEstimatorstr;
+
+
+typedef struct {
+
+ /* boolean, flags if previous packet exceeded B.N. */
+ int PrevExceed;
+ /* ms */
+ int ExceedAgo;
+ /* packets left to send in current burst */
+ int BurstCounter;
+ /* packets */
+ int InitCounter;
+ /* ms remaining in buffer when next packet will be sent */
+ double StillBuffered;
+
+} RateModel;
+
+
+typedef struct {
+
+ unsigned int SpaceAlloced;
+ unsigned int MaxPermAlloced;
+ double Tmp0[MAXFFTSIZE];
+ double Tmp1[MAXFFTSIZE];
+ double Tmp2[MAXFFTSIZE];
+ double Tmp3[MAXFFTSIZE];
+ int Perm[MAXFFTSIZE];
+ int factor [NFACTOR];
+
+} FFTstr;
+
+
+/* The following strutc is used to store data from encoding, to make it
+ fast and easy to construct a new bitstream with a different Bandwidth
+ estimate. All values (except framelength and minBytes) is double size to
+ handle 60 ms of data.
+*/
+typedef struct {
+
+ /* Used to keep track of if it is first or second part of 60 msec packet */
+ int startIdx;
+
+ /* Frame length in samples */
+ WebRtc_Word16 framelength;
+
+ /* Pitch Gain */
+ int pitchGain_index[2];
+
+ /* Pitch Lag */
+ double meanGain[2];
+ int pitchIndex[PITCH_SUBFRAMES*2];
+
+ /* LPC */
+ int LPCindex_s[108*2]; /* KLT_ORDER_SHAPE = 108 */
+ int LPCindex_g[12*2]; /* KLT_ORDER_GAIN = 12 */
+ double LPCcoeffs_lo[(ORDERLO+1)*SUBFRAMES*2];
+ double LPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*2];
+
+ /* Encode Spec */
+ WebRtc_Word16 fre[FRAMESAMPLES];
+ WebRtc_Word16 fim[FRAMESAMPLES];
+ WebRtc_Word16 AvgPitchGain[2];
+
+ /* Used in adaptive mode only */
+ int minBytes;
+
+} ISAC_SaveEncData_t;
+
+
+typedef struct {
+
+ int indexLPCShape[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double lpcGain[SUBFRAMES<<1];
+ int lpcGainIndex[SUBFRAMES<<1];
+
+ Bitstr bitStreamObj;
+
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+} ISACUBSaveEncDataStruct;
+
+
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PitchAnalysisStruct pitchanalysisstr_obj;
+ FFTstr fftstr_obj;
+ ISAC_SaveEncData_t SaveEnc_obj;
+
+ int buffer_index;
+ WebRtc_Word16 current_framesamples;
+
+ float data_buffer_float[FRAMESAMPLES_30ms];
+
+ int frame_nb;
+ double bottleneck;
+ WebRtc_Word16 new_framelength;
+ double s2nr;
+
+ /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 payloadLimitBytes30;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 payloadLimitBytes60;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ WebRtc_Word16 maxPayloadBytes;
+ /* Maximum allowed rate in bytes per 30 msec packet */
+ WebRtc_Word16 maxRateInBytes;
+
+ /*---
+ If set to 1 iSAC will not addapt the frame-size, if used in
+ channel-adaptive mode. The initial value will be used for all rates.
+ ---*/
+ WebRtc_Word16 enforceFrameSize;
+
+ /*-----
+ This records the BWE index the encoder injected into the bit-stream.
+ It will be used in RCU. The same BWE index of main paylaod will be in
+ the redundant payload. We can not retrive it from BWE because it is
+ a recursive procedure (WebRtcIsac_GetDownlinkBwJitIndexImpl) and has to be
+ called only once per each encode.
+ -----*/
+ WebRtc_Word16 lastBWIdx;
+} ISACLBEncStruct;
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ FFTstr fftstr_obj;
+ ISACUBSaveEncDataStruct SaveEnc_obj;
+
+ int buffer_index;
+ float data_buffer_float[MAX_FRAMESAMPLES +
+ LB_TOTAL_DELAY_SAMPLES];
+ double bottleneck;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ //WebRtc_Word16 payloadLimitBytes30;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ //WebRtc_Word16 maxPayloadBytes;
+ WebRtc_Word16 maxPayloadSizeBytes;
+
+ double lastLPCVec[UB_LPC_ORDER];
+ WebRtc_Word16 numBytesUsed;
+ WebRtc_Word16 lastJitterInfo;
+} ISACUBEncStruct;
+
+
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACLBDecStruct;
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACUBDecStruct;
+
+
+
+typedef struct {
+
+ ISACLBEncStruct ISACencLB_obj;
+ ISACLBDecStruct ISACdecLB_obj;
+} ISACLBStruct;
+
+
+typedef struct {
+
+ ISACUBEncStruct ISACencUB_obj;
+ ISACUBDecStruct ISACdecUB_obj;
+} ISACUBStruct;
+
+/*
+ This struct is used to take a snapshot of the entropy coder and LPC gains
+ right before encoding LPC gains. This allows us to go back to that state
+ if we like to limit the payload size.
+*/
+typedef struct {
+ /* 6 lower-band & 6 upper-band */
+ double loFiltGain[SUBFRAMES];
+ double hiFiltGain[SUBFRAMES];
+ /* Upper boundary of interval W */
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 streamval;
+ /* Index to the current position in bytestream */
+ WebRtc_UWord32 stream_index;
+ WebRtc_UWord8 stream[3];
+} transcode_obj;
+
+
+typedef struct {
+ // lower-band codec instance
+ ISACLBStruct instLB;
+ // upper-band codec instance
+ ISACUBStruct instUB;
+
+ // Bandwidth Estimator and model for the rate.
+ BwEstimatorstr bwestimator_obj;
+ RateModel rate_data_obj;
+ double MaxDelay;
+
+ /* 0 = adaptive; 1 = instantaneous */
+ WebRtc_Word16 codingMode;
+
+ // overall bottleneck of the codec
+ WebRtc_Word32 bottleneck;
+
+ // QMF Filter state
+ WebRtc_Word32 analysisFBState1[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 analysisFBState2[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 synthesisFBState1[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 synthesisFBState2[FB_STATE_SIZE_WORD32];
+
+ // Error Code
+ WebRtc_Word16 errorCode;
+
+ // bandwidth of the encoded audio 8, 12 or 16 kHz
+ enum ISACBandwidth bandwidthKHz;
+ // Sampling rate of audio, encoder and decode, 8 or 16 kHz
+ enum IsacSamplingRate encoderSamplingRateKHz;
+ enum IsacSamplingRate decoderSamplingRateKHz;
+ // Flag to keep track of initializations, lower & upper-band
+ // encoder and decoder.
+ WebRtc_Word16 initFlag;
+
+ // Flag to to indicate signal bandwidth switch
+ WebRtc_Word16 resetFlag_8kHz;
+
+ // Maximum allowed rate, measured in Bytes per 30 ms.
+ WebRtc_Word16 maxRateBytesPer30Ms;
+ // Maximum allowed payload-size, measured in Bytes.
+ WebRtc_Word16 maxPayloadSizeBytes;
+} ISACMainStruct;
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/main/source/transform.c b/src/modules/audio_coding/codecs/isac/main/source/transform.c
new file mode 100644
index 0000000..97b801a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/main/source/transform.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "settings.h"
+#include "fft.h"
+#include "codec.h"
+#include "os_specific_inline.h"
+#include <math.h>
+
+static double costab1[FRAMESAMPLES_HALF];
+static double sintab1[FRAMESAMPLES_HALF];
+static double costab2[FRAMESAMPLES_QUARTER];
+static double sintab2[FRAMESAMPLES_QUARTER];
+
+void WebRtcIsac_InitTransform()
+{
+ int k;
+ double fact, phase;
+
+ fact = PI / (FRAMESAMPLES_HALF);
+ phase = 0.0;
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ costab1[k] = cos(phase);
+ sintab1[k] = sin(phase);
+ phase += fact;
+ }
+
+ fact = PI * ((double) (FRAMESAMPLES_HALF - 1)) / ((double) FRAMESAMPLES_HALF);
+ phase = 0.5 * fact;
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ costab2[k] = cos(phase);
+ sintab2[k] = sin(phase);
+ phase += fact;
+ }
+}
+
+
+void WebRtcIsac_Time2Spec(double *inre1,
+ double *inre2,
+ WebRtc_Word16 *outreQ7,
+ WebRtc_Word16 *outimQ7,
+ FFTstr *fftstr_obj)
+{
+
+ int k;
+ int dims[1];
+ double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+ double tmpre[FRAMESAMPLES_HALF], tmpim[FRAMESAMPLES_HALF];
+
+
+ dims[0] = FRAMESAMPLES_HALF;
+
+
+ /* Multiply with complex exponentials and combine into one complex vector */
+ fact = 0.5 / sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tmp1r = costab1[k];
+ tmp1i = sintab1[k];
+ tmpre[k] = (inre1[k] * tmp1r + inre2[k] * tmp1i) * fact;
+ tmpim[k] = (inre2[k] * tmp1r - inre1[k] * tmp1i) * fact;
+ }
+
+
+ /* Get DFT */
+ WebRtcIsac_Fftns(1, dims, tmpre, tmpim, -1, 1.0, fftstr_obj);
+
+ /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ xr = tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ yi = -tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k];
+ yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - k];
+
+ tmp1r = costab2[k];
+ tmp1i = sintab2[k];
+ outreQ7[k] = (WebRtc_Word16)WebRtcIsac_lrint((xr * tmp1r - xi * tmp1i) * 128.0);
+ outimQ7[k] = (WebRtc_Word16)WebRtcIsac_lrint((xr * tmp1i + xi * tmp1r) * 128.0);
+ outreQ7[FRAMESAMPLES_HALF - 1 - k] = (WebRtc_Word16)WebRtcIsac_lrint((-yr * tmp1i - yi * tmp1r) * 128.0);
+ outimQ7[FRAMESAMPLES_HALF - 1 - k] = (WebRtc_Word16)WebRtcIsac_lrint((-yr * tmp1r + yi * tmp1i) * 128.0);
+ }
+}
+
+
+void WebRtcIsac_Spec2time(double *inre, double *inim, double *outre1, double *outre2, FFTstr *fftstr_obj)
+{
+
+ int k;
+ double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+
+ int dims;
+
+ dims = FRAMESAMPLES_HALF;
+
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ /* Move zero in time to beginning of frames */
+ tmp1r = costab2[k];
+ tmp1i = sintab2[k];
+ xr = inre[k] * tmp1r + inim[k] * tmp1i;
+ xi = inim[k] * tmp1r - inre[k] * tmp1i;
+ yr = -inim[FRAMESAMPLES_HALF - 1 - k] * tmp1r - inre[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+ yi = -inre[FRAMESAMPLES_HALF - 1 - k] * tmp1r + inim[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+
+ /* Combine into one vector, z = x + j * y */
+ outre1[k] = xr - yi;
+ outre1[FRAMESAMPLES_HALF - 1 - k] = xr + yi;
+ outre2[k] = xi + yr;
+ outre2[FRAMESAMPLES_HALF - 1 - k] = -xi + yr;
+ }
+
+
+ /* Get IDFT */
+ WebRtcIsac_Fftns(1, &dims, outre1, outre2, 1, FRAMESAMPLES_HALF, fftstr_obj);
+
+
+ /* Demodulate and separate */
+ fact = sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tmp1r = costab1[k];
+ tmp1i = sintab1[k];
+ xr = (outre1[k] * tmp1r - outre2[k] * tmp1i) * fact;
+ outre2[k] = (outre2[k] * tmp1r + outre1[k] * tmp1i) * fact;
+ outre1[k] = xr;
+ }
+}