Added fixed point iSAC codec implementation.
- Added fixed-point iSAC audio codec implementation (from stable r2699).
- Updated system wrappers (from stable r2699).
- Some cosmetic makefile changes.
Change-Id: If75d503698c11a4e4ceb851529127aadfe52f255
diff --git a/Android.mk b/Android.mk
index a6e7a49..7b046d6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,8 @@
include $(MY_WEBRTC_ROOT_PATH)/src/common_audio/resampler/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/common_audio/signal_processing/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/common_audio/vad/Android.mk
+include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_coding/codecs/isac/fix/source/Android.mk
+include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_coding/codecs/isac/main/source/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_processing/aec/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_processing/aecm/Android.mk
include $(MY_WEBRTC_ROOT_PATH)/src/modules/audio_processing/agc/Android.mk
@@ -20,7 +22,6 @@
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)
@@ -75,9 +76,15 @@
LOCAL_WHOLE_STATIC_LIBRARIES := \
libwebrtc_isac \
+ libwebrtc_isacfix \
libwebrtc_spl \
libwebrtc_system_wrappers
+ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+LOCAL_WHOLE_STATIC_LIBRARIES += \
+ libwebrtc_isacfix_neon
+endif
+
LOCAL_STATIC_LIBRARIES := \
libprotobuf-cpp-2.3.0-lite
diff --git a/src/modules/audio_coding/codecs/isac/fix/interface/isacfix.h b/src/modules/audio_coding/codecs/isac/fix/interface/isacfix.h
new file mode 100644
index 0000000..28e9429
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/interface/isacfix.h
@@ -0,0 +1,633 @@
+/*
+ * 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_FIX_INTERFACE_ISACFIX_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_ISACFIX_H_
+
+/*
+ * Define the fixpoint numeric formats
+ */
+#include "typedefs.h"
+
+
+typedef struct {
+ void *dummy;
+} ISACFIX_MainStruct;
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+ /**************************************************************************
+ * WebRtcIsacfix_AssignSize(...)
+ *
+ * Functions used when malloc is not allowed
+ * Output the number of bytes needed to allocate for iSAC struct.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_AssignSize(int *sizeinbytes);
+
+ /**************************************************************************
+ * WebRtcIsacfix_Assign(...)
+ *
+ * Functions used when malloc is not allowed, it
+ * places a struct at the given address.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ * - ISACFIX_inst_Addr : address of the memory where a space is
+ * for iSAC structure.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_Assign(ISACFIX_MainStruct **inst,
+ void *ISACFIX_inst_Addr);
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Create(ISACFIX_MainStruct **ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Free(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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.
+ * 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 WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 CodingMode);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_Word16 *speechIn,
+ WebRtc_Word16 *encoded);
+
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_EncodeNb(...)
+ *
+ * This function encodes 10ms narrow band (8 kHz sampling) frame(s) and inserts
+ * it into a package. Input speech length has to be 80 samples (10ms). The encoder
+ * interpolates into wide-band (16 kHz sampling) buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 wide-band samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * 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
+ */
+
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ WebRtc_Word16 WebRtcIsacfix_EncodeNb(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_Word16 *speechIn,
+ WebRtc_Word16 *encoded);
+#endif // WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * 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 WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 arr_ts);
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 send time of the packet from RTP header,
+ * in samples.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts);
+
+ /****************************************************************************
+ * WebRtcIsacfix_Decode(...)
+ *
+ * This function decodes an 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 WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 *speechType);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_DecodeNb(...)
+ *
+ * This function decodes a ISAC frame in narrow-band (8 kHz sampling).
+ * Output speech length will be a multiple of 240 samples: 240 or 480 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * 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
+ */
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ WebRtc_Word16 WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 *speechType);
+#endif // WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_DecodePlcNb(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in narrow-band (8kHz sampling).
+ * Output speech length will be "240*noOfLostFrames" samples
+ * that equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (240 sample=30ms) to produce
+ * NOTE! Maximum number is 2 (480 samples = 60ms)
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ WebRtc_Word16 WebRtcIsacfix_DecodePlcNb(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 noOfLostFrames );
+#endif // WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+
+
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (480sample = 30ms)
+ * to produce
+ * NOTE! Maximum number is 2 (960 samples = 60ms)
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 noOfLostFrames );
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_ReadFrameLen(const WebRtc_Word16* encoded,
+ WebRtc_Word16* frameLength);
+
+ /****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * 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
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 rate,
+ WebRtc_Word16 framesize);
+
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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
+ * - 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 WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 rateBPS,
+ WebRtc_Word16 frameSizeMs,
+ WebRtc_Word16 enforceFrameSize);
+
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+ void WebRtcIsacfix_version(char *version);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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 occured in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function return iSAC send bitrate
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : <0 Error code
+ * else bitrate
+ */
+
+ WebRtc_Word32 WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 maxPayloadBytes);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRateInBytes : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word32 maxRate);
+
+ /****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ * - ISAC_main_inst : an ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the recieved bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : index of bandwidth estimate to put in new bitstream
+ * - scale : factor for rate change (0.4 ~=> half the rate, 1 no change).
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 bweIndex,
+ float scale,
+ WebRtc_Word16 *encoded);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+ WebRtc_Word16* rateIndex);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_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
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+ WebRtc_Word16 rateIndex);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_ReadBwIndex(const WebRtc_Word16* encoded,
+ WebRtc_Word16* rateIndex);
+
+
+ /****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ * -ISAC_main_inst : iSAC instance
+ *
+ * Return value : frame lenght in samples
+ */
+
+ WebRtc_Word16 WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_ISACFIX_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/Android.mk b/src/modules/audio_coding/codecs/isac/fix/source/Android.mk
new file mode 100644
index 0000000..bd2a91d
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/Android.mk
@@ -0,0 +1,149 @@
+# 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.
+
+#############################
+# Build the non-neon library.
+
+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_isacfix
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ arith_routines.c \
+ arith_routines_hist.c \
+ arith_routines_logist.c \
+ bandwidth_estimator.c \
+ decode.c \
+ decode_bwe.c \
+ decode_plc.c \
+ encode.c \
+ entropy_coding.c \
+ fft.c \
+ filterbank_tables.c \
+ filterbanks.c \
+ filters.c \
+ initialize.c \
+ isacfix.c \
+ lattice.c \
+ lpc_masking_model.c \
+ lpc_tables.c \
+ pitch_estimator.c \
+ pitch_filter.c \
+ pitch_gain_tables.c \
+ pitch_lag_tables.c \
+ spectrum_ar_model_tables.c \
+ transform.c
+
+ifeq ($(ARCH_ARM_HAVE_ARMV7A),true)
+# Using .S (instead of .s) extention is to include a C header file in assembly.
+LOCAL_SRC_FILES += \
+ lattice_armv7.S \
+ pitch_filter_armv6.S
+else
+LOCAL_SRC_FILES += \
+ lattice_c.c
+endif
+
+# 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_STATIC_LIBRARIES += libwebrtc_system_wrappers
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl \
+ libstlport
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
+
+#########################
+# Build the neon library.
+ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_isacfix_neon
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ filters_neon.c \
+ lattice_neon.S \
+ lpc_masking_model_neon.S
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS) \
+ -mfpu=neon \
+ -mfloat-abi=softfp \
+ -flax-vector-conversions
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../interface \
+ $(LOCAL_PATH)/../../../../../.. \
+ $(LOCAL_PATH)/../../../../../../common_audio/signal_processing/include
+
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
+
+endif # ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+
+###########################
+# isac test app
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES:= ../test/kenny.c
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := $(MY_WEBRTC_COMMON_DEFS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../interface \
+ $(LOCAL_PATH)/../../../../../..
+
+LOCAL_STATIC_LIBRARIES := \
+ libwebrtc_isacfix \
+ libwebrtc_spl \
+ libwebrtc_system_wrappers
+
+ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+LOCAL_STATIC_LIBRARIES += \
+ libwebrtc_isacfix_neon
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils
+
+LOCAL_MODULE:= webrtc_isac_test
+
+ifdef NDK_ROOT
+include $(BUILD_EXECUTABLE)
+else
+include $(BUILD_NATIVE_TEST)
+endif
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/arith_routines.c b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
new file mode 100644
index 0000000..ee62bad
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
@@ -0,0 +1,124 @@
+/*
+ * 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_routins.c
+ *
+ * This C file contains a function for finalizing the bitstream
+ * after arithmetic coding.
+ *
+ */
+
+#include "arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ *
+ * Return value : number of bytes in the stream
+ */
+WebRtc_Word16 WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData)
+{
+ WebRtc_UWord16 *streamPtr;
+ WebRtc_UWord16 negCarry;
+
+ /* point to the right place in the stream buffer */
+ streamPtr = streamData->stream + streamData->stream_index;
+
+ /* find minimum length (determined by current interval width) */
+ if ( streamData->W_upper > 0x01FFFFFF )
+ {
+ streamData->streamval += 0x01000000;
+
+ /* if result is less than the added value we must take care of the carry */
+ if (streamData->streamval < 0x01000000)
+ {
+ /* propagate carry */
+ if (streamData->full == 0) {
+ /* Add value to current value */
+ negCarry = *streamPtr;
+ negCarry += 0x0100;
+ *streamPtr = negCarry;
+
+ /* if value is too big, propagate carry to next byte, and so on */
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtr;
+ negCarry++;
+ *streamPtr = negCarry;
+ }
+ } else {
+ /* propagate carry by adding one to the previous byte in the
+ * stream if that byte is 0xFFFF we need to propagate the carry
+ * furhter back in the stream */
+ while ( !(++(*--streamPtr)) );
+ }
+
+ /* put pointer back to the old value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ }
+ /* write remaining data to bitstream, if "full == 0" first byte has data */
+ if (streamData->full == 0) {
+ *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_W32(
+ WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8);
+ streamData->full = 0;
+ }
+ }
+ else
+ {
+ streamData->streamval += 0x00010000;
+
+ /* if result is less than the added value we must take care of the carry */
+ if (streamData->streamval < 0x00010000)
+ {
+ /* propagate carry */
+ if (streamData->full == 0) {
+ /* Add value to current value */
+ negCarry = *streamPtr;
+ negCarry += 0x0100;
+ *streamPtr = negCarry;
+
+ /* if value to big, propagate carry to next byte, and so on */
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtr;
+ negCarry++;
+ *streamPtr = negCarry;
+ }
+ } else {
+ /* Add carry to previous byte */
+ while ( !(++(*--streamPtr)) );
+ }
+
+ /* put pointer back to the old value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ }
+ /* write remaining data (2 bytes) to bitstream */
+ if (streamData->full) {
+ *streamPtr++ = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 16);
+ } else {
+ *streamPtr++ |= (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
+ *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 8)
+ & 0xFF00;
+ }
+ }
+
+ /* calculate stream length in bytes */
+ return (((streamPtr - streamData->stream)<<1) + !(streamData->full));
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
new file mode 100644
index 0000000..14f1add
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
@@ -0,0 +1,404 @@
+/*
+ * 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_routinshist.c
+ *
+ * This C file contains arithmetic encoding and decoding.
+ *
+ */
+
+#include "arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - data : data vector
+ * - cdf : array of cdf arrays
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok
+ * <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
+ const WebRtc_Word16 *data,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_Word16 lenData)
+{
+ WebRtc_UWord32 W_lower;
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 W_upper_LSB;
+ WebRtc_UWord32 W_upper_MSB;
+ WebRtc_UWord16 *streamPtr;
+ WebRtc_UWord16 negCarry;
+ WebRtc_UWord16 *maxStreamPtr;
+ WebRtc_UWord16 *streamPtrCarry;
+ WebRtc_UWord32 cdfLo;
+ WebRtc_UWord32 cdfHi;
+ int k;
+
+
+ /* point to beginning of stream buffer
+ * and set maximum streamPtr value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+
+ W_upper = streamData->W_upper;
+
+ for (k = lenData; k > 0; k--)
+ {
+ /* fetch cdf_lower and cdf_upper from cdf tables */
+ cdfLo = (WebRtc_UWord32) *(*cdf + (WebRtc_UWord32)*data);
+ cdfHi = (WebRtc_UWord32) *(*cdf++ + (WebRtc_UWord32)*data++ + 1);
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
+ W_lower = WEBRTC_SPL_UMUL(W_upper_MSB, cdfLo);
+ W_lower += WEBRTC_SPL_UMUL_RSFT16(W_upper_LSB, cdfLo);
+ W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
+ W_upper += WEBRTC_SPL_UMUL_RSFT16(W_upper_LSB, cdfHi);
+
+ /* 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 */
+ streamPtrCarry = streamPtr;
+ if (streamData->full == 0) {
+ negCarry = *streamPtrCarry;
+ negCarry += 0x0100;
+ *streamPtrCarry = negCarry;
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtrCarry;
+ negCarry++;
+ *streamPtrCarry = negCarry;
+ }
+ } else {
+ while ( !(++(*--streamPtrCarry)) );
+ }
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
+ if (streamData->full == 0) {
+ *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_W32(
+ WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8);
+ streamData->full = 0;
+ }
+
+ if( streamPtr > maxStreamPtr ) {
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+ }
+ streamData->streamval = WEBRTC_SPL_LSHIFT_W32(streamData->streamval, 8);
+ }
+ }
+
+ /* calculate new stream_index */
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * 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)
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - cdfSize : array of cdf table sizes+1 (power of two: 2^k)
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in the stream
+ * <0 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecHistBisectMulti(WebRtc_Word16 *data,
+ Bitstr_dec *streamData,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_UWord16 *cdfSize,
+ const WebRtc_Word16 lenData)
+{
+ WebRtc_UWord32 W_lower = 0;
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB;
+ WebRtc_UWord32 W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord16 *streamPtr;
+ const WebRtc_UWord16 *cdfPtr;
+ WebRtc_Word16 sizeTmp;
+ int k;
+
+
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+
+ /* Error check: should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ /* first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamval = WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)*streamPtr++, 16);
+ streamval |= *streamPtr++;
+ } else {
+ streamval = streamData->streamval;
+ }
+
+ for (k = lenData; 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 = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
+
+ /* start halfway the cdf range */
+ sizeTmp = WEBRTC_SPL_RSHIFT_W16(*cdfSize++, 1);
+ cdfPtr = *cdf + (sizeTmp - 1);
+
+ /* method of bisection */
+ for ( ;; )
+ {
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += WEBRTC_SPL_UMUL_32_16_RSFT16(W_upper_LSB, *cdfPtr);
+ sizeTmp = WEBRTC_SPL_RSHIFT_W16(sizeTmp, 1);
+ if (sizeTmp == 0) {
+ break;
+ }
+
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ cdfPtr += sizeTmp;
+ } else {
+ W_upper = W_tmp;
+ cdfPtr -= sizeTmp;
+ }
+ }
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ *data++ = cdfPtr - *cdf++;
+ } else {
+ W_upper = W_tmp;
+ *data++ = cdfPtr - *cdf++ - 1;
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ /* W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
+ (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
+ WEBRTC_SPL_RSHIFT_W16(*streamPtr, 8);
+ streamData->full = 0;
+ }
+ W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
+ }
+
+
+ /* Error check: should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ }
+
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+ streamData->streamval = streamval;
+
+ if ( W_upper > 0x01FFFFFF ) {
+ return (streamData->stream_index*2 - 3 + !streamData->full);
+ } else {
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * 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.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - initIndex : vector of initial cdf table search entries
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in original stream
+ * <0 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecHistOneStepMulti(WebRtc_Word16 *data,
+ Bitstr_dec *streamData,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_UWord16 *initIndex,
+ const WebRtc_Word16 lenData)
+{
+ WebRtc_UWord32 W_lower;
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB;
+ WebRtc_UWord32 W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord16 *streamPtr;
+ const WebRtc_UWord16 *cdfPtr;
+ int k;
+
+
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+ /* Error check: Should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ /* Check if it is the first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamval = WEBRTC_SPL_LSHIFT_U32(*streamPtr++, 16);
+ streamval |= *streamPtr++;
+ } else {
+ streamval = streamData->streamval;
+ }
+
+ for (k = lenData; 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 = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+ /* start at the specified table entry */
+ cdfPtr = *cdf + (*initIndex++);
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += WEBRTC_SPL_UMUL_32_16_RSFT16(W_upper_LSB, *cdfPtr);
+
+ if (streamval > W_tmp)
+ {
+ for ( ;; )
+ {
+ W_lower = W_tmp;
+
+ /* range check */
+ if (cdfPtr[0] == 65535) {
+ return -3;
+ }
+
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
+ W_tmp += WEBRTC_SPL_UMUL_32_16_RSFT16(W_upper_LSB, *cdfPtr);
+
+ if (streamval <= W_tmp) {
+ break;
+ }
+ }
+ W_upper = W_tmp;
+ *data++ = cdfPtr - *cdf++ - 1;
+ } else {
+ for ( ;; )
+ {
+ W_upper = W_tmp;
+ --cdfPtr;
+
+ /* range check */
+ if (cdfPtr < *cdf) {
+ return -3;
+ }
+
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += WEBRTC_SPL_UMUL_32_16_RSFT16(W_upper_LSB, *cdfPtr);
+
+ if (streamval > W_tmp) {
+ break;
+ }
+ }
+ W_lower = W_tmp;
+ *data++ = cdfPtr - *cdf++;
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ /* W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr >> 8);
+ streamData->full = 0;
+ }
+ W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
+ }
+ }
+
+ streamData->stream_index = streamPtr - 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 - 3 + !streamData->full);
+ } else {
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
new file mode 100644
index 0000000..39c437e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
@@ -0,0 +1,404 @@
+/*
+ * 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_routinslogist.c
+ *
+ * This C file contains arithmetic encode and decode logistic
+ *
+ */
+
+#include "arith_routins.h"
+
+
+/* Tables for piecewise linear cdf functions: y = k*x */
+
+/* x Points for function piecewise() in Q15 */
+static const WebRtc_Word32 kHistEdges[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
+};
+
+
+/* k Points for function piecewise() in Q0 */
+static const WebRtc_UWord16 kCdfSlope[51] = {
+ 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
+};
+
+/* y Points for function piecewise() in Q0 */
+static const WebRtc_UWord16 kCdfLogistic[51] = {
+ 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
+};
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Piecewise(...)
+ *
+ * Piecewise linear function
+ *
+ * Input:
+ * - xinQ15 : input value x in Q15
+ *
+ * Return value : korresponding y-value in Q0
+ */
+
+
+static __inline WebRtc_UWord16 WebRtcIsacfix_Piecewise(WebRtc_Word32 xinQ15) {
+ WebRtc_Word32 ind;
+ WebRtc_Word32 qtmp1;
+ WebRtc_UWord16 qtmp2;
+
+ /* Find index for x-value */
+ qtmp1 = WEBRTC_SPL_SAT(kHistEdges[50],xinQ15,kHistEdges[0]);
+ ind = WEBRTC_SPL_MUL(5, qtmp1 - kHistEdges[0]);
+ ind = WEBRTC_SPL_RSHIFT_W32(ind, 16);
+
+ /* Calculate corresponding y-value ans return*/
+ qtmp1 = qtmp1 - kHistEdges[ind];
+ qtmp2 = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_U32(
+ WEBRTC_SPL_UMUL_32_16(qtmp1,kCdfSlope[ind]), 15);
+ return (kCdfLogistic[ind] + qtmp2);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - dataQ7 : data vector in Q7
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok,
+ * <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc *streamData,
+ WebRtc_Word16 *dataQ7,
+ const WebRtc_UWord16 *envQ8,
+ const WebRtc_Word16 lenData)
+{
+ WebRtc_UWord32 W_lower;
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord16 W_upper_LSB;
+ WebRtc_UWord16 W_upper_MSB;
+ WebRtc_UWord16 *streamPtr;
+ WebRtc_UWord16 *maxStreamPtr;
+ WebRtc_UWord16 *streamPtrCarry;
+ WebRtc_UWord16 negcarry;
+ WebRtc_UWord32 cdfLo;
+ WebRtc_UWord32 cdfHi;
+ int k;
+
+ /* point to beginning of stream buffer
+ * and set maximum streamPtr value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+ W_upper = streamData->W_upper;
+
+ for (k = 0; k < lenData; k++)
+ {
+ /* compute cdf_lower and cdf_upper by evaluating the
+ * WebRtcIsacfix_Piecewise linear cdf */
+ cdfLo = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+ cdfHi = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+
+ /* test and clip if probability gets too small */
+ while ((cdfLo + 1) >= cdfHi) {
+ /* clip */
+ if (*dataQ7 > 0) {
+ *dataQ7 -= 128;
+ cdfHi = cdfLo;
+ cdfLo = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+ } else {
+ *dataQ7 += 128;
+ cdfLo = cdfHi;
+ cdfHi = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+ }
+ }
+
+ dataQ7++;
+ /* increment only once per 4 iterations */
+ envQ8 += (k & 1) & (k >> 1);
+
+
+ /* update interval */
+ W_upper_LSB = (WebRtc_UWord16)W_upper;
+ W_upper_MSB = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+ W_lower = WEBRTC_SPL_UMUL_32_16(cdfLo, W_upper_MSB);
+ W_lower += WEBRTC_SPL_UMUL_32_16_RSFT16(cdfLo, W_upper_LSB);
+ W_upper = WEBRTC_SPL_UMUL_32_16(cdfHi, W_upper_MSB);
+ W_upper += WEBRTC_SPL_UMUL_32_16_RSFT16(cdfHi, W_upper_LSB);
+
+ /* 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 */
+ streamPtrCarry = streamPtr;
+ if (streamData->full == 0) {
+ negcarry = *streamPtrCarry;
+ negcarry += 0x0100;
+ *streamPtrCarry = negcarry;
+ while (!(negcarry))
+ {
+ negcarry = *--streamPtrCarry;
+ negcarry++;
+ *streamPtrCarry = negcarry;
+ }
+ } else {
+ while (!(++(*--streamPtrCarry)));
+ }
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ W_upper = WEBRTC_SPL_LSHIFT_U32(W_upper, 8);
+ if (streamData->full == 0) {
+ *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_U32(
+ streamData->streamval, 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_U32(
+ WEBRTC_SPL_RSHIFT_U32(streamData->streamval, 24), 8);
+ streamData->full = 0;
+ }
+
+ if( streamPtr > maxStreamPtr )
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+
+ streamData->streamval = WEBRTC_SPL_LSHIFT_U32(streamData->streamval, 8);
+ }
+ }
+
+ /* calculate new stream_index */
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Input/Output:
+ * - dataQ7 : input: dither vector, output: data vector
+ *
+ * Return value : number of bytes in the stream so far
+ * -1 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecLogisticMulti2(WebRtc_Word16 *dataQ7,
+ Bitstr_dec *streamData,
+ const WebRtc_Word32 *envQ8,
+ const WebRtc_Word16 lenData)
+{
+ WebRtc_UWord32 W_lower;
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord16 W_upper_LSB;
+ WebRtc_UWord16 W_upper_MSB;
+ WebRtc_UWord32 streamVal;
+ WebRtc_UWord16 cdfTmp;
+ WebRtc_Word32 res;
+ WebRtc_Word32 inSqrt;
+ WebRtc_Word32 newRes;
+ const WebRtc_UWord16 *streamPtr;
+ WebRtc_Word16 candQ7;
+ WebRtc_Word16 envCount;
+ WebRtc_UWord16 tmpARSpecQ8 = 0;
+ int k, i;
+
+
+ /* point to beginning of stream buffer */
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+
+ /* Check if it is first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamVal = WEBRTC_SPL_LSHIFT_U32(*streamPtr++, 16);
+ streamVal |= *streamPtr++;
+
+ } else {
+ streamVal = streamData->streamval;
+ }
+
+
+ res = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1,
+ WEBRTC_SPL_RSHIFT_W16(WebRtcSpl_GetSizeInBits(envQ8[0]), 1));
+ envCount = 0;
+
+ /* code assumes lenData%4 == 0 */
+ for (k = 0; k < lenData; k += 4)
+ {
+ int k4;
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ inSqrt = envQ8[envCount];
+ i = 10;
+
+ /* For safty reasons */
+ if (inSqrt < 0)
+ inSqrt=-inSqrt;
+
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(inSqrt, res) + res, 1);
+ do
+ {
+ res = newRes;
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(inSqrt, res) + res, 1);
+ } while (newRes != res && i-- > 0);
+
+ tmpARSpecQ8 = (WebRtc_UWord16)newRes;
+
+ for(k4 = 0; k4 < 4; k4++)
+ {
+ /* find the integer *data for which streamVal lies in [W_lower+1, W_upper] */
+ W_upper_LSB = (WebRtc_UWord16) (W_upper & 0x0000FFFF);
+ W_upper_MSB = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+ /* find first candidate by inverting the logistic cdf
+ * Input dither value collected from io-stream */
+ candQ7 = - *dataQ7 + 64;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
+ W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
+
+ if (streamVal > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
+ W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
+
+ while (streamVal > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
+ W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
+
+ /* error check */
+ if (W_lower == W_tmp) {
+ return -1;
+ }
+ }
+ W_upper = W_tmp;
+
+ /* Output value put in dataQ7: another sample decoded */
+ *dataQ7 = candQ7 - 64;
+ }
+ else
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
+ W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
+
+ while ( !(streamVal > W_tmp) )
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
+ W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
+
+ /* error check */
+ if (W_upper == W_tmp){
+ return -1;
+ }
+ }
+ W_lower = W_tmp;
+
+ /* Output value put in dataQ7: another sample decoded */
+ *dataQ7 = candQ7 + 64;
+ }
+
+ dataQ7++;
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamVal -= W_lower;
+
+ /* renormalize interval and update streamVal
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamVal = WEBRTC_SPL_LSHIFT_W32(streamVal, 8) | (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamVal = WEBRTC_SPL_LSHIFT_W32(streamVal, 8) |
+ WEBRTC_SPL_RSHIFT_U16(*streamPtr, 8);
+ streamData->full = 0;
+ }
+ W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
+ }
+ }
+ envCount++;
+ }
+
+ streamData->stream_index = streamPtr - 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 - 3 + !streamData->full);
+ else
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/arith_routins.h b/src/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
new file mode 100644
index 0000000..9aa49da
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
@@ -0,0 +1,160 @@
+/*
+ * 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_routins.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+
+#include "structs.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - dataQ7 : data vector in Q7
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok,
+ * <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(
+ Bitstr_enc *streamData,
+ WebRtc_Word16 *dataQ7,
+ const WebRtc_UWord16 *env,
+ const WebRtc_Word16 lenData);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ *
+ * Return value : number of bytes in the stream
+ */
+WebRtc_Word16 WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Input/Output:
+ * - dataQ7 : input: dither vector, output: data vector, in Q7
+ *
+ * Return value : number of bytes in the stream so far
+ * <0 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecLogisticMulti2(
+ WebRtc_Word16 *data,
+ Bitstr_dec *streamData,
+ const WebRtc_Word32 *env,
+ const WebRtc_Word16 lenData);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - data : data vector
+ * - cdf : array of cdf arrays
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok
+ * <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(
+ Bitstr_enc *streamData,
+ const WebRtc_Word16 *data,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_Word16 lenData);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, using
+ * method of bisection.
+ * C df tables should be of size 2^k-1 (which corresponds to an
+ * alphabet size of 2^k-2)
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - cdfSize : array of cdf table sizes+1 (power of two: 2^k)
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in the stream
+ * <0 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecHistBisectMulti(
+ WebRtc_Word16 *data,
+ Bitstr_dec *streamData,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_UWord16 *cdfSize,
+ const WebRtc_Word16 lenData);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * 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.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - initIndex : vector of initial cdf table search entries
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in original stream
+ * <0 if error detected
+ */
+WebRtc_Word16 WebRtcIsacfix_DecHistOneStepMulti(
+ WebRtc_Word16 *data,
+ Bitstr_dec *streamData,
+ const WebRtc_UWord16 **cdf,
+ const WebRtc_UWord16 *initIndex,
+ const WebRtc_Word16 lenData);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c b/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
new file mode 100644
index 0000000..a274b66
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
@@ -0,0 +1,1022 @@
+/*
+ * 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.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ * NOTE! Castings needed for C55, do not remove!
+ *
+ */
+
+#include "bandwidth_estimator.h"
+#include "settings.h"
+
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const WebRtc_Word16 kQRateTable[12] = {
+ 10000, 11115, 12355, 13733, 15265, 16967,
+ 18860, 20963, 23301, 25900, 28789, 32000
+};
+
+/* 0.1 times the values in the table kQRateTable */
+/* values are in Q16 */
+static const WebRtc_Word32 KQRate01[12] = {
+ 65536000, 72843264, 80969728, 90000589, 100040704, 111194931,
+ 123600896, 137383117, 152705434, 169738240, 188671590, 209715200
+};
+
+/* Bits per Bytes Seconds
+ * 8 bits/byte * 1000 msec/sec * 1/framelength (in msec)->bits/byte*sec
+ * frame length will either be 30 or 60 msec. 8738 is 1/60 in Q19 and 1/30 in Q18
+ * The following number is either in Q15 or Q14 depending on the current frame length */
+static const WebRtc_Word32 kBitsByteSec = 4369000;
+
+/* Received header rate. First value is for 30 ms packets and second for 60 ms */
+static const WebRtc_Word16 kRecHeaderRate[2] = {
+ 9333, 4666
+};
+
+/* Inverted minimum and maximum bandwidth in Q30.
+ minBwInv 30 ms, maxBwInv 30 ms,
+ minBwInv 60 ms, maxBwInv 69 ms
+*/
+static const WebRtc_Word32 kInvBandwidth[4] = {
+ 55539, 25978,
+ 73213, 29284
+};
+
+/* Number of samples in 25 msec */
+static const WebRtc_Word32 kSamplesIn25msec = 400;
+
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ * - bweStr : Struct containing bandwidth information.
+ *
+ * Return value : 0
+ */
+WebRtc_Word32 WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr *bweStr)
+{
+ bweStr->prevFrameSizeMs = INIT_FRAME_LEN;
+ bweStr->prevRtpNumber = 0;
+ bweStr->prevSendTime = 0;
+ bweStr->prevArrivalTime = 0;
+ bweStr->prevRtpRate = 1;
+ bweStr->lastUpdate = 0;
+ bweStr->lastReduction = 0;
+ bweStr->countUpdates = -9;
+
+ /* INIT_BN_EST = 20000
+ * INIT_BN_EST_Q7 = 2560000
+ * INIT_HDR_RATE = 4666
+ * INIT_REC_BN_EST_Q5 = 789312
+ *
+ * recBwInv = 1/(INIT_BN_EST + INIT_HDR_RATE) in Q30
+ * recBwAvg = INIT_BN_EST + INIT_HDR_RATE in Q5
+ */
+ bweStr->recBwInv = 43531;
+ bweStr->recBw = INIT_BN_EST;
+ bweStr->recBwAvgQ = INIT_BN_EST_Q7;
+ bweStr->recBwAvg = INIT_REC_BN_EST_Q5;
+ bweStr->recJitter = (WebRtc_Word32) 327680; /* 10 in Q15 */
+ bweStr->recJitterShortTerm = 0;
+ bweStr->recJitterShortTermAbs = (WebRtc_Word32) 40960; /* 5 in Q13 */
+ bweStr->recMaxDelay = (WebRtc_Word32) 10;
+ bweStr->recMaxDelayAvgQ = (WebRtc_Word32) 5120; /* 10 in Q9 */
+ bweStr->recHeaderRate = INIT_HDR_RATE;
+ bweStr->countRecPkts = 0;
+ bweStr->sendBwAvg = INIT_BN_EST_Q7;
+ bweStr->sendMaxDelayAvg = (WebRtc_Word32) 5120; /* 10 in Q9 */
+
+ bweStr->countHighSpeedRec = 0;
+ bweStr->highSpeedRec = 0;
+ bweStr->countHighSpeedSent = 0;
+ bweStr->highSpeedSend = 0;
+ bweStr->inWaitPeriod = 0;
+
+ /* Find the inverse of the max bw and min bw in Q30
+ * (1 / (MAX_ISAC_BW + INIT_HDR_RATE) in Q30
+ * (1 / (MIN_ISAC_BW + INIT_HDR_RATE) in Q30
+ */
+ bweStr->maxBwInv = kInvBandwidth[3];
+ bweStr->minBwInv = kInvBandwidth[2];
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ * - bweStr : struct containing bandwidth information.
+ * - rtpNumber : value from RTP packet, from NetEq
+ * - frameSize : length of signal frame in ms, from iSAC decoder
+ * - sendTime : value in RTP header giving send time in samples
+ * - arrivalTime : 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
+ *
+ * Return value : 0 if everything went fine,
+ * -1 otherwise
+ */
+WebRtc_Word32 WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bweStr,
+ const WebRtc_UWord16 rtpNumber,
+ const WebRtc_Word16 frameSize,
+ const WebRtc_UWord32 sendTime,
+ const WebRtc_UWord32 arrivalTime,
+ const WebRtc_Word16 pksize,
+ const WebRtc_UWord16 Index)
+{
+ WebRtc_UWord16 weight = 0;
+ WebRtc_UWord32 currBwInv = 0;
+ WebRtc_UWord16 recRtpRate;
+ WebRtc_UWord32 arrTimeProj;
+ WebRtc_Word32 arrTimeDiff;
+ WebRtc_Word32 arrTimeNoise;
+ WebRtc_Word32 arrTimeNoiseAbs;
+ WebRtc_Word32 sendTimeDiff;
+
+ WebRtc_Word32 delayCorrFactor = DELAY_CORRECTION_MED;
+ WebRtc_Word32 lateDiff = 0;
+ WebRtc_Word16 immediateSet = 0;
+ WebRtc_Word32 frameSizeSampl;
+
+ WebRtc_Word32 temp;
+ WebRtc_Word32 msec;
+ WebRtc_UWord32 exponent;
+ WebRtc_UWord32 reductionFactor;
+ WebRtc_UWord32 numBytesInv;
+ WebRtc_Word32 sign;
+
+ WebRtc_UWord32 byteSecondsPerBit;
+ WebRtc_UWord32 tempLower;
+ WebRtc_UWord32 tempUpper;
+ WebRtc_Word32 recBwAvgInv;
+ WebRtc_Word32 numPktsExpected;
+
+ WebRtc_Word16 errCode;
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+ /* The function also checks if Index has a valid value */
+ errCode = WebRtcIsacfix_UpdateUplinkBwRec(bweStr, Index);
+ if (errCode <0) {
+ return(errCode);
+ }
+
+
+ /* UPDATE ESTIMATES ON THIS SIDE */
+
+ /* Bits per second per byte * 1/30 or 1/60 */
+ if (frameSize == 60) {
+ /* If frameSize changed since last call, from 30 to 60, recalculate some values */
+ if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+ bweStr->countUpdates = 10;
+ bweStr->recHeaderRate = kRecHeaderRate[1];
+
+ bweStr->maxBwInv = kInvBandwidth[3];
+ bweStr->minBwInv = kInvBandwidth[2];
+ bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, (bweStr->recBw + bweStr->recHeaderRate));
+ }
+
+ /* kBitsByteSec is in Q15 */
+ recRtpRate = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(kBitsByteSec,
+ (WebRtc_Word32)pksize), 15) + bweStr->recHeaderRate;
+
+ } else {
+ /* If frameSize changed since last call, from 60 to 30, recalculate some values */
+ if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+ bweStr->countUpdates = 10;
+ bweStr->recHeaderRate = kRecHeaderRate[0];
+
+ bweStr->maxBwInv = kInvBandwidth[1];
+ bweStr->minBwInv = kInvBandwidth[0];
+ bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, (bweStr->recBw + bweStr->recHeaderRate));
+ }
+
+ /* kBitsByteSec is in Q14 */
+ recRtpRate = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(kBitsByteSec,
+ (WebRtc_Word32)pksize), 14) + bweStr->recHeaderRate;
+ }
+
+
+ /* Check for timer wrap-around */
+ if (arrivalTime < bweStr->prevArrivalTime) {
+ bweStr->prevArrivalTime = arrivalTime;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+
+ bweStr->countRecPkts = 0;
+
+ /* store frame size */
+ bweStr->prevFrameSizeMs = frameSize;
+
+ /* store far-side transmission rate */
+ bweStr->prevRtpRate = recRtpRate;
+
+ /* store far-side RTP time stamp */
+ bweStr->prevRtpNumber = rtpNumber;
+
+ return 0;
+ }
+
+ bweStr->countRecPkts++;
+
+ /* Calculate framesize in msec */
+ frameSizeSampl = WEBRTC_SPL_MUL_16_16((WebRtc_Word16)SAMPLES_PER_MSEC, frameSize);
+
+ /* Check that it's not one of the first 9 packets */
+ if ( bweStr->countUpdates > 0 ) {
+
+ /* Stay in Wait Period for 1.5 seconds (no updates in wait period) */
+ if(bweStr->inWaitPeriod) {
+ if ((arrivalTime - bweStr->startWaitPeriod)> FS_1_HALF) {
+ bweStr->inWaitPeriod = 0;
+ }
+ }
+
+ /* If not been updated for a long time, reduce the BN estimate */
+
+ /* Check send time difference between this packet and previous received */
+ sendTimeDiff = sendTime - bweStr->prevSendTime;
+ if (sendTimeDiff <= WEBRTC_SPL_LSHIFT_W32(frameSizeSampl, 1)) {
+
+ /* Only update if 3 seconds has past since last update */
+ if ((arrivalTime - bweStr->lastUpdate) > FS3) {
+
+ /* Calculate expected number of received packets since last update */
+ numPktsExpected = WEBRTC_SPL_UDIV(arrivalTime - bweStr->lastUpdate, frameSizeSampl);
+
+ /* If received number of packets is more than 90% of expected (922 = 0.9 in Q10): */
+ /* do the update, else not */
+ if(WEBRTC_SPL_LSHIFT_W32(bweStr->countRecPkts, 10) > WEBRTC_SPL_MUL_16_16(922, numPktsExpected)) {
+ /* Q4 chosen to approx dividing by 16 */
+ msec = (arrivalTime - bweStr->lastReduction);
+
+ /* the number below represents 13 seconds, highly unlikely
+ but to insure no overflow when reduction factor is multiplied by recBw inverse */
+ if (msec > 208000) {
+ msec = 208000;
+ }
+
+ /* Q20 2^(negative number: - 76/1048576) = .99995
+ product is Q24 */
+ exponent = WEBRTC_SPL_UMUL(0x0000004C, msec);
+
+ /* do the approx with positive exponent so that value is actually rf^-1
+ and multiply by bw inverse */
+ reductionFactor = WEBRTC_SPL_RSHIFT_U32(0x01000000 | (exponent & 0x00FFFFFF),
+ WEBRTC_SPL_RSHIFT_U32(exponent, 24));
+
+ /* reductionFactor in Q13 */
+ reductionFactor = WEBRTC_SPL_RSHIFT_U32(reductionFactor, 11);
+
+ if ( reductionFactor != 0 ) {
+ bweStr->recBwInv = WEBRTC_SPL_MUL((WebRtc_Word32)bweStr->recBwInv, (WebRtc_Word32)reductionFactor);
+ bweStr->recBwInv = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)bweStr->recBwInv, 13);
+
+ } else {
+ /* recBwInv = 1 / (INIT_BN_EST + INIT_HDR_RATE) in Q26 (Q30??)*/
+ bweStr->recBwInv = WEBRTC_SPL_DIV((1073741824 +
+ WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)INIT_BN_EST + INIT_HDR_RATE), 1)), INIT_BN_EST + INIT_HDR_RATE);
+ }
+
+ /* reset time-since-update counter */
+ bweStr->lastReduction = arrivalTime;
+ } else {
+ /* Delay last reduction with 3 seconds */
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->countRecPkts = 0;
+ }
+ }
+ } else {
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->countRecPkts = 0;
+ }
+
+
+ /* update only if previous packet was not lost */
+ if ( rtpNumber == bweStr->prevRtpNumber + 1 ) {
+ arrTimeDiff = arrivalTime - bweStr->prevArrivalTime;
+
+ if (!(bweStr->highSpeedSend && bweStr->highSpeedRec)) {
+ if (arrTimeDiff > frameSizeSampl) {
+ if (sendTimeDiff > 0) {
+ lateDiff = arrTimeDiff - sendTimeDiff -
+ WEBRTC_SPL_LSHIFT_W32(frameSizeSampl, 1);
+ } else {
+ lateDiff = arrTimeDiff - frameSizeSampl;
+ }
+
+ /* 8000 is 1/2 second (in samples at FS) */
+ if (lateDiff > 8000) {
+ delayCorrFactor = (WebRtc_Word32) DELAY_CORRECTION_MAX;
+ bweStr->inWaitPeriod = 1;
+ bweStr->startWaitPeriod = arrivalTime;
+ immediateSet = 1;
+ } else if (lateDiff > 5120) {
+ delayCorrFactor = (WebRtc_Word32) DELAY_CORRECTION_MED;
+ immediateSet = 1;
+ bweStr->inWaitPeriod = 1;
+ bweStr->startWaitPeriod = arrivalTime;
+ }
+ }
+ }
+
+ if ((bweStr->prevRtpRate > WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) bweStr->recBwAvg, 5)) &&
+ (recRtpRate > WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)bweStr->recBwAvg, 5)) &&
+ !bweStr->inWaitPeriod) {
+
+ /* test if still in initiation period and increment counter */
+ if (bweStr->countUpdates++ > 99) {
+ /* constant weight after initiation part, 0.01 in Q13 */
+ weight = (WebRtc_UWord16) 82;
+ } else {
+ /* weight decreases with number of updates, 1/countUpdates in Q13 */
+ weight = (WebRtc_UWord16) WebRtcSpl_DivW32W16(
+ (WebRtc_Word32)(8192 + WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) bweStr->countUpdates, 1)),
+ (WebRtc_Word16)bweStr->countUpdates);
+ }
+
+ /* Bottle Neck Estimation */
+
+ /* limit outliers, if more than 25 ms too much */
+ if (arrTimeDiff > frameSizeSampl + kSamplesIn25msec) {
+ arrTimeDiff = frameSizeSampl + kSamplesIn25msec;
+ }
+
+ /* don't allow it to be less than frame rate - 10 ms */
+ if (arrTimeDiff < frameSizeSampl - FRAMESAMPLES_10ms) {
+ arrTimeDiff = frameSizeSampl - FRAMESAMPLES_10ms;
+ }
+
+ /* compute inverse receiving rate for last packet, in Q19 */
+ numBytesInv = (WebRtc_UWord16) WebRtcSpl_DivW32W16(
+ (WebRtc_Word32)(524288 + WEBRTC_SPL_RSHIFT_W32(((WebRtc_Word32)pksize + HEADER_SIZE), 1)),
+ (WebRtc_Word16)(pksize + HEADER_SIZE));
+
+ /* 8389 is ~ 1/128000 in Q30 */
+ byteSecondsPerBit = WEBRTC_SPL_MUL_16_16(arrTimeDiff, 8389);
+
+ /* get upper N bits */
+ tempUpper = WEBRTC_SPL_RSHIFT_U32(byteSecondsPerBit, 15);
+
+ /* get lower 15 bits */
+ tempLower = byteSecondsPerBit & 0x00007FFF;
+
+ tempUpper = WEBRTC_SPL_MUL(tempUpper, numBytesInv);
+ tempLower = WEBRTC_SPL_MUL(tempLower, numBytesInv);
+ tempLower = WEBRTC_SPL_RSHIFT_U32(tempLower, 15);
+
+ currBwInv = tempUpper + tempLower;
+ currBwInv = WEBRTC_SPL_RSHIFT_U32(currBwInv, 4);
+
+ /* Limit inv rate. Note that minBwInv > maxBwInv! */
+ if(currBwInv < bweStr->maxBwInv) {
+ currBwInv = bweStr->maxBwInv;
+ } else if(currBwInv > bweStr->minBwInv) {
+ currBwInv = bweStr->minBwInv;
+ }
+
+ /* update bottle neck rate estimate */
+ bweStr->recBwInv = WEBRTC_SPL_UMUL(weight, currBwInv) +
+ WEBRTC_SPL_UMUL((WebRtc_UWord32) 8192 - weight, bweStr->recBwInv);
+
+ /* Shift back to Q30 from Q40 (actual used bits shouldn't be more than 27 based on minBwInv)
+ up to 30 bits used with Q13 weight */
+ bweStr->recBwInv = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwInv, 13);
+
+ /* reset time-since-update counter */
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->countRecPkts = 0;
+
+ /* to save resolution compute the inverse of recBwAvg in Q26 by left shifting numerator to 2^31
+ and NOT right shifting recBwAvg 5 bits to an integer
+ At max 13 bits are used
+ shift to Q5 */
+ recBwAvgInv = WEBRTC_SPL_UDIV((WebRtc_UWord32)(0x80000000 + WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 1)),
+ bweStr->recBwAvg);
+
+ /* Calculate Projected arrival time difference */
+
+ /* The numerator of the quotient can be 22 bits so right shift inv by 4 to avoid overflow
+ result in Q22 */
+ arrTimeProj = WEBRTC_SPL_MUL((WebRtc_Word32)8000, recBwAvgInv);
+ /* shift to Q22 */
+ arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 4);
+ /* complete calulation */
+ arrTimeProj = WEBRTC_SPL_MUL(((WebRtc_Word32)pksize + HEADER_SIZE), arrTimeProj);
+ /* shift to Q10 */
+ arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 12);
+
+ /* difference between projected and actual arrival time differences */
+ /* Q9 (only shift arrTimeDiff by 5 to simulate divide by 16 (need to revisit if change sampling rate) DH */
+ if (WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6) > (WebRtc_Word32)arrTimeProj) {
+ arrTimeNoise = WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6) - arrTimeProj;
+ sign = 1;
+ } else {
+ arrTimeNoise = arrTimeProj - WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6);
+ sign = -1;
+ }
+
+ /* Q9 */
+ arrTimeNoiseAbs = arrTimeNoise;
+
+ /* long term averaged absolute jitter, Q15 */
+ weight = WEBRTC_SPL_RSHIFT_W32(weight, 3);
+ bweStr->recJitter = WEBRTC_SPL_MUL(weight, WEBRTC_SPL_LSHIFT_W32(arrTimeNoiseAbs, 5))
+ + WEBRTC_SPL_MUL(1024 - weight, bweStr->recJitter);
+
+ /* remove the fractional portion */
+ bweStr->recJitter = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitter, 10);
+
+ /* Maximum jitter is 10 msec in Q15 */
+ if (bweStr->recJitter > (WebRtc_Word32)327680) {
+ bweStr->recJitter = (WebRtc_Word32)327680;
+ }
+
+ /* short term averaged absolute jitter */
+ /* Calculation in Q13 products in Q23 */
+ bweStr->recJitterShortTermAbs = WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32(arrTimeNoiseAbs, 3)) +
+ WEBRTC_SPL_MUL(973, bweStr->recJitterShortTermAbs);
+ bweStr->recJitterShortTermAbs = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTermAbs , 10);
+
+ /* short term averaged jitter */
+ /* Calculation in Q13 products in Q23 */
+ bweStr->recJitterShortTerm = WEBRTC_SPL_MUL(205, WEBRTC_SPL_LSHIFT_W32(arrTimeNoise, 3)) * sign +
+ WEBRTC_SPL_MUL(3891, bweStr->recJitterShortTerm);
+
+ if (bweStr->recJitterShortTerm < 0) {
+ temp = -bweStr->recJitterShortTerm;
+ temp = WEBRTC_SPL_RSHIFT_W32(temp, 12);
+ bweStr->recJitterShortTerm = -temp;
+ } else {
+ bweStr->recJitterShortTerm = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTerm, 12);
+ }
+ }
+ }
+ } else {
+ /* reset time-since-update counter when receiving the first 9 packets */
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->countRecPkts = 0;
+ bweStr->countUpdates++;
+ }
+
+ /* Limit to minimum or maximum bottle neck rate (in Q30) */
+ if (bweStr->recBwInv > bweStr->minBwInv) {
+ bweStr->recBwInv = bweStr->minBwInv;
+ } else if (bweStr->recBwInv < bweStr->maxBwInv) {
+ bweStr->recBwInv = bweStr->maxBwInv;
+ }
+
+
+ /* store frame length */
+ bweStr->prevFrameSizeMs = frameSize;
+
+ /* store far-side transmission rate */
+ bweStr->prevRtpRate = recRtpRate;
+
+ /* store far-side RTP time stamp */
+ bweStr->prevRtpNumber = rtpNumber;
+
+ /* Replace bweStr->recMaxDelay by the new value (atomic operation) */
+ if (bweStr->prevArrivalTime != 0xffffffff) {
+ bweStr->recMaxDelay = WEBRTC_SPL_MUL(3, bweStr->recJitter);
+ }
+
+ /* store arrival time stamp */
+ bweStr->prevArrivalTime = arrivalTime;
+ bweStr->prevSendTime = sendTime;
+
+ /* Replace bweStr->recBw by the new value */
+ bweStr->recBw = WEBRTC_SPL_UDIV(1073741824, bweStr->recBwInv) - bweStr->recHeaderRate;
+
+ if (immediateSet) {
+ /* delay correction factor is in Q10 */
+ bweStr->recBw = WEBRTC_SPL_UMUL(delayCorrFactor, bweStr->recBw);
+ bweStr->recBw = WEBRTC_SPL_RSHIFT_U32(bweStr->recBw, 10);
+
+ if (bweStr->recBw < (WebRtc_Word32) MIN_ISAC_BW) {
+ bweStr->recBw = (WebRtc_Word32) MIN_ISAC_BW;
+ }
+
+ bweStr->recBwAvg = WEBRTC_SPL_LSHIFT_U32(bweStr->recBw + bweStr->recHeaderRate, 5);
+
+ bweStr->recBwAvgQ = WEBRTC_SPL_LSHIFT_U32(bweStr->recBw, 7);
+
+ bweStr->recJitterShortTerm = 0;
+
+ bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, bweStr->recBw + bweStr->recHeaderRate);
+
+ immediateSet = 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 WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bweStr,
+ const WebRtc_Word16 Index)
+{
+ WebRtc_UWord16 RateInd;
+
+ if ( (Index < 0) || (Index > 23) ) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+ if ( Index > 11 ) {
+ RateInd = Index - 12;
+ /* compute the jitter estimate as decoded on the other side in Q9 */
+ /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MAX_ISAC_MD */
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+ WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)MAX_ISAC_MD, 9));
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
+
+ } else {
+ RateInd = Index;
+ /* compute the jitter estimate as decoded on the other side in Q9 */
+ /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MIN_ISAC_MD */
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+ WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)MIN_ISAC_MD,9));
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
+
+ }
+
+
+ /* compute the BN estimate as decoded on the other side */
+ /* sendBwAvg = 0.9 * sendBwAvg + 0.1 * kQRateTable[RateInd]; */
+ bweStr->sendBwAvg = WEBRTC_SPL_UMUL(461, bweStr->sendBwAvg) +
+ WEBRTC_SPL_UMUL(51, WEBRTC_SPL_LSHIFT_U32(kQRateTable[RateInd], 7));
+ bweStr->sendBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 9);
+
+
+ if (WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7) > 28000 && !bweStr->highSpeedSend) {
+ bweStr->countHighSpeedSent++;
+
+ /* approx 2 seconds with 30ms frames */
+ if (bweStr->countHighSpeedSent >= 66) {
+ bweStr->highSpeedSend = 1;
+ }
+ } else if (!bweStr->highSpeedSend) {
+ bweStr->countHighSpeedSent = 0;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ * - bweStr : BWE struct
+ *
+ * Return:
+ * bandwith and jitter index (0..23)
+ */
+WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bweStr)
+{
+ WebRtc_Word32 rate;
+ WebRtc_Word32 maxDelay;
+ WebRtc_UWord16 rateInd;
+ WebRtc_UWord16 maxDelayBit;
+ WebRtc_Word32 tempTerm1;
+ WebRtc_Word32 tempTerm2;
+ WebRtc_Word32 tempTermX;
+ WebRtc_Word32 tempTermY;
+ WebRtc_Word32 tempMin;
+ WebRtc_Word32 tempMax;
+
+ /* Get Rate Index */
+
+ /* Get unquantized rate. Always returns 10000 <= rate <= 32000 */
+ rate = WebRtcIsacfix_GetDownlinkBandwidth(bweStr);
+
+ /* Compute the averaged BN estimate on this side */
+
+ /* recBwAvg = 0.9 * recBwAvg + 0.1 * (rate + bweStr->recHeaderRate), 0.9 and 0.1 in Q9 */
+ bweStr->recBwAvg = WEBRTC_SPL_UMUL(922, bweStr->recBwAvg) +
+ WEBRTC_SPL_UMUL(102, WEBRTC_SPL_LSHIFT_U32((WebRtc_UWord32)rate + bweStr->recHeaderRate, 5));
+ bweStr->recBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 10);
+
+ /* find quantization index that gives the closest rate after averaging */
+ for (rateInd = 1; rateInd < 12; rateInd++) {
+ if (rate <= kQRateTable[rateInd]){
+ break;
+ }
+ }
+
+ /* find closest quantization index, and update quantized average by taking: */
+ /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+ /* 0.9 times recBwAvgQ in Q16 */
+ /* 461/512 - 25/65536 =0.900009 */
+ tempTerm1 = WEBRTC_SPL_MUL(bweStr->recBwAvgQ, 25);
+ tempTerm1 = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 7);
+ tempTermX = WEBRTC_SPL_UMUL(461, bweStr->recBwAvgQ) - tempTerm1;
+
+ /* rate in Q16 */
+ tempTermY = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)rate, 16);
+
+ /* 0.1 * kQRateTable[rateInd] = KQRate01[rateInd] */
+ tempTerm1 = tempTermX + KQRate01[rateInd] - tempTermY;
+ tempTerm2 = tempTermY - tempTermX - KQRate01[rateInd-1];
+
+ /* Compare (0.9 * recBwAvgQ + 0.1 * kQRateTable[rateInd] - rate) >
+ (rate - 0.9 * recBwAvgQ - 0.1 * kQRateTable[rateInd-1]) */
+ if (tempTerm1 > tempTerm2) {
+ rateInd--;
+ }
+
+ /* Update quantized average by taking: */
+ /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+ /* Add 0.1 times kQRateTable[rateInd], in Q16 */
+ tempTermX += KQRate01[rateInd];
+
+ /* Shift back to Q7 */
+ bweStr->recBwAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTermX, 9);
+
+ /* Count consecutive received bandwidth above 28000 kbps (28000 in Q7 = 3584000) */
+ /* If 66 high estimates in a row, set highSpeedRec to one */
+ /* 66 corresponds to ~2 seconds in 30 msec mode */
+ if ((bweStr->recBwAvgQ > 3584000) && !bweStr->highSpeedRec) {
+ bweStr->countHighSpeedRec++;
+ if (bweStr->countHighSpeedRec >= 66) {
+ bweStr->highSpeedRec = 1;
+ }
+ } else if (!bweStr->highSpeedRec) {
+ bweStr->countHighSpeedRec = 0;
+ }
+
+ /* Get Max Delay Bit */
+
+ /* get unquantized max delay */
+ maxDelay = WebRtcIsacfix_GetDownlinkMaxDelay(bweStr);
+
+ /* Update quantized max delay average */
+ tempMax = 652800; /* MAX_ISAC_MD * 0.1 in Q18 */
+ tempMin = 130560; /* MIN_ISAC_MD * 0.1 in Q18 */
+ tempTermX = WEBRTC_SPL_MUL((WebRtc_Word32)bweStr->recMaxDelayAvgQ, (WebRtc_Word32)461);
+ tempTermY = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)maxDelay, 18);
+
+ tempTerm1 = tempTermX + tempMax - tempTermY;
+ tempTerm2 = tempTermY - tempTermX - tempMin;
+
+ if ( tempTerm1 > tempTerm2) {
+ maxDelayBit = 0;
+ tempTerm1 = tempTermX + tempMin;
+
+ /* update quantized average, shift back to Q9 */
+ bweStr->recMaxDelayAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 9);
+ } else {
+ maxDelayBit = 12;
+ tempTerm1 = tempTermX + tempMax;
+
+ /* update quantized average, shift back to Q9 */
+ bweStr->recMaxDelayAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 9);
+ }
+
+ /* Return bandwitdh and jitter index (0..23) */
+ return (WebRtc_UWord16)(rateInd + maxDelayBit);
+}
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bweStr)
+{
+ WebRtc_UWord32 recBw;
+ WebRtc_Word32 jitter_sign; /* Q8 */
+ WebRtc_Word32 bw_adjust; /* Q16 */
+ WebRtc_Word32 rec_jitter_short_term_abs_inv; /* Q18 */
+ WebRtc_Word32 temp;
+
+ /* Q18 rec jitter short term abs is in Q13, multiply it by 2^13 to save precision
+ 2^18 then needs to be shifted 13 bits to 2^31 */
+ rec_jitter_short_term_abs_inv = WEBRTC_SPL_UDIV(0x80000000, bweStr->recJitterShortTermAbs);
+
+ /* Q27 = 9 + 18 */
+ jitter_sign = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTerm, 4), (WebRtc_Word32)rec_jitter_short_term_abs_inv);
+
+ if (jitter_sign < 0) {
+ temp = -jitter_sign;
+ temp = WEBRTC_SPL_RSHIFT_W32(temp, 19);
+ jitter_sign = -temp;
+ } else {
+ jitter_sign = WEBRTC_SPL_RSHIFT_W32(jitter_sign, 19);
+ }
+
+ /* adjust bw proportionally to negative average jitter sign */
+ //bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+ //Q8 -> Q16 .15 +.15 * jitter^2 first term is .15 in Q16 latter term is Q8*Q8*Q8
+ //38 in Q8 ~.15 9830 in Q16 ~.15
+ temp = 9830 + WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL(38, WEBRTC_SPL_MUL(jitter_sign, jitter_sign))), 8);
+
+ if (jitter_sign < 0) {
+ temp = WEBRTC_SPL_MUL(jitter_sign, temp);
+ temp = -temp;
+ temp = WEBRTC_SPL_RSHIFT_W32(temp, 8);
+ bw_adjust = (WebRtc_UWord32)65536 + temp; /* (1 << 16) + temp; */
+ } else {
+ bw_adjust = (WebRtc_UWord32)65536 - WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(jitter_sign, temp), 8);/* (1 << 16) - ((jitter_sign * temp) >> 8); */
+ }
+
+ //make sure following multiplication won't overflow
+ //bw adjust now Q14
+ bw_adjust = WEBRTC_SPL_RSHIFT_W32(bw_adjust, 2);//see if good resolution is maintained
+
+ /* adjust Rate if jitter sign is mostly constant */
+ recBw = WEBRTC_SPL_UMUL(bweStr->recBw, bw_adjust);
+
+ recBw = WEBRTC_SPL_RSHIFT_W32(recBw, 14);
+
+ /* limit range of bottle neck rate */
+ if (recBw < MIN_ISAC_BW) {
+ recBw = MIN_ISAC_BW;
+ } else if (recBw > MAX_ISAC_BW) {
+ recBw = MAX_ISAC_BW;
+ }
+
+ return (WebRtc_UWord16) recBw;
+}
+
+/* Returns the mmax delay (in ms) */
+WebRtc_Word16 WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bweStr)
+{
+ WebRtc_Word16 recMaxDelay;
+
+ recMaxDelay = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(bweStr->recMaxDelay, 15);
+
+ /* limit range of jitter estimate */
+ if (recMaxDelay < MIN_ISAC_MD) {
+ recMaxDelay = MIN_ISAC_MD;
+ } else if (recMaxDelay > MAX_ISAC_MD) {
+ recMaxDelay = MAX_ISAC_MD;
+ }
+
+ return recMaxDelay;
+}
+
+/* get the bottle neck rate from here to far side, as estimated by far side */
+WebRtc_Word16 WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr *bweStr)
+{
+ WebRtc_Word16 send_bw;
+
+ send_bw = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7);
+
+ /* limit range of bottle neck rate */
+ if (send_bw < MIN_ISAC_BW) {
+ send_bw = MIN_ISAC_BW;
+ } else if (send_bw > MAX_ISAC_BW) {
+ send_bw = MAX_ISAC_BW;
+ }
+
+ return send_bw;
+}
+
+
+
+/* Returns the max delay value from the other side in ms */
+WebRtc_Word16 WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr *bweStr)
+{
+ WebRtc_Word16 send_max_delay;
+
+ send_max_delay = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
+
+ /* 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)
+ */
+WebRtc_UWord16 WebRtcIsacfix_GetMinBytes(RateModel *State,
+ WebRtc_Word16 StreamSize, /* bytes in bitstream */
+ const WebRtc_Word16 FrameSamples, /* samples per frame */
+ const WebRtc_Word16 BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const WebRtc_Word16 DelayBuildUp) /* max delay from bottle neck buffering (ms) */
+{
+ WebRtc_Word32 MinRate = 0;
+ WebRtc_UWord16 MinBytes;
+ WebRtc_Word16 TransmissionTime;
+ WebRtc_Word32 inv_Q12;
+ WebRtc_Word32 den;
+
+
+ /* 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) {
+ MinRate = INIT_RATE;
+ } else {
+ MinRate = 0;
+ }
+ } else {
+ /* handle burst */
+ if (State->BurstCounter) {
+ if (State->StillBuffered < WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL((512 - WEBRTC_SPL_DIV(512, BURST_LEN)), DelayBuildUp), 9)) {
+ /* max bps derived from BottleNeck and DelayBuildUp values */
+ inv_Q12 = WEBRTC_SPL_DIV(4096, WEBRTC_SPL_MUL(BURST_LEN, FrameSamples));
+ MinRate = WEBRTC_SPL_MUL(512 + WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(DelayBuildUp, inv_Q12), 3)), BottleNeck);
+ } else {
+ /* max bps derived from StillBuffered and DelayBuildUp values */
+ inv_Q12 = WEBRTC_SPL_DIV(4096, FrameSamples);
+ if (DelayBuildUp > State->StillBuffered) {
+ MinRate = WEBRTC_SPL_MUL(512 + WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(DelayBuildUp - State->StillBuffered, inv_Q12), 3)), BottleNeck);
+ } else if ((den = WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, (State->StillBuffered - DelayBuildUp))) >= FrameSamples) {
+ /* MinRate will be negative here */
+ MinRate = 0;
+ } else {
+ MinRate = WEBRTC_SPL_MUL((512 - WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(den, inv_Q12), 3)), BottleNeck);
+ }
+ //if (MinRate < 1.04 * BottleNeck)
+ // MinRate = 1.04 * BottleNeck;
+ //Q9
+ if (MinRate < WEBRTC_SPL_MUL(532, BottleNeck)) {
+ MinRate += WEBRTC_SPL_MUL(22, BottleNeck);
+ }
+ }
+
+ State->BurstCounter--;
+ }
+ }
+
+
+ /* convert rate from bits/second to bytes/packet */
+ //round and shift before conversion
+ MinRate += 256;
+ MinRate = WEBRTC_SPL_RSHIFT_W32(MinRate, 9);
+ MinBytes = (WebRtc_UWord16)WEBRTC_SPL_UDIV(WEBRTC_SPL_MUL(MinRate, FrameSamples), FS8);
+
+ /* 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% */
+ //517/512 ~ 1.01
+ if (WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(StreamSize, FS8), FrameSamples) > (WEBRTC_SPL_MUL(517, BottleNeck) >> 9)) {
+ if (State->PrevExceed) {
+ /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+ State->ExceedAgo -= WEBRTC_SPL_DIV(BURST_INTERVAL, BURST_LEN - 1);
+ if (State->ExceedAgo < 0) {
+ State->ExceedAgo = 0;
+ }
+ } else {
+ State->ExceedAgo += (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
+ State->PrevExceed = 1;
+ }
+ } else {
+ State->PrevExceed = 0;
+ State->ExceedAgo += (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
+ }
+
+ /* set burst flag if bottle neck not exceeded for long time */
+ if ((State->ExceedAgo > BURST_INTERVAL) && (State->BurstCounter == 0)) {
+ if (State->PrevExceed) {
+ State->BurstCounter = BURST_LEN - 1;
+ } else {
+ State->BurstCounter = BURST_LEN;
+ }
+ }
+
+
+ /* Update buffer delay */
+ TransmissionTime = (WebRtc_Word16)WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(StreamSize, 8000), BottleNeck); /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); //>>4 = SAMPLES_PER_MSEC /* ms */
+ if (State->StillBuffered < 0) {
+ State->StillBuffered = 0;
+ }
+
+ if (State->StillBuffered > 2000) {
+ State->StillBuffered = 2000;
+ }
+
+ return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(RateModel *State,
+ WebRtc_Word16 StreamSize, /* bytes in bitstream */
+ const WebRtc_Word16 FrameSamples, /* samples per frame */
+ const WebRtc_Word16 BottleNeck) /* bottle neck rate; excl headers (bps) */
+{
+ WebRtc_Word16 TransmissionTime;
+
+ /* avoid the initial "high-rate" burst */
+ State->InitCounter = 0;
+
+ /* Update buffer delay */
+ TransmissionTime = (WebRtc_Word16)WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(WEBRTC_SPL_MUL(StreamSize, 8), 1000), BottleNeck); /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
+ if (State->StillBuffered < 0) {
+ State->StillBuffered = 0;
+ }
+
+}
+
+
+void WebRtcIsacfix_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; /* ms */
+}
+
+
+
+
+
+WebRtc_Word16 WebRtcIsacfix_GetNewFrameLength(WebRtc_Word16 bottle_neck, WebRtc_Word16 current_framesamples)
+{
+ WebRtc_Word16 new_framesamples;
+
+ new_framesamples = current_framesamples;
+
+ /* find new framelength */
+ switch(current_framesamples) {
+ case 480:
+ if (bottle_neck < Thld_30_60) {
+ new_framesamples = 960;
+ }
+ break;
+ case 960:
+ if (bottle_neck >= Thld_60_30) {
+ new_framesamples = 480;
+ }
+ break;
+ default:
+ new_framesamples = -1; /* Error */
+ }
+
+ return new_framesamples;
+}
+
+WebRtc_Word16 WebRtcIsacfix_GetSnr(WebRtc_Word16 bottle_neck, WebRtc_Word16 framesamples)
+{
+ WebRtc_Word16 s2nr = 0;
+
+ /* find new SNR value */
+ //consider BottleNeck to be in Q10 ( * 1 in Q10)
+ switch(framesamples) {
+ case 480:
+ /*s2nr = -1*(a_30 << 10) + ((b_30 * bottle_neck) >> 10);*/
+ s2nr = -22500 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(500, bottle_neck, 10); //* 0.001; //+ c_30 * bottle_neck * bottle_neck * 0.000001;
+ break;
+ case 960:
+ /*s2nr = -1*(a_60 << 10) + ((b_60 * bottle_neck) >> 10);*/
+ s2nr = -22500 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(500, bottle_neck, 10); //* 0.001; //+ c_30 * bottle_neck * bottle_neck * 0.000001;
+ break;
+ default:
+ s2nr = -1; /* Error */
+ }
+
+ return s2nr; //return in Q10
+
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h b/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
new file mode 100644
index 0000000..76a50f8
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
@@ -0,0 +1,127 @@
+/*
+ * 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_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include "structs.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ * - bwest_str : Struct containing bandwidth information.
+ *
+ * Return value : 0
+ */
+
+WebRtc_Word32 WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr *bwest_str);
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ * - bweStr : struct containing bandwidth information.
+ * - rtpNumber : value from RTP packet, from NetEq
+ * - frameSize : length of signal frame in ms, from iSAC decoder
+ * - sendTime : value in RTP header giving send time in samples
+ * - arrivalTime : 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
+ *
+ * Return value : 0 if everything went fine,
+ * -1 otherwise
+ */
+
+WebRtc_Word32 WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bwest_str,
+ const WebRtc_UWord16 rtp_number,
+ const WebRtc_Word16 frameSize,
+ const WebRtc_UWord32 send_ts,
+ const WebRtc_UWord32 arr_ts,
+ const WebRtc_Word16 pksize,
+ const WebRtc_UWord16 Index);
+
+/* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
+WebRtc_Word16 WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bwest_str,
+ const WebRtc_Word16 Index);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ * - bweStr : BWE struct
+ *
+ * Return:
+ * bandwith and jitter index (0..23)
+ */
+WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bwest_str);
+
+/* Returns the bandwidth estimation (in bps) */
+WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bwest_str);
+
+/* Returns the bandwidth that iSAC should send with in bps */
+WebRtc_Word16 WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr *bwest_str);
+
+/* Returns the max delay (in ms) */
+WebRtc_Word16 WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str);
+
+/* Returns the max delay value from the other side in ms */
+WebRtc_Word16 WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr *bwest_str);
+
+/*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+WebRtc_UWord16 WebRtcIsacfix_GetMinBytes(RateModel *State,
+ WebRtc_Word16 StreamSize, /* bytes in bitstream */
+ const WebRtc_Word16 FrameLen, /* ms per frame */
+ const WebRtc_Word16 BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const WebRtc_Word16 DelayBuildUp); /* max delay from bottle neck buffering (ms) */
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(RateModel *State,
+ WebRtc_Word16 StreamSize, /* bytes in bitstream */
+ const WebRtc_Word16 FrameSamples, /* samples per frame */
+ const WebRtc_Word16 BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+
+void WebRtcIsacfix_InitRateModel(RateModel *State);
+
+/* Returns the new framelength value (input argument: bottle_neck) */
+WebRtc_Word16 WebRtcIsacfix_GetNewFrameLength(WebRtc_Word16 bottle_neck, WebRtc_Word16 current_framelength);
+
+/* Returns the new SNR value (input argument: bottle_neck) */
+//returns snr in Q10
+WebRtc_Word16 WebRtcIsacfix_GetSnr(WebRtc_Word16 bottle_neck, WebRtc_Word16 framesamples);
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/codec.h b/src/modules/audio_coding/codecs/isac/fix/source/codec.h
new file mode 100644
index 0000000..1b4f987
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/codec.h
@@ -0,0 +1,179 @@
+/*
+ * 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_FIX_SOURCE_CODEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_
+
+#include "structs.h"
+
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr *bwest_str,
+ Bitstr_dec *streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts);
+
+WebRtc_Word16 WebRtcIsacfix_DecodeImpl(WebRtc_Word16 *signal_out16,
+ ISACFIX_DecInst_t *ISACdec_obj,
+ WebRtc_Word16 *current_framesamples);
+
+WebRtc_Word16 WebRtcIsacfix_DecodePlcImpl(WebRtc_Word16 *decoded,
+ ISACFIX_DecInst_t *ISACdec_obj,
+ WebRtc_Word16 *current_framesample );
+
+int WebRtcIsacfix_EncodeImpl(WebRtc_Word16 *in,
+ ISACFIX_EncInst_t *ISACenc_obj,
+ BwEstimatorstr *bw_estimatordata,
+ WebRtc_Word16 CodingMode);
+
+int WebRtcIsacfix_EncodeStoredData(ISACFIX_EncInst_t *ISACenc_obj,
+ int BWnumber,
+ float scale);
+
+/* initialization functions */
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc *maskdata);
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec *maskdata);
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr *prefiltdata);
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr *postfiltdata);
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr *pitchfiltdata);
+
+void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct *State);
+
+void WebRtcIsacfix_InitPlc( PLCstr *State );
+
+
+/* transform functions */
+
+void WebRtcIsacfix_InitTransform();
+
+
+void WebRtcIsacfix_Time2Spec(WebRtc_Word16 *inre1Q9,
+ WebRtc_Word16 *inre2Q9,
+ WebRtc_Word16 *outre,
+ WebRtc_Word16 *outim);
+
+
+
+void WebRtcIsacfix_Spec2Time(WebRtc_Word16 *inreQ7,
+ WebRtc_Word16 *inimQ7,
+ WebRtc_Word32 *outre1Q16,
+ WebRtc_Word32 *outre2Q16);
+
+
+
+
+/* filterbank functions */
+
+void WebRtcIsacfix_SplitAndFilter1(WebRtc_Word16 *in,
+ WebRtc_Word16 *LP16,
+ WebRtc_Word16 *HP16,
+ PreFiltBankstr *prefiltdata);
+
+void WebRtcIsacfix_FilterAndCombine1(WebRtc_Word16 *tempin_ch1,
+ WebRtc_Word16 *tempin_ch2,
+ WebRtc_Word16 *out16,
+ PostFiltBankstr *postfiltdata);
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+
+void WebRtcIsacfix_SplitAndFilter2(WebRtc_Word16 *in,
+ WebRtc_Word16 *LP16,
+ WebRtc_Word16 *HP16,
+ PreFiltBankstr *prefiltdata);
+
+void WebRtcIsacfix_FilterAndCombine2(WebRtc_Word16 *tempin_ch1,
+ WebRtc_Word16 *tempin_ch2,
+ WebRtc_Word16 *out16,
+ PostFiltBankstr *postfiltdata,
+ WebRtc_Word16 len);
+
+#endif
+
+/* normalized lattice filters */
+
+void WebRtcIsacfix_NormLatticeFilterMa(WebRtc_Word16 orderCoef,
+ WebRtc_Word32 *stateGQ15,
+ WebRtc_Word16 *lat_inQ0,
+ WebRtc_Word16 *filt_coefQ15,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 lo_hi,
+ WebRtc_Word16 *lat_outQ9);
+
+void WebRtcIsacfix_NormLatticeFilterAr(WebRtc_Word16 orderCoef,
+ WebRtc_Word16 *stateGQ0,
+ WebRtc_Word32 *lat_inQ25,
+ WebRtc_Word16 *filt_coefQ15,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 lo_hi,
+ WebRtc_Word16 *lat_outQ0);
+
+/* TODO(kma): Remove the following functions into individual header files. */
+
+/* Internal functions in both C and ARM Neon versions */
+
+int WebRtcIsacfix_AutocorrC(WebRtc_Word32* __restrict r,
+ const WebRtc_Word16* __restrict x,
+ WebRtc_Word16 N,
+ WebRtc_Word16 order,
+ WebRtc_Word16* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int WebRtcIsacfix_AutocorrNeon(WebRtc_Word32* __restrict r,
+ const WebRtc_Word16* __restrict x,
+ WebRtc_Word16 N,
+ WebRtc_Word16 order,
+ WebRtc_Word16* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+#endif
+
+/* Function pointers associated with the above functions. */
+
+typedef int (*AutocorrFix)(WebRtc_Word32* __restrict r,
+ const WebRtc_Word16* __restrict x,
+ WebRtc_Word16 N,
+ WebRtc_Word16 order,
+ WebRtc_Word16* __restrict scale);
+extern AutocorrFix WebRtcIsacfix_AutocorrFix;
+
+typedef void (*FilterMaLoopFix)(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+extern FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/decode.c b/src/modules/audio_coding/codecs/isac/fix/source/decode.c
new file mode 100644
index 0000000..2e15e7a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/decode.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.
+ */
+
+/*
+ * decode.c
+ *
+ * This C file contains the internal decoding function.
+ *
+ */
+
+#include <string.h>
+
+#include "bandwidth_estimator.h"
+#include "codec.h"
+#include "entropy_coding.h"
+#include "pitch_estimator.h"
+#include "settings.h"
+#include "structs.h"
+
+
+
+
+WebRtc_Word16 WebRtcIsacfix_DecodeImpl(WebRtc_Word16 *signal_out16,
+ ISACFIX_DecInst_t *ISACdec_obj,
+ WebRtc_Word16 *current_framesamples)
+{
+ int k;
+ int err;
+ WebRtc_Word16 BWno;
+ WebRtc_Word16 len = 0;
+
+ WebRtc_Word16 model;
+
+
+ WebRtc_Word16 Vector_Word16_1[FRAMESAMPLES/2];
+ WebRtc_Word16 Vector_Word16_2[FRAMESAMPLES/2];
+
+ WebRtc_Word32 Vector_Word32_1[FRAMESAMPLES/2];
+ WebRtc_Word32 Vector_Word32_2[FRAMESAMPLES/2];
+
+ WebRtc_Word16 lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+ WebRtc_Word16 hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+ WebRtc_Word32 gain_lo_hiQ17[2*SUBFRAMES];
+
+ WebRtc_Word16 PitchLags_Q7[PITCH_SUBFRAMES];
+ WebRtc_Word16 PitchGains_Q12[PITCH_SUBFRAMES];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ WebRtc_Word16 tmp_1, tmp_2;
+ WebRtc_Word32 tmp32a, tmp32b;
+ WebRtc_Word16 gainQ13;
+
+
+ WebRtc_Word16 frame_nb; /* counter */
+ WebRtc_Word16 frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */
+ WebRtc_Word16 processed_samples;
+
+ /* PLC */
+ WebRtc_Word16 overlapWin[ 240 ];
+
+ (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
+ (ISACdec_obj->bitstr_obj).streamval = 0;
+ (ISACdec_obj->bitstr_obj).stream_index = 0;
+ (ISACdec_obj->bitstr_obj).full = 1;
+
+
+ /* decode framelength and BW estimation - not used, only for stream pointer*/
+ err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples);
+ if (err<0) // error check
+ return err;
+
+ frame_mode = (WebRtc_Word16)WEBRTC_SPL_DIV(*current_framesamples, MAX_FRAMESAMPLES); /* 0, or 1 */
+ processed_samples = (WebRtc_Word16)WEBRTC_SPL_DIV(*current_framesamples, frame_mode+1); /* either 320 (20ms) or 480 (30, 60 ms) */
+
+ err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno);
+ if (err<0) // error check
+ return err;
+
+ /* one loop if it's one frame (20 or 30ms), 2 loops if 2 frames bundled together (60ms) */
+ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+
+ /* decode & dequantize pitch parameters */
+ err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12);
+ if (err<0) // error check
+ return err;
+
+ err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7);
+ if (err<0) // error check
+ return err;
+
+ AvgPitchGain_Q12 = (WebRtc_Word16)(((WebRtc_Word32)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2);
+
+ /* decode & dequantize FiltCoef */
+ err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+ &ISACdec_obj->bitstr_obj, &model);
+
+ if (err<0) // error check
+ return err;
+
+ /* decode & dequantize spectrum */
+ len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12);
+ if (len < 0) // error check
+ return len;
+
+ // Why does this need Q16 in and out? /JS
+ WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2);
+
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ Vector_Word16_1[k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(Vector_Word32_1[k]+64, 7); //Q16 -> Q9
+ }
+
+ /* ---- If this is recovery frame ---- */
+ if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED )
+ {
+ (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED;
+ if( (ISACdec_obj->plcstr_obj).B < 1000 )
+ {
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000;
+ }
+
+ ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */
+ ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */
+ ISACdec_obj->plcstr_obj.pitchCycles = 0;
+
+ PitchGains_Q12[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[0], 700, 10 );
+
+ /* ---- Add-overlap ---- */
+ WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP );
+ for( k = 0; k < RECOVERY_OVERLAP; k++ )
+ Vector_Word16_1[k] = WEBRTC_SPL_ADD_SAT_W16(
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( (ISACdec_obj->plcstr_obj).overlapLP[k], overlapWin[RECOVERY_OVERLAP - k - 1], 14),
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( Vector_Word16_1[k], overlapWin[k], 14) );
+
+
+
+ }
+
+ /* --- Store side info --- */
+ if( frame_nb == frame_mode )
+ {
+ /* --- LPC info */
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO );
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI );
+ (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2];
+ (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1];
+
+ /* --- LTP info */
+ (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3];
+ (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3];
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3];
+
+ if( PitchLags_Q7[3] < 3000 )
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3];
+
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 );
+
+ }
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* inverse pitch filter */
+ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4);
+
+ if( frame_nb == frame_mode )
+ {
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG );
+ }
+
+
+ /* reduce gain to compensate for pitch enhancer */
+ /* gain = 1.0f - 0.45f * AvgPitchGain; */
+ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(AvgPitchGain_Q12, 29, 0); // Q18
+ tmp32b = 262144 - tmp32a; // Q18
+ gainQ13 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q13
+
+ for (k = 0; k < FRAMESAMPLES/2; k++)
+ {
+ Vector_Word32_1[k] = (WebRtc_Word32) WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(Vector_Word16_2[k], gainQ13), 3); // Q25
+ }
+
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+ Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+ /* --- Store Highpass Residual --- */
+ for (k = 0; k < FRAMESAMPLES/2; k++)
+ Vector_Word32_1[k] = WEBRTC_SPL_LSHIFT_W32(Vector_Word32_2[k], 9); // Q16 -> Q25
+
+ for( k = 0; k < PITCH_MAX_LAG + 10; k++ )
+ (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k];
+
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+ Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+ /* recombine the 2 bands */
+
+ /* Form the polyphase signals, and compensate for DC offset */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tmp_1 = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(((WebRtc_Word32)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/
+ tmp_2 = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(((WebRtc_Word32)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/
+ Vector_Word16_1[k] = tmp_1;
+ Vector_Word16_2[k] = tmp_2;
+ }
+
+ WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1, Vector_Word16_2, signal_out16 + frame_nb * processed_samples, &ISACdec_obj->postfiltbankstr_obj);
+
+ }
+ return len;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c b/src/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
new file mode 100644
index 0000000..68c6003
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_bwe.c
+ *
+ * This C file contains the internal decode bandwidth estimate function.
+ *
+ */
+
+
+#include "bandwidth_estimator.h"
+#include "codec.h"
+#include "entropy_coding.h"
+#include "structs.h"
+
+
+
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr *bwest_str,
+ Bitstr_dec *streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts)
+{
+ WebRtc_Word16 index;
+ WebRtc_Word16 frame_samples;
+ int err;
+
+ /* decode framelength */
+ err = WebRtcIsacfix_DecodeFrameLen(streamdata, &frame_samples);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* decode BW estimation */
+ err = WebRtcIsacfix_DecodeSendBandwidth(streamdata, &index);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* Update BWE with received data */
+ err = WebRtcIsacfix_UpdateUplinkBwImpl(
+ bwest_str,
+ rtp_seq_number,
+ (WebRtc_UWord16)WEBRTC_SPL_UDIV(WEBRTC_SPL_UMUL(frame_samples,1000), FS),
+ send_ts,
+ arr_ts,
+ (WebRtc_Word16) packet_size, /* in bytes */
+ index);
+
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* Succesful */
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/decode_plc.c b/src/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
new file mode 100644
index 0000000..de51658
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_plc.c
+ *
+ * Packet Loss Concealment.
+ *
+ */
+
+#include <string.h>
+
+#include "settings.h"
+#include "entropy_coding.h"
+#include "pitch_estimator.h"
+#include "bandwidth_estimator.h"
+#include "structs.h"
+#include "codec.h"
+
+
+#define NO_OF_PRIMES 8
+#define NOISE_FILTER_LEN 30
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+
+static WebRtc_Word16 plc_filterma_Fast(
+ WebRtc_Word16 *In, /* (i) Vector to be filtered. InOut[-orderCoef+1]
+ to InOut[-1] contains state */
+ WebRtc_Word16 *Out, /* (o) Filtered vector */
+ WebRtc_Word16 *B, /* (i) The filter coefficients (in Q0) */
+ WebRtc_Word16 Blen, /* (i) Number of B coefficients */
+ WebRtc_Word16 len, /* (i) Number of samples to be filtered */
+ WebRtc_Word16 reduceDecay,
+ WebRtc_Word16 decay,
+ WebRtc_Word16 rshift )
+{
+ int i, j;
+ WebRtc_Word32 o;
+ WebRtc_Word32 lim;
+
+ lim = WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 15 + rshift )-1;
+
+ for (i = 0; i < len; i++)
+ {
+ G_CONST WebRtc_Word16 *b_ptr = &B[0];
+ G_CONST WebRtc_Word16 *x_ptr = &In[i];
+
+ o = (WebRtc_Word32)0;
+
+ for (j = 0;j < Blen; j++)
+ {
+ o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_MUL_16_16( *b_ptr, *x_ptr) );
+ b_ptr++;
+ x_ptr--;
+ }
+
+ /* to round off correctly */
+ o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_LSHIFT_W32( 1, (rshift-1) ) );
+
+ /* saturate according to the domain of the filter coefficients */
+ o = WEBRTC_SPL_SAT((WebRtc_Word32)lim, o, (WebRtc_Word32)-lim);
+
+ /* o should be in the range of WebRtc_Word16 */
+ o = WEBRTC_SPL_RSHIFT_W32( o, rshift );
+
+ /* decay the output signal; this is specific to plc */
+ *Out++ = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16)o, decay, 15); // ((o + (WebRtc_Word32)2048) >> 12);
+
+ /* change the decay */
+ decay -= reduceDecay;
+ if( decay < 0 )
+ decay = 0;
+ }
+ return( decay );
+}
+
+
+
+
+
+
+
+
+static __inline WebRtc_Word32 log2_Q8_T( WebRtc_UWord32 x ) {
+
+ WebRtc_Word32 zeros, lg2;
+ WebRtc_Word16 frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
+ /* log2(magn(i)) */
+
+ lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
+ return lg2;
+
+}
+
+static __inline WebRtc_Word16 exp2_Q10_T(WebRtc_Word16 x) { // Both in and out in Q10
+
+ WebRtc_Word16 tmp16_1, tmp16_2;
+
+ tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
+ tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
+ if(tmp16_1>0)
+ return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
+ else
+ return (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
+
+}
+
+
+/*
+ This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
+ hard-coded. The values 700 and 5000 were experimentally obtained.
+
+ The function implements membership values for two sets. The mebership functions are
+ of second orders corresponding to half-bell-shapped pulses.
+*/
+static void MemshipValQ15( WebRtc_Word16 in, WebRtc_Word16 *A, WebRtc_Word16 *B )
+{
+ WebRtc_Word16 x;
+
+ in -= 700; /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
+
+ if( in <= 2150 )
+ {
+ if( in > 0 )
+ {
+ /* b = in^2 / (2 * M^2), a = 1 - b in Q0.
+ We have to compute in Q15 */
+
+ /* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
+ x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999 */
+
+ /* we are sure that x is in the range of WebRtc_Word16 */
+ x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
+ WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
+ /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+ be in correct domain and one more for the division by 2 */
+ *B = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
+ *A = WEBRTC_SPL_WORD16_MAX - *B;
+ }
+ else
+ {
+ *B = 0;
+ *A = WEBRTC_SPL_WORD16_MAX;
+ }
+ }
+ else
+ {
+ if( in < 4300 )
+ {
+ /* This is a mirror case of the above */
+ in = 4300 - in;
+ x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
+ WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
+ /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+ be in correct domain and one more for the division by 2 */
+ *A = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
+ *B = WEBRTC_SPL_WORD16_MAX - *A;
+
+ }
+ else
+ {
+ *A = 0;
+ *B = WEBRTC_SPL_WORD16_MAX;
+ }
+ }
+}
+
+
+
+
+static void LinearResampler( WebRtc_Word16 *in, WebRtc_Word16 *out, WebRtc_Word16 lenIn, WebRtc_Word16 lenOut )
+{
+ WebRtc_Word32 n;
+ WebRtc_Word16 resOut, i, j, relativePos, diff; /* */
+ WebRtc_UWord16 udiff;
+
+ if( lenIn == lenOut )
+ {
+ WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
+ return;
+ }
+
+ n = WEBRTC_SPL_MUL_16_16( (WebRtc_Word16)(lenIn-1), RESAMP_RES );
+ resOut = WebRtcSpl_DivW32W16ResW16( n, (WebRtc_Word16)(lenOut-1) );
+
+ out[0] = in[0];
+ for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
+ {
+
+ relativePos += resOut;
+ while( relativePos > RESAMP_RES )
+ {
+ j++;
+ relativePos -= RESAMP_RES;
+ }
+
+
+ /* an overflow may happen and the differce in sample values may
+ * require more than 16 bits. We like to avoid 32 bit arithmatic
+ * as much as possible */
+
+ if( (in[ j ] > 0) && (in[j + 1] < 0) )
+ {
+ udiff = (WebRtc_UWord16)(in[ j ] - in[j + 1]);
+ out[ i ] = in[ j ] - (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
+ }
+ else
+ {
+ if( (in[j] < 0) && (in[j+1] > 0) )
+ {
+ udiff = (WebRtc_UWord16)( in[j + 1] - in[ j ] );
+ out[ i ] = in[ j ] + (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
+ }
+ else
+ {
+ diff = in[ j + 1 ] - in[ j ];
+ out[ i ] = in[ j ] + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( diff, relativePos, RESAMP_RES_BIT );
+ }
+ }
+ }
+}
+
+
+
+
+
+WebRtc_Word16 WebRtcIsacfix_DecodePlcImpl(WebRtc_Word16 *signal_out16,
+ ISACFIX_DecInst_t *ISACdec_obj,
+ WebRtc_Word16 *current_framesamples )
+{
+ int subframecnt;
+ WebRtc_Word16 len = 0;
+
+ WebRtc_Word16* Vector_Word16_1;
+ WebRtc_Word16 Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+ WebRtc_Word16* Vector_Word16_2;
+ WebRtc_Word16 Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+
+ WebRtc_Word32 Vector_Word32_1[FRAMESAMPLES_HALF];
+ WebRtc_Word32 Vector_Word32_2[FRAMESAMPLES_HALF];
+
+ WebRtc_Word16 lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+ WebRtc_Word16 hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+
+ WebRtc_Word16 pitchLags_Q7[PITCH_SUBFRAMES];
+ WebRtc_Word16 pitchGains_Q12[PITCH_SUBFRAMES];
+
+ WebRtc_Word16 tmp_1, tmp_2;
+ WebRtc_Word32 tmp32a, tmp32b;
+ WebRtc_Word16 gainQ13;
+
+ WebRtc_Word16 myDecayRate;
+
+ /* ---------- PLC variables ------------ */
+ WebRtc_Word16 lag0, i, k, noiseIndex;
+ WebRtc_Word16 stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
+
+ WebRtc_Word32 gain_lo_hiQ17[2*SUBFRAMES];
+
+ WebRtc_Word16 nLP, pLP, wNoisyLP, wPriodicLP, tmp16, minIdx;
+ WebRtc_Word32 nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
+ WebRtc_Word16 noise1, rshift;
+
+
+ WebRtc_Word16 ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
+ WebRtc_Word32 varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
+ int rightShiftIn, rightShiftOut;
+
+
+ /* ------------------------------------- */
+
+
+ myDecayRate = (DECAY_RATE);
+ Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
+ Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
+
+
+ /* ----- Simply Copy Previous LPC parameters ------ */
+ for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
+ {
+ /* lower Band */
+ WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
+ (ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
+ gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
+
+ /* Upper Band */
+ WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
+ (ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
+ gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
+ }
+
+
+
+
+ lag0 = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 + 64, 7 ) + 1;
+
+
+ if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
+ {
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+
+ (ISACdec_obj->plcstr_obj).lastPitchLP =
+ &((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
+ minCorr = WEBRTC_SPL_WORD32_MAX;
+
+ if ( (FRAMESAMPLES_HALF - 2*lag0 - 10) > 0 )
+ {
+ minIdx = 11;
+ for( i = 0; i < 21; i++ )
+ {
+ corr = 0;
+ for( k = 0; k < lag0; k++ )
+ {
+ corr = WEBRTC_SPL_ADD_SAT_W32( corr, WEBRTC_SPL_ABS_W32(
+ WEBRTC_SPL_SUB_SAT_W16(
+ (ISACdec_obj->plcstr_obj).lastPitchLP[k],
+ (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+ FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
+ }
+ if( corr < minCorr )
+ {
+ minCorr = corr;
+ minIdx = i;
+ }
+ }
+ (ISACdec_obj->plcstr_obj).prevPitchLP =
+ &( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+ FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).prevPitchLP =
+ (ISACdec_obj->plcstr_obj).lastPitchLP;
+ }
+ pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
+
+ WebRtcSpl_AutoCorrelation(
+ &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
+ lag0, 0, &varIn, &rightShiftIn);
+ WebRtcSpl_AutoCorrelation(
+ &(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
+ lag0, 0, &varOut, &rightShiftOut);
+
+ maxAbs = 0;
+ for( i = 0; i< lag0; i++)
+ {
+ myAbs = WEBRTC_SPL_ABS_W16(
+ (ISACdec_obj->plcstr_obj).prevPitchInvOut[
+ PITCH_MAX_LAG + 10 - lag0 + i] );
+ maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
+ }
+ logVarIn = log2_Q8_T( (WebRtc_UWord32)( varIn ) ) +
+ (WebRtc_Word32)(rightShiftIn << 8);
+ logVarOut = log2_Q8_T( (WebRtc_UWord32)( varOut ) ) +
+ (WebRtc_Word32)(rightShiftOut << 8);
+ logMaxAbs = log2_Q8_T( (WebRtc_UWord32)( maxAbs ) );
+
+ ltpGain = (WebRtc_Word16)(logVarOut - logVarIn);
+ Q = 2 * logMaxAbs - ( logVarOut - 1512 );
+
+ /*
+ * ---
+ * We are computing sqrt( (VarIn/lag0) / var( noise ) )
+ * var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
+ * so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) ) ).
+ * Note that put log function is in Q8 but the exponential function is in Q10.
+ * --
+ */
+
+ logVarIn -= log2_Q8_T( (WebRtc_UWord32)( lag0 ) );
+ tmp16 = (WebRtc_Word16)((logVarIn<<1) - (4<<10) );
+ rightShiftIn = 0;
+ if( tmp16 > 4096 )
+ {
+ tmp16 -= 4096;
+ tmp16 = exp2_Q10_T( tmp16 );
+ tmp16 >>= 6;
+ }
+ else
+ tmp16 = exp2_Q10_T( tmp16 )>>10;
+
+ (ISACdec_obj->plcstr_obj).std = tmp16 - 4;
+
+ if( (ltpGain < 110) || (ltpGain > 230) )
+ {
+ if( ltpGain < 100 && (pitchGain < 1800) )
+ {
+ (ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
+ )? WEBRTC_SPL_WORD16_MAX:0;
+ }
+ (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+ (ISACdec_obj->plcstr_obj).A;
+ }
+ else
+ {
+ if( (pitchGain < 450) || (pitchGain > 1600) )
+ {
+ (ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
+ )? WEBRTC_SPL_WORD16_MAX:0;
+ (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+ (ISACdec_obj->plcstr_obj).A;
+ }
+ else
+ {
+ myVoiceIndicator = ltpGain * 2 + pitchGain;
+ MemshipValQ15( myVoiceIndicator,
+ &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+ }
+ }
+
+
+
+ myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
+ MemshipValQ15( myVoiceIndicator,
+ &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+
+
+
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+
+ }
+ else
+ {
+ myDecayRate = (DECAY_RATE<<2);
+ }
+
+ if( (ISACdec_obj->plcstr_obj).B < 1000 )
+ {
+ myDecayRate += (DECAY_RATE<<3);
+ }
+
+ /* ------------ reconstructing the residual signal ------------------ */
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+ /* inverse pitch filter */
+
+ pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
+ ((ISACdec_obj->plcstr_obj).stretchLag<<7);
+ pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
+ pitchGains_Q12[2] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ pitchGains_Q12[3], 1010, 10 );
+ pitchGains_Q12[1] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ pitchGains_Q12[2], 1010, 10 );
+ pitchGains_Q12[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ pitchGains_Q12[1], 1010, 10 );
+
+
+ /* most of the time either B or A are zero so seperating */
+ if( (ISACdec_obj->plcstr_obj).B == 0 )
+ {
+ for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+ {
+ /* --- Low Pass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_1[i] = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
+
+ /* --- Highpass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_2[i] = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
+
+ }
+ for( i = 1; i < NOISE_FILTER_LEN; i++ )
+ {
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_Extended_1[ i ] = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
+
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_Extended_2[ i ] = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
+ }
+ plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
+ &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
+ NOISE_FILTER_LEN], (WebRtc_Word16) NOISE_FILTER_LEN,
+ (WebRtc_Word16) FRAMESAMPLES_HALF, (WebRtc_Word16)(5),
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise, (WebRtc_Word16)(6));
+
+ maxCoeff = WebRtcSpl_MaxAbsValueW32(
+ &(ISACdec_obj->plcstr_obj).prevHP[
+ PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
+
+ rshift = 0;
+ while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
+ {
+ maxCoeff = WEBRTC_SPL_RSHIFT_W32(maxCoeff, 1);
+ rshift++;
+ }
+ for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
+ Vector_Word16_1[ FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =
+ (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (ISACdec_obj->plcstr_obj).prevHP[
+ PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN + i], rshift);
+ }
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
+ Vector_Word16_2,
+ Vector_Word16_Extended_2,
+ &Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
+ (WebRtc_Word16) NOISE_FILTER_LEN,
+ (WebRtc_Word16) FRAMESAMPLES_HALF,
+ (WebRtc_Word16) (5),
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+ (WebRtc_Word16) (7) );
+
+ for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+ Vector_Word32_2[i] = WEBRTC_SPL_LSHIFT_W32(
+ (WebRtc_Word32)Vector_Word16_Extended_2[i], rshift );
+
+ Vector_Word16_1 = Vector_Word16_Extended_1;
+ }
+ else
+ {
+ if( (ISACdec_obj->plcstr_obj).A == 0 )
+ {
+ /* ------ Periodic Vector --- */
+ for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+ {
+ /* --- Lowpass */
+ pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
+
+ /* --- Highpass */
+ pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+ (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+ (ISACdec_obj->plcstr_obj).stretchLag +
+ (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+
+ (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+ if( (ISACdec_obj->plcstr_obj).pitchIndex ==
+ (ISACdec_obj->plcstr_obj).stretchLag )
+ {
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+ (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+ if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+ {
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+ }
+
+ (ISACdec_obj->plcstr_obj).stretchLag = (
+ (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+ )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
+ stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ switch( (ISACdec_obj->plcstr_obj).pitchCycles )
+ {
+ case 1:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)((
+ (WebRtc_Word32)stretchPitchLP[k]* 3 +
+ (WebRtc_Word32)stretchPitchLP1[k])>>2);
+ }
+ break;
+ }
+ case 2:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)((
+ (WebRtc_Word32)stretchPitchLP[k] +
+ (WebRtc_Word32)stretchPitchLP1[k] )>>1);
+ }
+ break;
+ }
+ case 3:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)((stretchPitchLP[k] +
+ (WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
+ }
+ break;
+ }
+ }
+
+ if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+ {
+ myDecayRate += 35; //(myDecayRate>>1);
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+ }
+
+ }
+
+ /* ------ Sum the noisy and periodic signals ------ */
+ Vector_Word16_1[i] = pLP;
+ Vector_Word32_2[i] = pHP;
+ }
+ }
+ else
+ {
+ for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+ {
+
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+
+ noise1 = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
+
+ nLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ (WebRtc_Word16)((noise1)*(ISACdec_obj->plcstr_obj).std),
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise, 15 );
+
+ /* --- Highpass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ noise1 = WEBRTC_SPL_RSHIFT_W16(
+ (ISACdec_obj->plcstr_obj).seed, 11 ) - 8;
+
+ nHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+ (WebRtc_Word32)(noise1*(ISACdec_obj->plcstr_obj).std) );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
+
+ /* ------ Periodic Vector --- */
+ /* --- Lowpass */
+ pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
+
+ /* --- Highpass */
+ pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+ (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+ (ISACdec_obj->plcstr_obj).stretchLag +
+ (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+ {
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+ }
+
+ /* ------ Weighting the noisy and periodic vectors ------- */
+ wNoisyLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
+ (ISACdec_obj->plcstr_obj).A, nLP, 15 ) );
+ wNoisyHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).A, (nHP) ) );
+
+ wPriodicLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
+ (ISACdec_obj->plcstr_obj).B, pLP, 15));
+ wPriodicHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).B, pHP));
+
+ (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+ if((ISACdec_obj->plcstr_obj).pitchIndex ==
+ (ISACdec_obj->plcstr_obj).stretchLag)
+ {
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+ (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+ if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+ else
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+
+ (ISACdec_obj->plcstr_obj).stretchLag = (
+ (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+ )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+ LinearResampler(
+ (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
+ stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ switch((ISACdec_obj->plcstr_obj).pitchCycles)
+ {
+ case 1:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)((
+ (WebRtc_Word32)stretchPitchLP[k]* 3 +
+ (WebRtc_Word32)stretchPitchLP1[k] )>>2);
+ }
+ break;
+ }
+ case 2:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)((
+ (WebRtc_Word32)stretchPitchLP[k] +
+ (WebRtc_Word32)stretchPitchLP1[k])>>1);
+ }
+ break;
+ }
+ case 3:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (WebRtc_Word16)(
+ (stretchPitchLP[k] +
+ (WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
+ }
+ break;
+ }
+ }
+
+ if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+ {
+ myDecayRate += 55; //(myDecayRate>>1);
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+ }
+ }
+
+ /* ------ Sum the noisy and periodic signals ------ */
+ Vector_Word16_1[i] = (WebRtc_Word16)WEBRTC_SPL_ADD_SAT_W16(
+ wNoisyLP, wPriodicLP );
+ Vector_Word32_2[i] = (WebRtc_Word32)WEBRTC_SPL_ADD_SAT_W32(
+ wNoisyHP, wPriodicHP );
+ }
+ }
+ }
+ /* ----------------- residual signal is reconstructed ------------------ */
+
+ k = (ISACdec_obj->plcstr_obj).pitchIndex;
+ /* --- Write one pitch cycle for recovery block --- */
+
+ for( i = 0; i < RECOVERY_OVERLAP; i++ )
+ {
+ (ISACdec_obj->plcstr_obj).overlapLP[i] = (WebRtc_Word16)(
+ WEBRTC_SPL_MUL_16_16_RSFT(stretchPitchLP[k],
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15) );
+ k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
+ }
+
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = (ISACdec_obj->plcstr_obj).stretchLag << 7;
+
+
+ /* --- Inverse Pitch Filter --- */
+ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
+ &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
+
+ /* reduce gain to compensate for pitch enhancer */
+ /* gain = 1.0f - 0.45f * AvgPitchGain; */
+ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT((ISACdec_obj->plcstr_obj).AvgPitchGain_Q12,
+ 29, 0); // Q18
+ tmp32b = 262144 - tmp32a; // Q18
+ gainQ13 = (WebRtc_Word16) (tmp32b >> 5); // Q13
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++)
+ Vector_Word32_1[k] = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16(
+ Vector_Word16_2[k], gainQ13) << 3; // Q25
+
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
+ (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+ Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
+ (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+ Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+ /* recombine the 2 bands */
+
+ /* Form the polyphase signals, and compensate for DC offset */
+ for (k=0;k<FRAMESAMPLES_HALF;k++)
+ {
+ /* Construct a new upper channel signal*/
+ tmp_1 = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(
+ ((WebRtc_Word32)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
+ /* Construct a new lower channel signal*/
+ tmp_2 = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(
+ ((WebRtc_Word32)Vector_Word16_1[k]-Vector_Word16_2[k]));
+ Vector_Word16_1[k] = tmp_1;
+ Vector_Word16_2[k] = tmp_2;
+ }
+
+
+ WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
+ Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
+
+ (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
+ *current_framesamples = 480;
+
+ return len;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/encode.c b/src/modules/audio_coding/codecs/isac/fix/source/encode.c
new file mode 100644
index 0000000..cb531e5
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/encode.c
@@ -0,0 +1,626 @@
+/*
+ * 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 "arith_routins.h"
+#include "bandwidth_estimator.h"
+#include "codec.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "entropy_coding.h"
+#include "lpc_tables.h"
+#include "lpc_masking_model.h"
+#include "pitch_estimator.h"
+#include "structs.h"
+#include <stdio.h>
+
+
+int WebRtcIsacfix_EncodeImpl(WebRtc_Word16 *in,
+ ISACFIX_EncInst_t *ISACenc_obj,
+ BwEstimatorstr *bw_estimatordata,
+ WebRtc_Word16 CodingMode)
+{
+ WebRtc_Word16 stream_length = 0;
+ WebRtc_Word16 usefulstr_len = 0;
+ int k;
+ WebRtc_Word16 BWno;
+
+ WebRtc_Word16 lofilt_coefQ15[(ORDERLO)*SUBFRAMES];
+ WebRtc_Word16 hifilt_coefQ15[(ORDERHI)*SUBFRAMES];
+ WebRtc_Word32 gain_lo_hiQ17[2*SUBFRAMES];
+
+ WebRtc_Word16 LPandHP[FRAMESAMPLES/2 + QLOOKAHEAD];
+ WebRtc_Word16 LP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+ WebRtc_Word16 HP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+
+ WebRtc_Word16 PitchLags_Q7[PITCH_SUBFRAMES];
+ WebRtc_Word16 PitchGains_Q12[PITCH_SUBFRAMES];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ WebRtc_Word16 frame_mode; /* 0 for 30ms, 1 for 60ms */
+ WebRtc_Word16 processed_samples;
+ int status;
+
+ WebRtc_Word32 bits_gainsQ11;
+ WebRtc_Word16 MinBytes;
+ WebRtc_Word16 bmodel;
+
+ transcode_obj transcodingParam;
+ WebRtc_Word16 payloadLimitBytes;
+ WebRtc_Word16 arithLenBeforeEncodingDFT;
+ WebRtc_Word16 iterCntr;
+
+ /* copy new frame length and bottle neck rate only for the first 10 ms data */
+ if (ISACenc_obj->buffer_index == 0) {
+ /* set the framelength for the next packet */
+ ISACenc_obj->current_framesamples = ISACenc_obj->new_framelength;
+ }
+
+ frame_mode = ISACenc_obj->current_framesamples/MAX_FRAMESAMPLES; /* 0 (30 ms) or 1 (60 ms) */
+ processed_samples = ISACenc_obj->current_framesamples/(frame_mode+1); /* 480 (30, 60 ms) */
+
+ /* buffer speech samples (by 10ms packet) until the framelength is reached (30 or 60 ms) */
+ /**************************************************************************************/
+ /* fill the buffer with 10ms input data */
+ for(k=0; k<FRAMESAMPLES_10ms; k++) {
+ ISACenc_obj->data_buffer_fix[k + ISACenc_obj->buffer_index] = in[k];
+ }
+ /* if buffersize is not equal to current framesize, and end of file is not reached yet, */
+ /* increase index and go back to main to get more speech samples */
+ if (ISACenc_obj->buffer_index + FRAMESAMPLES_10ms != processed_samples) {
+ ISACenc_obj->buffer_index = ISACenc_obj->buffer_index + FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* if buffer reached the right size, reset index and continue with encoding the frame */
+ ISACenc_obj->buffer_index = 0;
+
+ /* end of buffer function */
+ /**************************/
+
+ /* encoding */
+ /************/
+
+ if (frame_mode == 0 || ISACenc_obj->frame_nb == 0 )
+ {
+ /* reset bitstream */
+ ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACenc_obj->bitstr_obj.streamval = 0;
+ ISACenc_obj->bitstr_obj.stream_index = 0;
+ ISACenc_obj->bitstr_obj.full = 1;
+
+ if (CodingMode == 0) {
+ ISACenc_obj->BottleNeck = WebRtcIsacfix_GetUplinkBandwidth(bw_estimatordata);
+ ISACenc_obj->MaxDelay = WebRtcIsacfix_GetUplinkMaxDelay(bw_estimatordata);
+ }
+ if (CodingMode == 0 && frame_mode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+ ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+ ISACenc_obj->current_framesamples);
+ }
+
+ // multiply the bottleneck by 0.88 before computing SNR, 0.88 is tuned by experimenting on TIMIT
+ // 901/1024 is 0.87988281250000
+ ISACenc_obj->s2nr = WebRtcIsacfix_GetSnr((WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ISACenc_obj->BottleNeck, 901, 10),
+ ISACenc_obj->current_framesamples);
+
+ /* encode frame length */
+ status = WebRtcIsacfix_EncodeFrameLen(ISACenc_obj->current_framesamples, &ISACenc_obj->bitstr_obj);
+ if (status < 0)
+ {
+ /* Wrong frame size */
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+
+ /* Save framelength for multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ (ISACenc_obj->SaveEnc_ptr)->framelength=ISACenc_obj->current_framesamples;
+ }
+
+ /* bandwidth estimation and coding */
+ BWno = WebRtcIsacfix_GetDownlinkBwIndexImpl(bw_estimatordata);
+ status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ }
+
+ /* split signal in two bands */
+ WebRtcIsacfix_SplitAndFilter1(ISACenc_obj->data_buffer_fix, LP16a, HP16a, &ISACenc_obj->prefiltbankstr_obj );
+
+ /* estimate pitch parameters and pitch-filter lookahead signal */
+ WebRtcIsacfix_PitchAnalysis(LP16a+QLOOKAHEAD, LPandHP,
+ &ISACenc_obj->pitchanalysisstr_obj, PitchLags_Q7, PitchGains_Q12); /* LPandHP = LP_lookahead_pfQ0, */
+
+ /* Set where to store data in multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ if (frame_mode == 0 || ISACenc_obj->frame_nb == 0)
+ {
+ (ISACenc_obj->SaveEnc_ptr)->startIdx = 0;
+ }
+ else
+ {
+ (ISACenc_obj->SaveEnc_ptr)->startIdx = 1;
+ }
+ }
+
+ /* quantize & encode pitch parameters */
+ status = WebRtcIsacfix_EncodePitchGain(PitchGains_Q12, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ status = WebRtcIsacfix_EncodePitchLag(PitchLags_Q7 , PitchGains_Q12, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ AvgPitchGain_Q12 = WEBRTC_SPL_RSHIFT_W32(PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3], 2);
+
+ /* find coefficients for perceptual pre-filters */
+ WebRtcIsacfix_GetLpcCoef(LPandHP, HP16a+QLOOKAHEAD, &ISACenc_obj->maskfiltstr_obj,
+ ISACenc_obj->s2nr, PitchGains_Q12,
+ gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15); /*LPandHP = LP_lookahead_pfQ0*/
+
+ // record LPC Gains for possible bit-rate reduction
+ for(k = 0; k < KLT_ORDER_GAIN; k++)
+ {
+ transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+ }
+
+ /* code LPC model and shape - gains not quantized yet */
+ status = WebRtcIsacfix_EncodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+ &bmodel, &bits_gainsQ11, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr, &transcodingParam);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+
+ /* low-band filtering */
+ WebRtcIsacfix_NormLatticeFilterMa(ORDERLO, ISACenc_obj->maskfiltstr_obj.PreStateLoGQ15,
+ LP16a, lofilt_coefQ15, gain_lo_hiQ17, 0, LPandHP);/* LPandHP = LP16b */
+
+ /* pitch filter */
+ WebRtcIsacfix_PitchFilter(LPandHP, LP16a, &ISACenc_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 1);/* LPandHP = LP16b */
+
+ /* high-band filtering */
+ WebRtcIsacfix_NormLatticeFilterMa(ORDERHI, ISACenc_obj->maskfiltstr_obj.PreStateHiGQ15,
+ HP16a, hifilt_coefQ15, gain_lo_hiQ17, 1, LPandHP);/*LPandHP = HP16b*/
+
+ /* transform */
+ WebRtcIsacfix_Time2Spec(LP16a, LPandHP, LP16a, LPandHP); /*LPandHP = HP16b*/
+
+ /* Save data for multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+ (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+ }
+ (ISACenc_obj->SaveEnc_ptr)->AvgPitchGain[(ISACenc_obj->SaveEnc_ptr)->startIdx] = AvgPitchGain_Q12;
+ }
+
+ /* quantization and lossless coding */
+ status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+ if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+
+ if((frame_mode == 1) && (ISACenc_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 = ISACenc_obj->payloadLimitBytes60 >> 1;
+ }
+ else if (frame_mode == 0)
+ {
+ // it is a 30ms frame
+ payloadLimitBytes = (ISACenc_obj->payloadLimitBytes30) - 3;
+ }
+ else
+ {
+ // this is the second half of a 60ms frame.
+ payloadLimitBytes = ISACenc_obj->payloadLimitBytes60 - 3; // subract 3 because termination process may add 3 bytes
+ }
+
+ iterCntr = 0;
+ while((((ISACenc_obj->bitstr_obj.stream_index) << 1) > payloadLimitBytes) ||
+ (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH))
+ {
+ WebRtc_Word16 arithLenDFTByte;
+ WebRtc_Word16 bytesLeftQ5;
+ WebRtc_Word16 ratioQ5[8] = {0, 6, 9, 12, 16, 19, 22, 25};
+
+ // According to experiments on TIMIT the following is proper for audio, but it is not agressive enough for tonal inputs
+ // such as DTMF, sweep-sine, ...
+ //
+ // (0.55 - (0.8 - ratio[i]/32) * 5 / 6) * 2^14
+ // WebRtc_Word16 scaleQ14[8] = {0, 648, 1928, 3208, 4915, 6195, 7475, 8755};
+
+
+ // This is a supper-agressive scaling passed the tests (tonal inputs) tone with one iteration for payload limit
+ // of 120 (32kbps bottleneck), number of frames needed a rate-reduction was 58403
+ //
+ WebRtc_Word16 scaleQ14[8] = {0, 348, 828, 1408, 2015, 3195, 3500, 3500};
+ WebRtc_Word16 idx;
+
+ if(iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION)
+ {
+ // We were not able to limit the payload size
+
+ if((frame_mode == 1) && (ISACenc_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 togetehr we won't exceed
+ // the limit.
+ ISACenc_obj->frame_nb = 1;
+ return 0;
+ }
+ else if((frame_mode == 1) && (ISACenc_obj->frame_nb == 1))
+ {
+ ISACenc_obj->frame_nb = 0;
+ }
+
+ if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+ {
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+ else
+ {
+ return status;
+ }
+ }
+ if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+ {
+ arithLenDFTByte = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full) - arithLenBeforeEncodingDFT;
+ bytesLeftQ5 = (payloadLimitBytes - arithLenBeforeEncodingDFT) << 5;
+
+ // bytesLeft / arithLenDFTBytes indicates how much scaling is required a rough estimate (agressive)
+ // scale = 0.55 - (0.8 - bytesLeft / arithLenDFTBytes) * 5 / 6
+ // bytesLeft / arithLenDFTBytes below 0.2 will have a scale of zero and above 0.8 are treated as 0.8
+ // to avoid division we do more simplification.
+ //
+ // values of (bytesLeft / arithLenDFTBytes)*32 between ratioQ5[i] and ratioQ5[i+1] are rounded to ratioQ5[i]
+ // and the corresponding scale is chosen
+
+ // we compare bytesLeftQ5 with ratioQ5[]*arithLenDFTByte;
+ idx = 4;
+ idx += (bytesLeftQ5 >= WEBRTC_SPL_MUL_16_16(ratioQ5[idx], arithLenDFTByte))? 2:-2;
+ idx += (bytesLeftQ5 >= WEBRTC_SPL_MUL_16_16(ratioQ5[idx], arithLenDFTByte))? 1:-1;
+ idx += (bytesLeftQ5 >= WEBRTC_SPL_MUL_16_16(ratioQ5[idx], arithLenDFTByte))? 0:-1;
+ }
+ else
+ {
+ // we are here because the bit-stream did not fit into the buffer, in this case, the stream_index is not
+ // trustable, especially if the is the first 30ms of a packet. Thereforem, we will go for the most agressive
+ // case.
+ idx = 0;
+ }
+ // scale FFT coefficients to reduce the bit-rate
+ for(k = 0; k < FRAMESAMPLES_HALF; k++)
+ {
+ LP16a[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(LP16a[k], scaleQ14[idx], 14);
+ LPandHP[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(LPandHP[k], scaleQ14[idx], 14);
+ }
+
+ // Save data for multiple packets memory
+ if (ISACenc_obj->SaveEnc_ptr != NULL)
+ {
+ for(k = 0; k < FRAMESAMPLES_HALF; k++)
+ {
+ (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+ (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+ }
+ }
+
+ // scale the unquantized LPC gains and save the scaled version for the future use
+ for(k = 0; k < KLT_ORDER_GAIN; k++)
+ {
+ gain_lo_hiQ17[k] = WEBRTC_SPL_MUL_16_32_RSFT14(scaleQ14[idx], transcodingParam.lpcGains[k]);//transcodingParam.lpcGains[k]; //
+ transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+ }
+
+ // reset the bit-stream object to the state which it had before encoding LPC Gains
+ ISACenc_obj->bitstr_obj.full = transcodingParam.full;
+ ISACenc_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+ ISACenc_obj->bitstr_obj.streamval = transcodingParam.streamval;
+ ISACenc_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+ ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index-1] = transcodingParam.beforeLastWord;
+ ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index] = transcodingParam.lastWord;
+
+
+ // quantize and encode LPC gain
+ WebRtcIsacfix_EstCodeLpcGain(gain_lo_hiQ17, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+ status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+ if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+ {
+ if (frame_mode == 1 && ISACenc_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.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ iterCntr++;
+ }
+
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 0)
+ /* i.e. 60 ms framesize and just processed the first 30ms, */
+ /* go back to main function to buffer the other 30ms speech frame */
+ {
+ ISACenc_obj->frame_nb = 1;
+ return 0;
+ }
+ else if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ ISACenc_obj->frame_nb = 0;
+ /* also update the framelength for next packet, in Adaptive mode only */
+ if (CodingMode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+ ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+ ISACenc_obj->current_framesamples);
+ }
+ }
+
+
+ /* complete arithmetic coding */
+ stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+ /* can this be negative? */
+
+ if(CodingMode == 0)
+ {
+
+ /* update rate model and get minimum number of bytes in this packet */
+ MinBytes = WebRtcIsacfix_GetMinBytes(&ISACenc_obj->rate_data_obj, (WebRtc_Word16) stream_length,
+ ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck, ISACenc_obj->MaxDelay);
+
+ /* if bitstream is too short, add garbage at the end */
+
+ /* Store length of coded data */
+ usefulstr_len = stream_length;
+
+ /* Make sure MinBytes does not exceed packet size limit */
+ if ((ISACenc_obj->frame_nb == 0) && (MinBytes > ISACenc_obj->payloadLimitBytes30)) {
+ MinBytes = ISACenc_obj->payloadLimitBytes30;
+ } else if ((ISACenc_obj->frame_nb == 1) && (MinBytes > ISACenc_obj->payloadLimitBytes60)) {
+ MinBytes = ISACenc_obj->payloadLimitBytes60;
+ }
+
+ /* 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 lenght we can signal using 8 bits. */
+ if( MinBytes > usefulstr_len + 255 ) {
+ MinBytes = usefulstr_len + 255;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ (ISACenc_obj->SaveEnc_ptr)->minBytes = MinBytes;
+ }
+
+ while (stream_length < MinBytes)
+ {
+ if (stream_length & 0x0001){
+ ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+ ISACenc_obj->bitstr_obj.stream[ WEBRTC_SPL_RSHIFT_W16(stream_length, 1) ] |= (WebRtc_UWord16)(ISACenc_obj->bitstr_seed & 0xFF);
+ } else {
+ ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+ ISACenc_obj->bitstr_obj.stream[ WEBRTC_SPL_RSHIFT_W16(stream_length, 1) ] = WEBRTC_SPL_LSHIFT_U16(ISACenc_obj->bitstr_seed, 8);
+ }
+ stream_length++;
+ }
+
+ /* to get the real stream_length, without garbage */
+ if (usefulstr_len & 0x0001) {
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0xFF00;
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] += (MinBytes - usefulstr_len) & 0x00FF;
+ }
+ else {
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0x00FF;
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] += WEBRTC_SPL_LSHIFT_U16((MinBytes - usefulstr_len) & 0x00FF, 8);
+ }
+ }
+ else
+ {
+ /* update rate model */
+ WebRtcIsacfix_UpdateRateModel(&ISACenc_obj->rate_data_obj, (WebRtc_Word16) stream_length,
+ ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck);
+ }
+ return stream_length;
+}
+
+/* This function is used to create a new bitstream with new BWE.
+ The same data as previously encoded with the fucntion WebRtcIsacfix_EncodeImpl()
+ is used. The data needed is taken from the struct, where it was stored
+ when calling the encoder. */
+int WebRtcIsacfix_EncodeStoredData(ISACFIX_EncInst_t *ISACenc_obj,
+ int BWnumber,
+ float scale)
+{
+ int ii;
+ int status;
+ WebRtc_Word16 BWno = BWnumber;
+ int stream_length = 0;
+
+ WebRtc_Word16 model;
+ const WebRtc_UWord16 *Q_PitchGain_cdf_ptr[1];
+ const WebRtc_UWord16 **cdf;
+ const ISAC_SaveEncData_t *SaveEnc_str;
+ WebRtc_Word32 tmpLPCcoeffs_g[KLT_ORDER_GAIN<<1];
+ WebRtc_Word16 tmpLPCindex_g[KLT_ORDER_GAIN<<1];
+ WebRtc_Word16 tmp_fre[FRAMESAMPLES];
+ WebRtc_Word16 tmp_fim[FRAMESAMPLES];
+
+ SaveEnc_str = ISACenc_obj->SaveEnc_ptr;
+
+ /* Check if SaveEnc memory exists */
+ if (SaveEnc_str == NULL) {
+ return (-1);
+ }
+
+ /* Sanity Check - possible values for BWnumber is 0 - 23 */
+ if ((BWnumber < 0) || (BWnumber > 23)) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* reset bitstream */
+ ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACenc_obj->bitstr_obj.streamval = 0;
+ ISACenc_obj->bitstr_obj.stream_index = 0;
+ ISACenc_obj->bitstr_obj.full = 1;
+
+ /* encode frame length */
+ status = WebRtcIsacfix_EncodeFrameLen(SaveEnc_str->framelength, &ISACenc_obj->bitstr_obj);
+ if (status < 0) {
+ /* Wrong frame size */
+ return status;
+ }
+
+ /* encode bandwidth estimate */
+ status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Transcoding */
+ /* If scale < 1, rescale data to produce lower bitrate signal */
+ if ((0.0 < scale) && (scale < 1.0)) {
+ /* Compensate LPC gain */
+ for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+ tmpLPCcoeffs_g[ii] = (WebRtc_Word32) ((scale) * (float) SaveEnc_str->LPCcoeffs_g[ii]);
+ }
+
+ /* Scale DFT */
+ for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+ tmp_fre[ii] = (WebRtc_Word16) ((scale) * (float) SaveEnc_str->fre[ii]) ;
+ tmp_fim[ii] = (WebRtc_Word16) ((scale) * (float) SaveEnc_str->fim[ii]) ;
+ }
+ } else {
+ for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+ tmpLPCindex_g[ii] = SaveEnc_str->LPCindex_g[ii];
+ }
+
+ for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+ tmp_fre[ii] = SaveEnc_str->fre[ii];
+ tmp_fim[ii] = SaveEnc_str->fim[ii];
+ }
+ }
+
+ /* Loop over number of 30 msec */
+ for (ii = 0; ii <= SaveEnc_str->startIdx; ii++)
+ {
+
+ /* encode pitch gains */
+ *Q_PitchGain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->pitchGain_index[ii],
+ Q_PitchGain_cdf_ptr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization pitch lags */
+ /* voicing classificiation */
+ if (SaveEnc_str->meanGain[ii] <= 819) {
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ } else if (SaveEnc_str->meanGain[ii] <= 1638) {
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ } else {
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ }
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj,
+ &SaveEnc_str->pitchIndex[PITCH_SUBFRAMES*ii], cdf, PITCH_SUBFRAMES);
+ if (status < 0) {
+ return status;
+ }
+
+ /* LPC */
+ /* entropy coding of model number */
+ model = 0;
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &model,
+ WebRtcIsacfix_kModelCdfPtr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization indices - LPC shape only */
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->LPCindex_s[KLT_ORDER_SHAPE*ii],
+ WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+ if (status < 0) {
+ return status;
+ }
+
+ /* If transcoding, get new LPC gain indices */
+ if (scale < 1.0) {
+ WebRtcIsacfix_TranscodeLpcCoef(&tmpLPCcoeffs_g[KLT_ORDER_GAIN*ii], &tmpLPCindex_g[KLT_ORDER_GAIN*ii]);
+ }
+
+ /* entropy coding of quantization indices - LPC gain */
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN*ii],
+ WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ /* quantization and lossless coding */
+ status = WebRtcIsacfix_EncodeSpec(&tmp_fre[ii*FRAMESAMPLES_HALF], &tmp_fim[ii*FRAMESAMPLES_HALF],
+ &ISACenc_obj->bitstr_obj, SaveEnc_str->AvgPitchGain[ii]);
+ if (status < 0) {
+ return status;
+ }
+ }
+
+ /* complete arithmetic coding */
+ stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+
+ return stream_length;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c b/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
new file mode 100644
index 0000000..0b64d83
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
@@ -0,0 +1,2072 @@
+/*
+ * 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.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This file contains all functions used to arithmetically
+ * encode the iSAC bistream.
+ *
+ */
+
+#include <stddef.h>
+
+#include "arith_routins.h"
+#include "spectrum_ar_model_tables.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "entropy_coding.h"
+#include "lpc_tables.h"
+#include "settings.h"
+#include "signal_processing_library.h"
+
+
+/*
+ This function implements the fix-point correspondant function to lrint.
+
+ FLP: (WebRtc_Word32)floor(flt+.499999999999)
+ FIP: (fixVal+roundVal)>>qDomain
+
+ where roundVal = 2^(qDomain-1) = 1<<(qDomain-1)
+
+*/
+static __inline WebRtc_Word32 CalcLrIntQ(WebRtc_Word32 fixVal, WebRtc_Word16 qDomain) {
+ WebRtc_Word32 intgr;
+ WebRtc_Word32 roundVal;
+
+ roundVal = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, qDomain-1);
+ intgr = WEBRTC_SPL_RSHIFT_W32(fixVal+roundVal, qDomain);
+
+ return intgr;
+}
+
+/*
+ __inline WebRtc_UWord32 stepwise(WebRtc_Word32 dinQ10) {
+
+ WebRtc_Word32 ind, diQ10, dtQ10;
+
+ diQ10 = dinQ10;
+ if (diQ10 < DPMIN_Q10)
+ diQ10 = DPMIN_Q10;
+ if (diQ10 >= DPMAX_Q10)
+ diQ10 = DPMAX_Q10 - 1;
+
+ dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */
+/* ind = (dtQ10 * 5) >> 10; */ /* 2^10 / 5 = 0.2 in Q10 */
+/* Q10 -> Q0 */
+
+/* return rpointsFIX_Q10[ind];
+
+ }
+*/
+
+/* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */
+/* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+static WebRtc_Word16 CalcLogN(WebRtc_Word32 arg) {
+ WebRtc_Word16 zeros, log2, frac, logN;
+
+ zeros=WebRtcSpl_NormU32(arg);
+ frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(WEBRTC_SPL_LSHIFT_W32(arg, zeros)&0x7FFFFFFF, 23);
+ log2=(WebRtc_Word16)(WEBRTC_SPL_LSHIFT_W32(31-zeros, 8)+frac); // log2(x) in Q8
+ logN=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(log2,22713,15); //Q8*Q15 log(2) = 0.693147 = 22713 in Q15
+ logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x.
+
+ return logN;
+}
+
+
+/*
+ expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695
+
+ Input: Q8 (WebRtc_Word16)
+ Output: Q17 (WebRtc_Word32)
+
+ a = log2(e) = log2(exp(1)) ~= 1.442695 ==> a = 23637 in Q14 (1.442688)
+ To this value, 700 is added or subtracted in order to get an average error
+ nearer zero, instead of always same-sign.
+*/
+
+static WebRtc_Word32 CalcExpN(WebRtc_Word16 x) {
+ WebRtc_Word16 ax, axINT, axFRAC;
+ WebRtc_Word16 exp16;
+ WebRtc_Word32 exp;
+
+ if (x>=0) {
+ // ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637-700, 14); //Q8
+ ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8
+ axINT = WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0
+ axFRAC = ax&0x00FF;
+ exp16 = WEBRTC_SPL_LSHIFT_W32(1, axINT); //Q0
+ axFRAC = axFRAC+256; //Q8
+ exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q0*Q8 = Q8
+ exp = WEBRTC_SPL_LSHIFT_W32(exp, 9); //Q17
+ } else {
+ // ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637+700, 14); //Q8
+ ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8
+ ax = -ax;
+ axINT = 1 + WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0
+ axFRAC = 0x00FF - (ax&0x00FF);
+ exp16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(32768, axINT); //Q15
+ axFRAC = axFRAC+256; //Q8
+ exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q15*Q8 = Q23
+ exp = WEBRTC_SPL_RSHIFT_W32(exp, 6); //Q17
+ }
+
+ return exp;
+}
+
+
+/* compute correlation from power spectrum */
+static void CalcCorrelation(WebRtc_Word32 *PSpecQ12, WebRtc_Word32 *CorrQ7)
+{
+ WebRtc_Word32 summ[FRAMESAMPLES/8];
+ WebRtc_Word32 diff[FRAMESAMPLES/8];
+ WebRtc_Word32 sum;
+ int k, n;
+
+ for (k = 0; k < FRAMESAMPLES/8; k++) {
+ summ[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] + PSpecQ12[FRAMESAMPLES/4-1 - k] + 16, 5);
+ diff[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] - PSpecQ12[FRAMESAMPLES/4-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;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], diff[n]) + 256, 9);
+ CorrQ7[k+1] = sum;
+ }
+
+ for (k=1; k<AR_ORDER; k+=2) {
+ sum = 0;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], summ[n]) + 256, 9);
+ CorrQ7[k+1] = sum;
+ }
+}
+
+
+/* compute inverse AR power spectrum */
+static void CalcInvArSpec(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); /* result in 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(WebRtcIsacfix_kCos[k][n], CorrQ11[k+1]) + 2, 2);
+ }
+
+ CS_ptrQ9 = WebRtcIsacfix_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 = WebRtcIsacfix_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/4-1 - k] = CurveQ16[k] - WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
+ CurveQ16[k] += WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
+ }
+}
+
+static void CalcRootInvArSpec(const WebRtc_Word16 *ARCoefQ12,
+ const WebRtc_Word32 gainQ10,
+ WebRtc_UWord16 *CurveQ8)
+{
+ WebRtc_Word32 CorrQ11[AR_ORDER+1];
+ WebRtc_Word32 sum, tmpGain;
+ WebRtc_Word32 summQ16[FRAMESAMPLES/8];
+ WebRtc_Word32 diffQ16[FRAMESAMPLES/8];
+
+ const WebRtc_Word16 *CS_ptrQ9;
+ int k, n, i;
+ WebRtc_Word16 round, shftVal = 0, sh;
+ WebRtc_Word32 res, in_sqrt, newRes;
+
+ 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); /* result in 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++)
+ summQ16[n] = sum;
+
+ for (k = 1; k < (AR_ORDER); k += 2) {
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ summQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(CorrQ11[k+1],WebRtcIsacfix_kCos[k][n]) + 2, 2);
+ }
+
+ CS_ptrQ9 = WebRtcIsacfix_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 = WebRtcIsacfix_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);
+ }
+
+ in_sqrt = summQ16[0] + WEBRTC_SPL_LSHIFT_W32(diffQ16[0], shftVal);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = WEBRTC_SPL_LSHIFT_W32(1, WEBRTC_SPL_RSHIFT_W16(WebRtcSpl_GetSizeInBits(in_sqrt), 1));
+
+ for (k = 0; k < FRAMESAMPLES/8; k++)
+ {
+ in_sqrt = summQ16[k] + WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
+ i = 10;
+
+ /* make in_sqrt positive to prohibit sqrt of negative values */
+ if(in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1);
+ do
+ {
+ res = newRes;
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1);
+ } while (newRes != res && i-- > 0);
+
+ CurveQ8[k] = (WebRtc_Word16)newRes;
+ }
+ for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) {
+
+ in_sqrt = summQ16[FRAMESAMPLES/4-1 - k] - WEBRTC_SPL_LSHIFT_W32(diffQ16[FRAMESAMPLES/4-1 - k], shftVal);
+ i = 10;
+
+ /* make in_sqrt positive to prohibit sqrt of negative values */
+ if(in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1);
+ do
+ {
+ res = newRes;
+ newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1);
+ } while (newRes != res && i-- > 0);
+
+ CurveQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+}
+
+
+
+/* generate array of dither samples in Q7 */
+static void GenerateDitherQ7(WebRtc_Word16 *bufQ7,
+ WebRtc_UWord32 seed,
+ WebRtc_Word16 length,
+ WebRtc_Word16 AvgPitchGain_Q12)
+{
+ int k;
+ WebRtc_Word16 dither1_Q7, dither2_Q7, dither_gain_Q14, shft;
+
+ if (AvgPitchGain_Q12 < 614) /* this threshold should be equal to that in decode_spec() */
+ {
+ for (k = 0; k < length-2; k += 3)
+ {
+ /* new random unsigned WebRtc_Word32 */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 (Q7) */
+ dither1_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)seed + 16777216, 25); // * 128/4294967295
+
+ /* new random unsigned WebRtc_Word32 */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither2_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(seed + 16777216, 25);
+
+ shft = (WebRtc_Word16)(WEBRTC_SPL_RSHIFT_U32(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 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12));
+
+ /* dither on half of the coefficients */
+ for (k = 0; k < length-1; k += 2)
+ {
+ /* new random unsigned WebRtc_Word32 */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither1_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)seed + 16777216, 25);
+
+ /* dither sample is placed in either even or odd index */
+ shft = (WebRtc_Word16)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1); /* either 0 or 1 */
+
+ bufQ7[k + shft] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(dither_gain_Q14, dither1_Q7) + 8192, 14);
+ bufQ7[k + 1 - shft] = 0;
+ }
+ }
+}
+
+
+
+
+/*
+ * function to decode the complex spectrum from the bitstream
+ * returns the total number of bytes in the stream
+ */
+WebRtc_Word16 WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
+ WebRtc_Word16 *frQ7,
+ WebRtc_Word16 *fiQ7,
+ WebRtc_Word16 AvgPitchGain_Q12)
+{
+ WebRtc_Word16 data[FRAMESAMPLES];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES/4];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 gainQ10;
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word16 len;
+ int k;
+
+ /* create dither signal */
+ GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */
+
+ /* decode model parameters */
+ if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* compute inverse AR power spectrum */
+ CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* arithmetic decoding of spectrum */
+ /* 'data' input and output. Input = Dither */
+ len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (WebRtc_Word16)FRAMESAMPLES);
+
+ if (len<1)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* subtract dither and scale down spectral samples with low SNR */
+ if (AvgPitchGain_Q12 <= 614)
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)30, 10),
+ (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (WebRtc_UWord32)2195456, 16));
+ *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10);
+ *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10);
+ *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10);
+ *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10);
+ }
+ }
+ else
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)36, 10),
+ (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (WebRtc_UWord32)2654208, 16));
+ *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10);
+ *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10);
+ *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10);
+ *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10);
+ }
+ }
+
+ return len;
+}
+
+
+int WebRtcIsacfix_EncodeSpec(const WebRtc_Word16 *fr,
+ const WebRtc_Word16 *fi,
+ Bitstr_enc *streamdata,
+ WebRtc_Word16 AvgPitchGain_Q12)
+{
+ WebRtc_Word16 dataQ7[FRAMESAMPLES];
+ WebRtc_Word32 PSpec[FRAMESAMPLES/4];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES/4];
+ 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;
+ WebRtc_UWord32 sum;
+ WebRtc_Word16 lft_shft;
+ WebRtc_Word16 status;
+ int k, n, j;
+
+
+ /* create dither_float signal */
+ GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
+
+ /* add dither and quantize, and compute power spectrum */
+ /* Vector dataQ7 contains Dither in Q7 */
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ val = ((*fr++ + dataQ7[k] + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */
+ dataQ7[k] = val; /* New value in Data */
+ sum = WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */
+ dataQ7[k+1] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */
+ dataQ7[k+2] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */
+ dataQ7[k+3] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2);
+ }
+
+ /* compute correlation from power spectrum */
+ CalcCorrelation(PSpec, CorrQ7);
+
+
+ /* find AR coefficients */
+ /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
+ lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (lft_shft > 0) {
+ for (k=0; k<AR_ORDER+1; k++)
+ CorrQ7_norm[k] = WEBRTC_SPL_LSHIFT_W32(CorrQ7[k], lft_shft);
+ } else {
+ for (k=0; k<AR_ORDER+1; k++)
+ CorrQ7_norm[k] = WEBRTC_SPL_RSHIFT_W32(CorrQ7[k], -lft_shft);
+ }
+
+ /* find RC coefficients */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* quantize & code RC Coef */
+ status = WebRtcIsacfix_EncodeRcCoef(RCQ15, streamdata);
+ if (status < 0) {
+ return status;
+ }
+
+ /* 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 += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[j-n], ARCoefQ12[n]) + 256, 9)) + 4, 3);
+ for (n = j+1; n <= AR_ORDER; n++)
+ nrg += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[n-j], ARCoefQ12[n]) + 256, 9)) + 4, 3);
+ }
+
+ if (lft_shft > 0)
+ nrg = WEBRTC_SPL_RSHIFT_W32(nrg, lft_shft);
+ else
+ nrg = WEBRTC_SPL_LSHIFT_W32(nrg, -lft_shft);
+
+ if(nrg>131072)
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg); /* also shifts 31 bits to the left! */
+ else
+ gain2_Q10 = WEBRTC_SPL_RSHIFT_W32(FRAMESAMPLES, 2);
+
+ /* quantize & code gain2_Q10 */
+ if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata))
+ return -1;
+
+ /* compute inverse AR magnitude spectrum */
+ CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8);
+
+
+ /* arithmetic coding of spectrum */
+ status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (WebRtc_Word16)FRAMESAMPLES);
+ if ( status )
+ return( status );
+
+ return 0;
+}
+
+
+/* Matlab's LAR definition */
+static void Rc2LarFix(const WebRtc_Word16 *rcQ15, WebRtc_Word32 *larQ17, WebRtc_Word16 order) {
+
+ /*
+
+ This is a piece-wise implemenetation of a rc2lar-function (all values in the comment
+ are Q15 values and are based on [0 24956/32768 30000/32768 32500/32768], i.e.
+ [0.76159667968750 0.91552734375000 0.99182128906250]
+
+ x0 x1 a k x0(again) b
+ ==================================================================================
+ 0.00 0.76: 0 2.625997508581 0 0
+ 0.76 0.91: 2.000012018559 7.284502668663 0.761596679688 -3.547841027073
+ 0.91 0.99: 3.121320351712 31.115835041229 0.915527343750 -25.366077452148
+ 0.99 1.00: 5.495270168700 686.663805654056 0.991821289063 -675.552510708011
+
+ The implementation is y(x)= a + (x-x0)*k, but this can be simplified to
+
+ y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k
+
+ akx=[0 2.625997508581 0
+ 2.000012018559 7.284502668663 0.761596679688
+ 3.121320351712 31.115835041229 0.915527343750
+ 5.495270168700 686.663805654056 0.991821289063];
+
+ b = akx(:,1) - akx(:,3).*akx(:,2)
+
+ [ 0.0
+ -3.547841027073
+ -25.366077452148
+ -675.552510708011]
+
+ */
+
+ int k;
+ WebRtc_Word16 rc;
+ WebRtc_Word32 larAbsQ17;
+
+ for (k = 0; k < order; k++) {
+
+ rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15
+
+ /* Calculate larAbsQ17 in Q17 from rc in Q15 */
+
+ if (rc<24956) { //0.7615966 in Q15
+ // (Q15*Q13)>>11 = Q17
+ larAbsQ17 = WEBRTC_SPL_MUL_16_16_RSFT(rc, 21512, 11);
+ } else if (rc<30000) { //0.91552734375 in Q15
+ // Q17 + (Q15*Q12)>>10 = Q17
+ larAbsQ17 = -465024 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 29837, 10);
+ } else if (rc<32500) { //0.99182128906250 in Q15
+ // Q17 + (Q15*Q10)>>8 = Q17
+ larAbsQ17 = -3324784 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 31863, 8);
+ } else {
+ // Q17 + (Q15*Q5)>>3 = Q17
+ larAbsQ17 = -88546020 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 21973, 3);
+ }
+
+ if (rcQ15[k]>0) {
+ larQ17[k] = larAbsQ17;
+ } else {
+ larQ17[k] = -larAbsQ17;
+ }
+ }
+}
+
+
+static void Lar2RcFix(const WebRtc_Word32 *larQ17, WebRtc_Word16 *rcQ15, WebRtc_Word16 order) {
+
+ /*
+ This is a piece-wise implemenetation of a lar2rc-function
+ See comment in Rc2LarFix() about details.
+ */
+
+ int k;
+ WebRtc_Word16 larAbsQ11;
+ WebRtc_Word32 rc;
+
+ for (k = 0; k < order; k++) {
+
+ larAbsQ11 = (WebRtc_Word16) WEBRTC_SPL_ABS_W32(WEBRTC_SPL_RSHIFT_W32(larQ17[k]+32,6)); //Q11
+
+ if (larAbsQ11<4097) { //2.000012018559 in Q11
+ // Q11*Q16>>12 = Q15
+ rc = WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24957, 12);
+ } else if (larAbsQ11<6393) { //3.121320351712 in Q11
+ // (Q11*Q17 + Q13)>>13 = Q15
+ rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 17993) + 130738688), 13);
+ } else if (larAbsQ11<11255) { //5.495270168700 in Q11
+ // (Q11*Q19 + Q30)>>15 = Q15
+ rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 16850) + 875329820), 15);
+ } else {
+ // (Q11*Q24>>16 + Q19)>>4 = Q15
+ rc = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24433, 16)) + 515804), 4);
+ }
+
+ if (larQ17[k]<=0) {
+ rc = -rc;
+ }
+
+ rcQ15[k] = (WebRtc_Word16) rc; // Q15
+ }
+}
+
+static void Poly2LarFix(WebRtc_Word16 *lowbandQ15,
+ WebRtc_Word16 orderLo,
+ WebRtc_Word16 *hibandQ15,
+ WebRtc_Word16 orderHi,
+ WebRtc_Word16 Nsub,
+ WebRtc_Word32 *larsQ17) {
+
+ int k, n;
+ WebRtc_Word32 *outpQ17;
+ WebRtc_Word16 orderTot;
+ WebRtc_Word32 larQ17[MAX_ORDER]; // Size 7+6 is enough
+
+ orderTot = (orderLo + orderHi);
+ outpQ17 = larsQ17;
+ for (k = 0; k < Nsub; k++) {
+
+ Rc2LarFix(lowbandQ15, larQ17, orderLo);
+
+ for (n = 0; n < orderLo; n++)
+ outpQ17[n] = larQ17[n]; //Q17
+
+ Rc2LarFix(hibandQ15, larQ17, orderHi);
+
+ for (n = 0; n < orderHi; n++)
+ outpQ17[n + orderLo] = larQ17[n]; //Q17;
+
+ outpQ17 += orderTot;
+ lowbandQ15 += orderLo;
+ hibandQ15 += orderHi;
+ }
+}
+
+
+static void Lar2polyFix(WebRtc_Word32 *larsQ17,
+ WebRtc_Word16 *lowbandQ15,
+ WebRtc_Word16 orderLo,
+ WebRtc_Word16 *hibandQ15,
+ WebRtc_Word16 orderHi,
+ WebRtc_Word16 Nsub) {
+
+ int k, n;
+ WebRtc_Word16 orderTot;
+ WebRtc_Word16 *outplQ15, *outphQ15;
+ WebRtc_Word32 *inpQ17;
+ WebRtc_Word16 rcQ15[7+6];
+
+ orderTot = (orderLo + orderHi);
+ outplQ15 = lowbandQ15;
+ outphQ15 = hibandQ15;
+ inpQ17 = larsQ17;
+ for (k = 0; k < Nsub; k++) {
+
+ /* gains not handled here as in the FLP version */
+
+ /* Low band */
+ Lar2RcFix(&inpQ17[0], rcQ15, orderLo);
+ for (n = 0; n < orderLo; n++)
+ outplQ15[n] = rcQ15[n]; // Refl. coeffs
+
+ /* High band */
+ Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi);
+ for (n = 0; n < orderHi; n++)
+ outphQ15[n] = rcQ15[n]; // Refl. coeffs
+
+ inpQ17 += orderTot;
+ outplQ15 += orderLo;
+ outphQ15 += orderHi;
+ }
+}
+
+int WebRtcIsacfix_DecodeLpc(WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *LPCCoef_loQ15,
+ WebRtc_Word16 *LPCCoef_hiQ15,
+ Bitstr_dec *streamdata,
+ WebRtc_Word16 *outmodel) {
+
+ WebRtc_Word32 larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+ int err;
+
+ err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+
+ Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+ return 0;
+}
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
+ WebRtc_Word32 *LPCCoefQ17,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *outmodel)
+{
+ int j, k, n;
+ int err;
+ WebRtc_Word16 pos, pos2, posg, poss, offsg, offss, offs2;
+ WebRtc_Word16 gainpos;
+ WebRtc_Word16 model;
+ WebRtc_Word16 index_QQ[KLT_ORDER_SHAPE];
+ WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ WebRtc_Word16 tmpcoeffs_sQ10[KLT_ORDER_SHAPE];
+ WebRtc_Word32 tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+ WebRtc_Word32 tmpcoeffs2_sQ18[KLT_ORDER_SHAPE];
+ WebRtc_Word32 sumQQ;
+ WebRtc_Word16 sumQQ16;
+ WebRtc_Word32 tmp32;
+
+
+
+ /* entropy decoding of model number */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1);
+ if (err<0) // error check
+ return err;
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE);
+ if (err<0) // error check
+ return err;
+ /* find quantization levels for coefficients */
+ for (k=0; k<KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_sQ10[WebRtcIsacfix_kSelIndShape[k]] = WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[model]+WebRtcIsacfix_kOffsetShape[model][k] + index_QQ[k]];
+ }
+
+ err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfGainPtr[model], WebRtcIsacfix_kInitIndexGain[model], KLT_ORDER_GAIN);
+ if (err<0) // error check
+ return err;
+ /* find quantization levels for coefficients */
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[model]+ WebRtcIsacfix_kOffsetGain[model][k] + index_QQ[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<2; k++) {
+ sumQQ = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n=0; n<2; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[model][pos2], tmpcoeffs_gQ17[pos]<<5)); // (Q15*Q17)>>(16-5) = Q21
+ pos++;
+ pos2++;
+ }
+ tmpcoeffs2_gQ21[posg] = sumQQ; //Q21
+ posg++;
+ offs2 += 2;
+ }
+ offs2 = 0;
+
+ for (k=0; k<LPC_SHAPE_ORDER; k++) {
+ sumQQ = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n=0; n<LPC_SHAPE_ORDER; n++) {
+ sumQQ += WEBRTC_SPL_MUL_16_16_RSFT(tmpcoeffs_sQ10[pos], WebRtcIsacfix_kT1ShapeQ15[model][pos2], 7); // (Q10*Q15)>>7 = Q18
+ pos++;
+ pos2++;
+ }
+ tmpcoeffs2_sQ18[poss] = sumQQ; //Q18
+ poss++;
+ offs2 += LPC_SHAPE_ORDER;
+ }
+ offsg += 2;
+ 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<2; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = j;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2GainQ15[model][pos2], tmpcoeffs2_gQ21[pos]), 1); // (Q15*Q21)>>(16-1) = Q21
+ pos += 2;
+ pos2 += SUBFRAMES;
+
+ }
+ tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4);
+ posg++;
+ }
+ poss = offss;
+ for (k=0; k<LPC_SHAPE_ORDER; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = j;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2ShapeQ15[model][pos2], tmpcoeffs2_sQ18[pos])); // (Q15*Q18)>>16 = Q17
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_sQ17[poss] = sumQQ;
+ poss++;
+ }
+ offsg += 2;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* scaling, mean addition, and gain restoration */
+ gainpos = 0;
+ posg = 0;poss = 0;pos=0;
+ for (k=0; k<SUBFRAMES; k++) {
+
+ /* log gains */
+ sumQQ16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+ gainpos++;
+ posg++;
+
+ sumQQ16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+ gainpos++;
+ posg++;
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]), 3); // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+ }
+
+
+ *outmodel=model;
+
+ return 0;
+}
+
+/* estimate codel length of LPC Coef */
+static int EstCodeLpcCoef(WebRtc_Word32 *LPCCoefQ17,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *model,
+ WebRtc_Word32 *sizeQ11,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData,
+ transcode_obj *transcodingParam) {
+ int j, k, n;
+ WebRtc_Word16 posQQ, pos2QQ, gainpos;
+ WebRtc_Word16 pos, pos2, poss, posg, offsg, offss, offs2;
+ WebRtc_Word16 index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE];
+ WebRtc_Word16 index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE];
+ WebRtc_Word32 BitsQQ;
+
+ WebRtc_Word16 tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+ WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs2_sQ17[KLT_ORDER_SHAPE];
+ WebRtc_Word32 sumQQ;
+ WebRtc_Word32 tmp32;
+ WebRtc_Word16 sumQQ16;
+ int status = 0;
+
+ /* write LAR coefficients to statistics file */
+ /* Save data for creation of multiple bitstreams (and transcoding) */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+ }
+ }
+
+ /* log gains, mean removal and scaling */
+ posg = 0;poss = 0;pos=0; gainpos=0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, poss++, pos++) {
+ tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(17203, tmp32<<3); // tmp32 = 2.1*tmp32
+ tmpcoeffs_sQ17[poss] = tmp32; //Q17
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, poss++, pos++) {
+ tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(14746, tmp32<<1); // tmp32 = 0.45*tmp32
+ tmpcoeffs_sQ17[poss] = tmp32; //Q17
+ }
+
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ offsg = 0;
+ offss = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n=0; n<2; n++) {
+ sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[pos], WebRtcIsacfix_kT1GainQ15[0][pos2]); //Q21 = Q6*Q15
+ pos++;
+ pos2 += 2;
+ }
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+ }
+ poss = offss;
+ for (k=0; k<LPC_SHAPE_ORDER; k++) {
+ sumQQ = 0;
+ pos = offss;
+ pos2 = k;
+ for (n=0; n<LPC_SHAPE_ORDER; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1ShapeQ15[0][pos2], tmpcoeffs_sQ17[pos]<<1)); // (Q15*Q17)>>(16-1) = Q17
+ pos++;
+ pos2 += LPC_SHAPE_ORDER;
+ }
+ tmpcoeffs2_sQ17[poss] = sumQQ; //Q17
+ poss++;
+ }
+ offsg += 2;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* right transform */
+ offsg = 0;
+ offss = 0;
+ offs2 = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2GainQ15[0][pos2], tmpcoeffs2_gQ21[pos]), 1); // (Q15*Q21)>>(16-1) = Q21
+ pos += 2;
+ pos2++;
+ }
+ tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4);
+ posg++;
+ }
+ poss = offss;
+ for (k=0; k<LPC_SHAPE_ORDER; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2ShapeQ15[0][pos2], tmpcoeffs2_sQ17[pos]<<1)); // (Q15*Q17)>>(16-1) = Q17
+ pos += LPC_SHAPE_ORDER;
+ pos2++;
+ }
+ tmpcoeffs_sQ17[poss] = sumQQ;
+ poss++;
+ }
+ offs2 += SUBFRAMES;
+ offsg += 2;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* quantize coefficients */
+
+ BitsQQ = 0;
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (WebRtc_Word16)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+ index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k];
+ posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k];
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+ }
+
+ /* determine number of bits */
+ sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11
+ BitsQQ += sumQQ;
+ }
+
+ for (k=0; k<KLT_ORDER_SHAPE; k++) //ATTN: ok?
+ {
+ index_sQQ[k] = (WebRtc_Word16)(CalcLrIntQ(tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]], 17) + WebRtcIsacfix_kQuantMinShape[k]); //ATTN: ok?
+
+ if (index_sQQ[k] < 0)
+ index_sQQ[k] = 0;
+ else if (index_sQQ[k] > WebRtcIsacfix_kMaxIndShape[k])
+ index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k];
+ index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k];
+
+ posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k];
+ sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11
+ BitsQQ += sumQQ;
+ }
+
+
+
+ *model = 0;
+ *sizeQ11=BitsQQ;
+
+ /* entropy coding of model number */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization indices - shape only */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_SHAPE; k++)
+ {
+ encData->LPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k];
+ }
+ }
+ /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */
+ transcodingParam->full = streamdata->full;
+ transcodingParam->stream_index = streamdata->stream_index;
+ transcodingParam->streamval = streamdata->streamval;
+ transcodingParam->W_upper = streamdata->W_upper;
+ transcodingParam->beforeLastWord = streamdata->stream[streamdata->stream_index-1];
+ transcodingParam->lastWord = streamdata->stream[streamdata->stream_index];
+
+ /* entropy coding of index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ /* find quantization levels for shape coefficients */
+ for (k=0; k<KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]] = WEBRTC_SPL_MUL(128, WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[0]+index_ovr_sQQ[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++) {
+ sumQQ = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n=0; n<LPC_SHAPE_ORDER; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1ShapeQ15[0][pos2], tmpcoeffs_sQ17[pos]<<1)); // (Q15*Q17)>>(16-1) = Q17
+ pos++;
+ pos2++;
+ }
+ tmpcoeffs2_sQ17[poss] = sumQQ;
+
+ poss++;
+ 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++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = j;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2ShapeQ15[0][pos2], tmpcoeffs2_sQ17[pos]<<1)); // (Q15*Q17)>>(16-1) = Q17
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_sQ17[poss] = sumQQ;
+ poss++;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* scaling, mean addition, and gain restoration */
+ poss = 0;pos=0;
+ for (k=0; k<SUBFRAMES; k++) {
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]), 3); // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ }
+
+ //to update tmpcoeffs_gQ17 to the proper state
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[0]+index_ovr_gQQ[k]];
+ }
+
+
+
+ /* find quantization levels for coefficients */
+
+ /* left transform */
+ offsg = 0;
+ posg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n=0; n<2; n++) {
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][pos2], tmpcoeffs_gQ17[pos])<<1); // (Q15*Q17)>>(16-1) = Q17
+ pos++;
+ pos2++;
+ }
+ tmpcoeffs2_gQ21[posg] = WEBRTC_SPL_LSHIFT_W32(sumQQ, 4); //Q17<<4 = Q21
+ posg++;
+ offs2 += 2;
+ }
+ offsg += 2;
+ }
+
+ /* right transform */ // Transpose matrix
+ offsg = 0;
+ posg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = j;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2GainQ15[0][pos2], tmpcoeffs2_gQ21[pos]), 1); // (Q15*Q21)>>(16-1) = Q21
+ pos += 2;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4);
+ posg++;
+ }
+ offsg += 2;
+ }
+
+ /* scaling, mean addition, and gain restoration */
+ posg = 0;
+ gainpos = 0;
+ for (k=0; k<2*SUBFRAMES; k++) {
+
+ sumQQ16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+
+ gainpos++;
+ pos++;posg++;
+ }
+
+ return 0;
+}
+
+int WebRtcIsacfix_EstCodeLpcGain(WebRtc_Word32 *gain_lo_hiQ17,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData) {
+ int j, k, n;
+ WebRtc_Word16 posQQ, pos2QQ, gainpos;
+ WebRtc_Word16 pos, pos2, posg, offsg, offs2;
+ WebRtc_Word16 index_gQQ[KLT_ORDER_GAIN];
+
+ WebRtc_Word16 tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ WebRtc_Word32 sumQQ;
+ int status = 0;
+
+ /* write LAR coefficients to statistics file */
+ /* Save data for creation of multiple bitstreams (and transcoding) */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+ }
+ }
+
+ /* log gains, mean removal and scaling */
+ posg = 0; pos = 0; gainpos = 0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ offsg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n=0; n<2; n++) {
+ sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[pos], WebRtcIsacfix_kT1GainQ15[0][pos2]); //Q21 = Q6*Q15
+ pos++;
+ pos2 += 2;
+ }
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+ }
+ offsg += 2;
+ }
+
+ /* right transform */
+ offsg = 0;
+ offs2 = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2GainQ15[0][pos2], tmpcoeffs2_gQ21[pos]), 1); // (Q15*Q21)>>(16-1) = Q21
+ pos += 2;
+ pos2++;
+ }
+ tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4);
+ posg++;
+ }
+ offsg += 2;
+ offs2 += SUBFRAMES;
+ }
+
+ /* quantize coefficients */
+
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (WebRtc_Word16)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+ }
+ }
+
+ /* entropy coding of index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ return 0;
+}
+
+
+int WebRtcIsacfix_EncodeLpc(WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *LPCCoef_loQ15,
+ WebRtc_Word16 *LPCCoef_hiQ15,
+ WebRtc_Word16 *model,
+ WebRtc_Word32 *sizeQ11,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData,
+ transcode_obj *transcodeParam)
+{
+ int status = 0;
+ WebRtc_Word32 larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+ // = (6+12)*6 == 108
+
+ Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17);
+
+ status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11, streamdata, encData, transcodeParam);
+ if (status < 0) {
+ return (status);
+ }
+
+ Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+ return 0;
+}
+
+
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, WebRtc_Word16 *RCQ15)
+{
+ int k, err;
+ WebRtc_Word16 index[AR_ORDER];
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER);
+ if (err<0) // error check
+ return err;
+
+ /* find quantization levels for reflection coefficients */
+ for (k=0; k<AR_ORDER; k++)
+ {
+ RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+ }
+
+ return 0;
+}
+
+
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(WebRtc_Word16 *RCQ15, Bitstr_enc *streamdata)
+{
+ int k;
+ WebRtc_Word16 index[AR_ORDER];
+ int status;
+
+ /* quantize reflection coefficients (add noise feedback?) */
+ for (k=0; k<AR_ORDER; k++)
+ {
+ index[k] = WebRtcIsacfix_kRcInitInd[k];
+
+ if (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k]])
+ {
+ while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1])
+ index[k]++;
+ }
+ else
+ {
+ while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ;
+ }
+
+ RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+ }
+
+
+ /* entropy coding of quantization indices */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, WebRtc_Word32 *gainQ10)
+{
+ int err;
+ WebRtc_Word16 index;
+
+ /* entropy decoding of quantization index */
+ err = WebRtcIsacfix_DecHistOneStepMulti(
+ &index,
+ streamdata,
+ WebRtcIsacfix_kGainPtr,
+ WebRtcIsacfix_kGainInitInd,
+ 1);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* find quantization level */
+ *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+ return 0;
+}
+
+
+
+/* quantize & code squared Gain */
+int WebRtcIsacfix_EncodeGain2(WebRtc_Word32 *gainQ10, Bitstr_enc *streamdata)
+{
+ WebRtc_Word16 index;
+ int status = 0;
+
+ /* find quantization index */
+ index = WebRtcIsacfix_kGainInitInd[0];
+ if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index])
+ {
+ while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1])
+ index++;
+ }
+ else
+ {
+ while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ;
+ }
+
+ /* dequantize */
+ *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+ /* entropy coding of quantization index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, WebRtc_Word16 *PitchGains_Q12)
+{
+ int err;
+ WebRtc_Word16 index_comb;
+ const WebRtc_UWord16 *pitch_gain_cdf_ptr[1];
+
+ /* entropy decoding of quantization indices */
+ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 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;
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+ PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+ PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+ PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+ return 0;
+}
+
+
+/* quantize & code Pitch Gains */
+int WebRtcIsacfix_EncodePitchGain(WebRtc_Word16 *PitchGains_Q12, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData)
+{
+ int k,j;
+ WebRtc_Word16 SQ15[PITCH_SUBFRAMES];
+ WebRtc_Word16 index[3];
+ WebRtc_Word16 index_comb;
+ const WebRtc_UWord16 *pitch_gain_cdf_ptr[1];
+ WebRtc_Word32 CQ17;
+ int status = 0;
+
+
+ /* get the approximate arcsine (almost linear)*/
+ for (k=0; k<PITCH_SUBFRAMES; k++)
+ SQ15[k] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[k],33,2); //Q15
+
+
+ /* find quantization index; only for the first three transform coefficients */
+ for (k=0; k<3; k++)
+ {
+ /* transform */
+ CQ17=0;
+ for (j=0; j<PITCH_SUBFRAMES; j++) {
+ CQ17 += WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIsacfix_kTransform[k][j], SQ15[j],10); // Q17
+ }
+
+ index[k] = (WebRtc_Word16)((CQ17 + 8192)>>14); // Rounding and scaling with stepsize (=1/0.125=8)
+
+ /* check that the index is not outside the boundaries of the table */
+ if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k];
+ else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k];
+ index[k] -= WebRtcIsacfix_kLowerlimiGain[k];
+ }
+
+ /* calculate unique overall index */
+ index_comb = (WebRtc_Word16)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) +
+ WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]);
+
+ /* unquantize back to pitch gains by table look-up */
+ // (Y)
+ PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+ PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+ PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+ PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+
+ /* entropy coding of quantization pitch gains */
+ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->pitchGain_index[encData->startIdx] = index_comb;
+ }
+
+ return 0;
+}
+
+
+
+/* Pitch LAG */
+
+
+/* decode & dequantize Pitch Lags */
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
+ WebRtc_Word16 *PitchGain_Q12,
+ WebRtc_Word16 *PitchLags_Q7)
+{
+ int k, err;
+ WebRtc_Word16 index[PITCH_SUBFRAMES];
+ const WebRtc_Word16 *mean_val2Q10, *mean_val4Q10;
+
+ const WebRtc_Word16 *lower_limit;
+ const WebRtc_UWord16 *init_index;
+ const WebRtc_UWord16 *cdf_size;
+ const WebRtc_UWord16 **cdf;
+
+ WebRtc_Word32 meangainQ12;
+ WebRtc_Word32 CQ11, CQ10,tmp32a,tmp32b;
+ WebRtc_Word16 shft,tmp16a,tmp16c;
+
+ meangainQ12=0;
+ for (k = 0; k < 4; k++)
+ meangainQ12 += PitchGain_Q12[k];
+
+ meangainQ12 = WEBRTC_SPL_RSHIFT_W32(meangainQ12, 2); // Get average
+
+ /* voicing classificiation */
+ if (meangainQ12 <= 819) { // mean_gain < 0.2
+ shft = -1; // StepSize=2.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeLo;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+ lower_limit = WebRtcIsacfix_kLowerLimitLo;
+ init_index = WebRtcIsacfix_kInitIndLo;
+ } else if (meangainQ12 <= 1638) { // mean_gain < 0.4
+ shft = 0; // StepSize=1.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeMid;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+ lower_limit = WebRtcIsacfix_kLowerLimitMid;
+ init_index = WebRtcIsacfix_kInitIndMid;
+ } else {
+ shft = 1; // StepSize=0.5;
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeHi;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+ lower_limit = WebRtcIsacfix_kLowerLimitHi;
+ init_index = WebRtcIsacfix_kInitIndHi;
+ }
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+ if ((err<0) || (index[0]<0)) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+ err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ CQ11 = ((WebRtc_Word32)index[0] + lower_limit[0]); // Q0
+ CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11);
+ tmp16a = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32a, 5);
+ PitchLags_Q7[k] = tmp16a;
+ }
+
+ CQ10 = mean_val2Q10[index[1]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) WebRtcIsacfix_kTransform[1][k], (WebRtc_Word16) CQ10,10);
+ tmp16c = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5);
+ PitchLags_Q7[k] += tmp16c;
+ }
+
+ CQ10 = mean_val4Q10[index[3]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) WebRtcIsacfix_kTransform[3][k], (WebRtc_Word16) CQ10,10);
+ tmp16c = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5);
+ PitchLags_Q7[k] += tmp16c;
+ }
+
+ return 0;
+}
+
+
+
+/* quantize & code Pitch Lags */
+int WebRtcIsacfix_EncodePitchLag(WebRtc_Word16 *PitchLagsQ7,WebRtc_Word16 *PitchGain_Q12,
+ Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData)
+{
+ int k, j;
+ WebRtc_Word16 index[PITCH_SUBFRAMES];
+ WebRtc_Word32 meangainQ12, CQ17;
+ WebRtc_Word32 CQ11, CQ10,tmp32a;
+
+ const WebRtc_Word16 *mean_val2Q10,*mean_val4Q10;
+ const WebRtc_Word16 *lower_limit, *upper_limit;
+ const WebRtc_UWord16 **cdf;
+ WebRtc_Word16 shft, tmp16a, tmp16b, tmp16c;
+ WebRtc_Word32 tmp32b;
+ int status = 0;
+
+ /* compute mean pitch gain */
+ meangainQ12=0;
+ for (k = 0; k < 4; k++)
+ meangainQ12 += PitchGain_Q12[k];
+
+ meangainQ12 = WEBRTC_SPL_RSHIFT_W32(meangainQ12, 2);
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->meanGain[encData->startIdx] = meangainQ12;
+ }
+
+ /* voicing classificiation */
+ if (meangainQ12 <= 819) { // mean_gain < 0.2
+ shft = -1; // StepSize=2.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+ lower_limit = WebRtcIsacfix_kLowerLimitLo;
+ upper_limit = WebRtcIsacfix_kUpperLimitLo;
+ } else if (meangainQ12 <= 1638) { // mean_gain < 0.4
+ shft = 0; // StepSize=1.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+ lower_limit = WebRtcIsacfix_kLowerLimitMid;
+ upper_limit = WebRtcIsacfix_kUpperLimitMid;
+ } else {
+ shft = 1; // StepSize=0.5;
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+ lower_limit = WebRtcIsacfix_kLowerLimitHi;
+ upper_limit = WebRtcIsacfix_kUpperLimitHi;
+ }
+
+ /* find quantization index */
+ for (k=0; k<4; k++)
+ {
+ /* transform */
+ CQ17=0;
+ for (j=0; j<PITCH_SUBFRAMES; j++)
+ CQ17 += WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIsacfix_kTransform[k][j], PitchLagsQ7[j],2); // Q17
+
+ CQ17 = WEBRTC_SPL_SHIFT_W32(CQ17,shft); // Scale with StepSize
+
+ /* quantize */
+ tmp16b = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(CQ17 + 65536, 17 );
+ index[k] = tmp16b;
+
+ /* 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 bitstreams */
+ if(encData != NULL) {
+ encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
+ }
+ }
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ CQ11 = (index[0] + lower_limit[0]); // Q0
+ CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11); // Q12
+ tmp16a = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32a, 5);// Q7
+ PitchLagsQ7[k] = tmp16a;
+ }
+
+ CQ10 = mean_val2Q10[index[1]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) WebRtcIsacfix_kTransform[1][k], (WebRtc_Word16) CQ10,10);
+ tmp16c = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q7
+ PitchLagsQ7[k] += tmp16c;
+ }
+
+ CQ10 = mean_val4Q10[index[3]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) WebRtcIsacfix_kTransform[3][k], (WebRtc_Word16) CQ10,10);
+ tmp16c = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q7
+ PitchLagsQ7[k] += tmp16c;
+ }
+
+ /* entropy coding of quantization pitch lags */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+
+/* Routines for inband signaling of bandwitdh estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const WebRtc_UWord16 kFrameLenCdf[4] = {
+ 0, 21845, 43690, 65535};
+
+/* pointer to cdf array for frame length indicator */
+const WebRtc_UWord16 *kFrameLenCdfPtr[1] = {kFrameLenCdf};
+
+/* initial cdf index for decoder of frame length indicator */
+const WebRtc_UWord16 kFrameLenInitIndex[1] = {1};
+
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
+ WebRtc_Word16 *framesamples)
+{
+
+ int err;
+ WebRtc_Word16 frame_mode;
+
+ err = 0;
+ /* entropy decoding of frame length [1:30ms,2:60ms] */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&frame_mode, streamdata, kFrameLenCdfPtr, kFrameLenInitIndex, 1);
+ if (err<0) // error check
+ 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 WebRtcIsacfix_EncodeFrameLen(WebRtc_Word16 framesamples, Bitstr_enc *streamdata) {
+
+ int status;
+ WebRtc_Word16 frame_mode;
+
+ 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;
+
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &frame_mode, kFrameLenCdfPtr, 1);
+
+ return status;
+}
+
+/* cdf array for estimated bandwidth */
+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 */
+const WebRtc_UWord16 *kBwCdfPtr[1] = {kBwCdf};
+
+/* initial cdf index for decoder of estimated bandwidth*/
+const WebRtc_UWord16 kBwInitIndex[1] = {7};
+
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata, WebRtc_Word16 *BWno) {
+
+ int err;
+ WebRtc_Word16 BWno32;
+
+ /* entropy decoding of sender's BW estimation [0..23] */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr, kBwInitIndex, 1);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+ *BWno = (WebRtc_Word16)BWno32;
+ return err;
+
+}
+
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(WebRtc_Word16 *BWno, Bitstr_enc *streamdata)
+{
+ int status = 0;
+ /* entropy encoding of receiver's BW estimation [0..23] */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+
+ return status;
+}
+
+/* estimate codel length of LPC Coef */
+void WebRtcIsacfix_TranscodeLpcCoef(WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *index_gQQ) {
+ int j, k, n;
+ WebRtc_Word16 posQQ, pos2QQ;
+ WebRtc_Word16 pos, pos2, posg, offsg, offs2, gainpos;
+ WebRtc_Word32 tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ WebRtc_Word32 sumQQ;
+
+
+ /* log gains, mean removal and scaling */
+ posg = 0;pos=0; gainpos=0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ offsg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n=0; n<2; n++) {
+ sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[pos], WebRtcIsacfix_kT1GainQ15[0][pos2]); //Q21 = Q6*Q15
+ pos++;
+ pos2 += 2;
+ }
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+ }
+
+ offsg += 2;
+ }
+
+ /* right transform */
+ offsg = 0;
+ offs2 = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ posg = offsg;
+ for (k=0; k<2; k++) {
+ sumQQ = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n=0; n<SUBFRAMES; n++) {
+ sumQQ += WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT2GainQ15[0][pos2], tmpcoeffs2_gQ21[pos]), 1); // (Q15*Q21)>>(16-1) = Q21
+ pos += 2;
+ pos2++;
+ }
+ tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4);
+ posg++;
+ }
+ offsg += 2;
+ offs2 += SUBFRAMES;
+ }
+
+ /* quantize coefficients */
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (WebRtc_Word16)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h b/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
new file mode 100644
index 0000000..298ea22
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file contains all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+
+#include "structs.h"
+
+/* decode complex spectrum (return number of bytes in stream) */
+WebRtc_Word16 WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
+ WebRtc_Word16 *frQ7,
+ WebRtc_Word16 *fiQ7,
+ WebRtc_Word16 AvgPitchGain_Q12);
+
+/* encode complex spectrum */
+int WebRtcIsacfix_EncodeSpec(const WebRtc_Word16 *fr,
+ const WebRtc_Word16 *fi,
+ Bitstr_enc *streamdata,
+ WebRtc_Word16 AvgPitchGain_Q12);
+
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
+ WebRtc_Word32 *LPCCoefQ17,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *outmodel);
+
+int WebRtcIsacfix_DecodeLpc(WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *LPCCoef_loQ15,
+ WebRtc_Word16 *LPCCoef_hiQ15,
+ Bitstr_dec *streamdata,
+ WebRtc_Word16 *outmodel);
+
+/* quantize & code LPC Coef */
+int WebRtcIsacfix_EncodeLpc(WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *LPCCoef_loQ15,
+ WebRtc_Word16 *LPCCoef_hiQ15,
+ WebRtc_Word16 *model,
+ WebRtc_Word32 *sizeQ11,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData,
+ transcode_obj *transcodeParam);
+
+int WebRtcIsacfix_EstCodeLpcGain(WebRtc_Word32 *gain_lo_hiQ17,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData);
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata,
+ WebRtc_Word16 *RCQ15);
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(WebRtc_Word16 *RCQ15,
+ Bitstr_enc *streamdata);
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata,
+ WebRtc_Word32 *Gain2);
+
+/* quantize & code squared Gain (input is squared gain) */
+int WebRtcIsacfix_EncodeGain2(WebRtc_Word32 *gain2,
+ Bitstr_enc *streamdata);
+
+int WebRtcIsacfix_EncodePitchGain(WebRtc_Word16 *PitchGains_Q12,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData);
+
+int WebRtcIsacfix_EncodePitchLag(WebRtc_Word16 *PitchLagQ7,
+ WebRtc_Word16 *PitchGain_Q12,
+ Bitstr_enc *streamdata,
+ ISAC_SaveEncData_t* encData);
+
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata,
+ WebRtc_Word16 *PitchGain_Q12);
+
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
+ WebRtc_Word16 *PitchGain_Q12,
+ WebRtc_Word16 *PitchLagQ7);
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
+ WebRtc_Word16 *framelength);
+
+
+int WebRtcIsacfix_EncodeFrameLen(WebRtc_Word16 framelength,
+ Bitstr_enc *streamdata);
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata,
+ WebRtc_Word16 *BWno);
+
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(WebRtc_Word16 *BWno,
+ Bitstr_enc *streamdata);
+
+void WebRtcIsacfix_TranscodeLpcCoef(WebRtc_Word32 *tmpcoeffs_gQ6,
+ WebRtc_Word16 *index_gQQ);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/fft.c b/src/modules/audio_coding/codecs/isac/fix/source/fft.c
new file mode 100644
index 0000000..fff35c4
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/fft.c
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+/*
+ * fft.c
+ *
+ * Fast Fourier Transform
+ *
+ */
+
+
+#include "fft.h"
+
+const WebRtc_Word16 kSortTabFft[240] = {
+ 0, 60, 120, 180, 20, 80, 140, 200, 40, 100, 160, 220,
+ 4, 64, 124, 184, 24, 84, 144, 204, 44, 104, 164, 224,
+ 8, 68, 128, 188, 28, 88, 148, 208, 48, 108, 168, 228,
+ 12, 72, 132, 192, 32, 92, 152, 212, 52, 112, 172, 232,
+ 16, 76, 136, 196, 36, 96, 156, 216, 56, 116, 176, 236,
+ 1, 61, 121, 181, 21, 81, 141, 201, 41, 101, 161, 221,
+ 5, 65, 125, 185, 25, 85, 145, 205, 45, 105, 165, 225,
+ 9, 69, 129, 189, 29, 89, 149, 209, 49, 109, 169, 229,
+ 13, 73, 133, 193, 33, 93, 153, 213, 53, 113, 173, 233,
+ 17, 77, 137, 197, 37, 97, 157, 217, 57, 117, 177, 237,
+ 2, 62, 122, 182, 22, 82, 142, 202, 42, 102, 162, 222,
+ 6, 66, 126, 186, 26, 86, 146, 206, 46, 106, 166, 226,
+ 10, 70, 130, 190, 30, 90, 150, 210, 50, 110, 170, 230,
+ 14, 74, 134, 194, 34, 94, 154, 214, 54, 114, 174, 234,
+ 18, 78, 138, 198, 38, 98, 158, 218, 58, 118, 178, 238,
+ 3, 63, 123, 183, 23, 83, 143, 203, 43, 103, 163, 223,
+ 7, 67, 127, 187, 27, 87, 147, 207, 47, 107, 167, 227,
+ 11, 71, 131, 191, 31, 91, 151, 211, 51, 111, 171, 231,
+ 15, 75, 135, 195, 35, 95, 155, 215, 55, 115, 175, 235,
+ 19, 79, 139, 199, 39, 99, 159, 219, 59, 119, 179, 239
+};
+
+/* Cosine table in Q14 */
+const WebRtc_Word16 kCosTabFfftQ14[240] = {
+ 16384, 16378, 16362, 16333, 16294, 16244, 16182, 16110, 16026, 15931, 15826, 15709,
+ 15582, 15444, 15296, 15137, 14968, 14788, 14598, 14399, 14189, 13970, 13741, 13502,
+ 13255, 12998, 12733, 12458, 12176, 11885, 11585, 11278, 10963, 10641, 10311, 9974,
+ 9630, 9280, 8923, 8561, 8192, 7818, 7438, 7053, 6664, 6270, 5872, 5469,
+ 5063, 4653, 4240, 3825, 3406, 2986, 2563, 2139, 1713, 1285, 857, 429,
+ 0, -429, -857, -1285, -1713, -2139, -2563, -2986, -3406, -3825, -4240, -4653,
+ -5063, -5469, -5872, -6270, -6664, -7053, -7438, -7818, -8192, -8561, -8923, -9280,
+ -9630, -9974, -10311, -10641, -10963, -11278, -11585, -11885, -12176, -12458, -12733, -12998,
+ -13255, -13502, -13741, -13970, -14189, -14399, -14598, -14788, -14968, -15137, -15296, -15444,
+ -15582, -15709, -15826, -15931, -16026, -16110, -16182, -16244, -16294, -16333, -16362, -16378,
+ -16384, -16378, -16362, -16333, -16294, -16244, -16182, -16110, -16026, -15931, -15826, -15709,
+ -15582, -15444, -15296, -15137, -14968, -14788, -14598, -14399, -14189, -13970, -13741, -13502,
+ -13255, -12998, -12733, -12458, -12176, -11885, -11585, -11278, -10963, -10641, -10311, -9974,
+ -9630, -9280, -8923, -8561, -8192, -7818, -7438, -7053, -6664, -6270, -5872, -5469,
+ -5063, -4653, -4240, -3825, -3406, -2986, -2563, -2139, -1713, -1285, -857, -429,
+ 0, 429, 857, 1285, 1713, 2139, 2563, 2986, 3406, 3825, 4240, 4653,
+ 5063, 5469, 5872, 6270, 6664, 7053, 7438, 7818, 8192, 8561, 8923, 9280,
+ 9630, 9974, 10311, 10641, 10963, 11278, 11585, 11885, 12176, 12458, 12733, 12998,
+ 13255, 13502, 13741, 13970, 14189, 14399, 14598, 14788, 14968, 15137, 15296, 15444,
+ 15582, 15709, 15826, 15931, 16026, 16110, 16182, 16244, 16294, 16333, 16362, 16378
+};
+
+
+
+/* Uses 16x16 mul, without rounding, which is faster. Uses WEBRTC_SPL_MUL_16_16_RSFT */
+WebRtc_Word16 WebRtcIsacfix_FftRadix16Fastest(WebRtc_Word16 RexQx[], WebRtc_Word16 ImxQx[], WebRtc_Word16 iSign) {
+
+ WebRtc_Word16 dd, ee, ff, gg, hh, ii;
+ WebRtc_Word16 k0, k1, k2, k3, k4, kk;
+ WebRtc_Word16 tmp116, tmp216;
+
+ WebRtc_Word16 ccc1Q14, ccc2Q14, ccc3Q14, sss1Q14, sss2Q14, sss3Q14;
+ WebRtc_Word16 sss60Q14, ccc72Q14, sss72Q14;
+ WebRtc_Word16 aaQx, ajQx, akQx, ajmQx, ajpQx, akmQx, akpQx;
+ WebRtc_Word16 bbQx, bjQx, bkQx, bjmQx, bjpQx, bkmQx, bkpQx;
+
+ WebRtc_Word16 ReDATAQx[240], ImDATAQx[240];
+
+ sss60Q14 = kCosTabFfftQ14[20];
+ ccc72Q14 = kCosTabFfftQ14[48];
+ sss72Q14 = kCosTabFfftQ14[12];
+
+ if (iSign < 0) {
+ sss72Q14 = -sss72Q14;
+ sss60Q14 = -sss60Q14;
+ }
+ /* Complexity is: 10 cycles */
+
+ /* compute fourier transform */
+
+ // transform for factor of 4
+ for (kk=0; kk<60; kk++) {
+ k0 = kk;
+ k1 = k0 + 60;
+ k2 = k1 + 60;
+ k3 = k2 + 60;
+
+ akpQx = RexQx[k0] + RexQx[k2];
+ akmQx = RexQx[k0] - RexQx[k2];
+ ajpQx = RexQx[k1] + RexQx[k3];
+ ajmQx = RexQx[k1] - RexQx[k3];
+ bkpQx = ImxQx[k0] + ImxQx[k2];
+ bkmQx = ImxQx[k0] - ImxQx[k2];
+ bjpQx = ImxQx[k1] + ImxQx[k3];
+ bjmQx = ImxQx[k1] - ImxQx[k3];
+
+ RexQx[k0] = akpQx + ajpQx;
+ ImxQx[k0] = bkpQx + bjpQx;
+ ajpQx = akpQx - ajpQx;
+ bjpQx = bkpQx - bjpQx;
+ if (iSign < 0) {
+ akpQx = akmQx + bjmQx;
+ bkpQx = bkmQx - ajmQx;
+ akmQx -= bjmQx;
+ bkmQx += ajmQx;
+ } else {
+ akpQx = akmQx - bjmQx;
+ bkpQx = bkmQx + ajmQx;
+ akmQx += bjmQx;
+ bkmQx -= ajmQx;
+ }
+
+ ccc1Q14 = kCosTabFfftQ14[kk];
+ ccc2Q14 = kCosTabFfftQ14[WEBRTC_SPL_MUL_16_16(2, kk)];
+ ccc3Q14 = kCosTabFfftQ14[WEBRTC_SPL_MUL_16_16(3, kk)];
+ sss1Q14 = kCosTabFfftQ14[kk+60];
+ sss2Q14 = kCosTabFfftQ14[WEBRTC_SPL_MUL_16_16(2, kk)+60];
+ sss3Q14 = kCosTabFfftQ14[WEBRTC_SPL_MUL_16_16(3, kk)+60];
+ if (iSign==1) {
+ sss1Q14 = -sss1Q14;
+ sss2Q14 = -sss2Q14;
+ sss3Q14 = -sss3Q14;
+ }
+
+ //Do several multiplications like Q14*Q16>>14 = Q16
+ // RexQ16[k1] = akpQ16 * ccc1Q14 - bkpQ16 * sss1Q14;
+ // RexQ16[k2] = ajpQ16 * ccc2Q14 - bjpQ16 * sss2Q14;
+ // RexQ16[k3] = akmQ16 * ccc3Q14 - bkmQ16 * sss3Q14;
+ // ImxQ16[k1] = akpQ16 * sss1Q14 + bkpQ16 * ccc1Q14;
+ // ImxQ16[k2] = ajpQ16 * sss2Q14 + bjpQ16 * ccc2Q14;
+ // ImxQ16[k3] = akmQ16 * sss3Q14 + bkmQ16 * ccc3Q14;
+
+ RexQx[k1] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, akpQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, bkpQx, 14); // 6 non-mul + 2 mul cycles, i.e. 8 cycles (6+2*7=20 cycles if 16x32mul)
+ RexQx[k2] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjpQx, 14);
+ RexQx[k3] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, akmQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, bkmQx, 14);
+ ImxQx[k1] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, akpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, bkpQx, 14);
+ ImxQx[k2] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14);
+ ImxQx[k3] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, akmQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, bkmQx, 14);
+ //This mul segment needs 6*8 = 48 cycles for 16x16 muls, but 6*20 = 120 cycles for 16x32 muls
+
+
+ }
+ /* Complexity is: 51+48 = 99 cycles for 16x16 muls, but 51+120 = 171 cycles for 16x32 muls*/
+
+ // transform for factor of 3
+ kk=0;
+ k1=20;
+ k2=40;
+
+ for (hh=0; hh<4; hh++) {
+ for (ii=0; ii<20; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+ ajQx = RexQx[k1] + RexQx[k2];
+ bjQx = ImxQx[k1] + ImxQx[k2];
+ RexQx[kk] = akQx + ajQx;
+ ImxQx[kk] = bkQx + bjQx;
+ tmp116 = WEBRTC_SPL_RSHIFT_W16(ajQx, 1);
+ tmp216 = WEBRTC_SPL_RSHIFT_W16(bjQx, 1);
+ akQx = akQx - tmp116;
+ bkQx = bkQx - tmp216;
+ tmp116 = RexQx[k1] - RexQx[k2];
+ tmp216 = ImxQx[k1] - ImxQx[k2];
+
+ ajQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp116, 14); // Q14*Qx>>14 = Qx
+ bjQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp216, 14); // Q14*Qx>>14 = Qx
+ RexQx[k1] = akQx - bjQx;
+ RexQx[k2] = akQx + bjQx;
+ ImxQx[k1] = bkQx + ajQx;
+ ImxQx[k2] = bkQx - ajQx;
+
+ kk++;
+ k1++;
+ k2++;
+ }
+ /* Complexity : (31+6)*20 = 740 cycles for 16x16 muls, but (31+18)*20 = 980 cycles for 16x32 muls*/
+ kk=kk+40;
+ k1=k1+40;
+ k2=k2+40;
+ }
+ /* Complexity : 4*(740+3) = 2972 cycles for 16x16 muls, but 4*(980+3) = 3932 cycles for 16x32 muls*/
+
+ /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+ Same code (duplicated) for both ii=2 and ii=3 */
+ kk = 1;
+ ee = 0;
+ ff = 0;
+
+ for (gg=0; gg<19; gg++) {
+ kk += 20;
+ ff = ff+4;
+ for (hh=0; hh<2; hh++) {
+ ee = ff + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(hh, ff);
+ dd = ee + 60;
+ ccc2Q14 = kCosTabFfftQ14[ee];
+ sss2Q14 = kCosTabFfftQ14[dd];
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+ for (ii=0; ii<4; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+ RexQx[kk] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) - // Q14*Qx>>14 = Qx
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+ ImxQx[kk] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) + // Q14*Qx>>14 = Qx
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+
+ kk += 60;
+ }
+ kk = kk - 220;
+ }
+ // Complexity: 2*(13+5+4*13+2) = 144 for 16x16 muls, but 2*(13+5+4*33+2) = 304 cycles for 16x32 muls
+ kk = kk - 59;
+ }
+ // Complexity: 19*144 = 2736 for 16x16 muls, but 19*304 = 5776 cycles for 16x32 muls
+
+ // transform for factor of 5
+ kk = 0;
+ ccc2Q14 = kCosTabFfftQ14[96];
+ sss2Q14 = kCosTabFfftQ14[84];
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+
+ for (hh=0; hh<4; hh++) {
+ for (ii=0; ii<12; ii++) {
+ k1 = kk + 4;
+ k2 = k1 + 4;
+ k3 = k2 + 4;
+ k4 = k3 + 4;
+
+ akpQx = RexQx[k1] + RexQx[k4];
+ akmQx = RexQx[k1] - RexQx[k4];
+ bkpQx = ImxQx[k1] + ImxQx[k4];
+ bkmQx = ImxQx[k1] - ImxQx[k4];
+ ajpQx = RexQx[k2] + RexQx[k3];
+ ajmQx = RexQx[k2] - RexQx[k3];
+ bjpQx = ImxQx[k2] + ImxQx[k3];
+ bjmQx = ImxQx[k2] - ImxQx[k3];
+ aaQx = RexQx[kk];
+ bbQx = ImxQx[kk];
+ RexQx[kk] = aaQx + akpQx + ajpQx;
+ ImxQx[kk] = bbQx + bkpQx + bjpQx;
+
+ akQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, akpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) + aaQx;
+ bkQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bkpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14) + bbQx;
+ ajQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, akmQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajmQx, 14);
+ bjQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bkmQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjmQx, 14);
+ // 32+4*8=64 or 32+4*20=112
+
+ RexQx[k1] = akQx - bjQx;
+ RexQx[k4] = akQx + bjQx;
+ ImxQx[k1] = bkQx + ajQx;
+ ImxQx[k4] = bkQx - ajQx;
+
+ akQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, ajpQx, 14) + aaQx;
+ bkQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkpQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bjpQx, 14) + bbQx;
+ ajQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akmQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, ajmQx, 14);
+ bjQx = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkmQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bjmQx, 14);
+ // 8+4*8=40 or 8+4*20=88
+
+ RexQx[k2] = akQx - bjQx;
+ RexQx[k3] = akQx + bjQx;
+ ImxQx[k2] = bkQx + ajQx;
+ ImxQx[k3] = bkQx - ajQx;
+
+ kk = k4 + 4;
+ }
+ // Complexity: 12*(64+40+10) = 1368 for 16x16 muls, but 12*(112+88+10) = 2520 cycles for 16x32 muls
+ kk -= 239;
+ }
+ // Complexity: 4*1368 = 5472 for 16x16 muls, but 4*2520 = 10080 cycles for 16x32 muls
+
+ /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+ Same code (duplicated) for both ii=2 and ii=3 */
+ kk = 1;
+ ee=0;
+
+ for (gg=0; gg<3; gg++) {
+ kk += 4;
+ dd = 12 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(12, gg);
+ ff = 0;
+ for (hh=0; hh<4; hh++) {
+ ff = ff+dd;
+ ee = ff+60;
+ for (ii=0; ii<12; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+
+ ccc2Q14 = kCosTabFfftQ14[ff];
+ sss2Q14 = kCosTabFfftQ14[ee];
+
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+
+ RexQx[kk] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) -
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+ ImxQx[kk] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) +
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+ kk += 20;
+ }
+ kk = kk - 236;
+ // Complexity: 12*(12+12) = 288 for 16x16 muls, but 12*(12+32) = 528 cycles for 16x32 muls
+ }
+ kk = kk - 19;
+ // Complexity: 4*288+6 for 16x16 muls, but 4*528+6 cycles for 16x32 muls
+ }
+ // Complexity: 3*4*288+6 = 3462 for 16x16 muls, but 3*4*528+6 = 6342 cycles for 16x32 muls
+
+
+ // last transform for factor of 4 */
+ for (kk=0; kk<240; kk=kk+4) {
+ k1 = kk + 1;
+ k2 = k1 + 1;
+ k3 = k2 + 1;
+
+ akpQx = RexQx[kk] + RexQx[k2];
+ akmQx = RexQx[kk] - RexQx[k2];
+ ajpQx = RexQx[k1] + RexQx[k3];
+ ajmQx = RexQx[k1] - RexQx[k3];
+ bkpQx = ImxQx[kk] + ImxQx[k2];
+ bkmQx = ImxQx[kk] - ImxQx[k2];
+ bjpQx = ImxQx[k1] + ImxQx[k3];
+ bjmQx = ImxQx[k1] - ImxQx[k3];
+ RexQx[kk] = akpQx + ajpQx;
+ ImxQx[kk] = bkpQx + bjpQx;
+ ajpQx = akpQx - ajpQx;
+ bjpQx = bkpQx - bjpQx;
+ if (iSign < 0) {
+ akpQx = akmQx + bjmQx;
+ bkpQx = bkmQx - ajmQx;
+ akmQx -= bjmQx;
+ bkmQx += ajmQx;
+ } else {
+ akpQx = akmQx - bjmQx;
+ bkpQx = bkmQx + ajmQx;
+ akmQx += bjmQx;
+ bkmQx -= ajmQx;
+ }
+ RexQx[k1] = akpQx;
+ RexQx[k2] = ajpQx;
+ RexQx[k3] = akmQx;
+ ImxQx[k1] = bkpQx;
+ ImxQx[k2] = bjpQx;
+ ImxQx[k3] = bkmQx;
+ }
+ // Complexity: 60*45 = 2700 for 16x16 muls, but 60*45 = 2700 cycles for 16x32 muls
+
+ /* permute the results to normal order */
+ for (ii=0; ii<240; ii++) {
+ ReDATAQx[ii]=RexQx[ii];
+ ImDATAQx[ii]=ImxQx[ii];
+ }
+ // Complexity: 240*2=480 cycles
+
+ for (ii=0; ii<240; ii++) {
+ RexQx[ii]=ReDATAQx[kSortTabFft[ii]];
+ ImxQx[ii]=ImDATAQx[kSortTabFft[ii]];
+ }
+ // Complexity: 240*2*2=960 cycles
+
+ // Total complexity:
+ // 16x16 16x32
+ // Complexity: 10 10
+ // Complexity: 99 171
+ // Complexity: 2972 3932
+ // Complexity: 2736 5776
+ // Complexity: 5472 10080
+ // Complexity: 3462 6342
+ // Complexity: 2700 2700
+ // Complexity: 480 480
+ // Complexity: 960 960
+ // =======================
+ // 18891 30451
+ //
+ // If this FFT is called 2 time each frame, i.e. 67 times per second, it will correspond to
+ // a C54 complexity of 67*18891/1000000 = 1.27 MIPS with 16x16-muls, and 67*30451/1000000 =
+ // = 2.04 MIPS with 16x32-muls. Note that this routine somtimes is called 6 times during the
+ // encoding of a frame, i.e. the max complexity would be 7/2*1.27 = 4.4 MIPS for the 16x16 mul case.
+
+
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/fft.h b/src/modules/audio_coding/codecs/isac/fix/source/fft.h
new file mode 100644
index 0000000..efa116e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/fft.h
@@ -0,0 +1,41 @@
+/*
+ * 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:
+ * fft.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_FIX_SOURCE_FFT_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_
+
+
+#include "structs.h"
+
+
+WebRtc_Word16 WebRtcIsacfix_FftRadix16Fastest(WebRtc_Word16 RexQx[], WebRtc_Word16 ImxQx[], WebRtc_Word16 iSign);
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
new file mode 100644
index 0000000..d5d9efb
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+
+#include "typedefs.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Arguments:
+ * io: Input/output, in Q0.
+ * len: Input, sample length.
+ * coefficient: Input.
+ * state: Input/output, filter state, in Q4.
+ */
+void WebRtcIsacfix_HighpassFilterFixDec32(int16_t *io,
+ int16_t len,
+ const int16_t *coefficient,
+ int32_t *state);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif
+/* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
new file mode 100644
index 0000000..732611b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/*
+ * filterbank_tables.c
+ *
+ * This file contains variables that are used in
+ * filterbanks.c
+ *
+ */
+
+#include "filterbank_tables.h"
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.94895953203325f, 0.94984516000000f,
+ * -0.05101826139794f, 0.05015484000000f};
+ */
+const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8] = {
+ 16189, -31932, /* Q30 lo/hi pair */
+ 17243, 15562, /* Q30 lo/hi pair */
+ -17186, -26748, /* Q35 lo/hi pair */
+ -27476, 26296 /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.99701049409000f, 0.99714204490000f,
+ * 0.01701049409000f, -0.01704204490000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8] = {
+ -1306, -32719, /* Q30 lo/hi pair */
+ 11486, 16337, /* Q30 lo/hi pair */
+ 26078, 8918, /* Q35 lo/hi pair */
+ 3956, -8935 /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.98645294509837f, 0.98672435560000f,
+ * 0.00645294509837f, -0.00662435560000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8] = {
+ -2953, -32546, /* Q30 lo/hi pair */
+ 32233, 16166, /* Q30 lo/hi pair */
+ 13217, 3383, /* Q35 lo/hi pair */
+ -4597, -3473 /* Q35 lo/hi pair */
+};
+
+/* The upper channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2] = {
+ 1137, 12537
+};
+
+/* The lower channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2] = {
+ 5059, 24379
+};
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
new file mode 100644
index 0000000..9a888e4
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ * filterbank_tables.h
+ *
+ * Header file for variables that are defined in
+ * filterbank_tables.c.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+
+#include "typedefs.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/********************* Coefficient Tables ************************/
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8];
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8];
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8];
+
+/* The upper channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2];
+
+/* The lower channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2];
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filterbanks.c b/src/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
new file mode 100644
index 0000000..949e7cf
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
@@ -0,0 +1,354 @@
+/*
+ * 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.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function
+ * WebRtcIsacfix_SplitAndFilter, and WebRtcIsacfix_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "codec.h"
+#include "filterbank_internal.h"
+#include "filterbank_tables.h"
+#include "settings.h"
+
+
+static void AllpassFilter2FixDec16(WebRtc_Word16 *InOut16, //Q0
+ const WebRtc_Word16 *APSectionFactors, //Q15
+ WebRtc_Word16 lengthInOut,
+ WebRtc_Word16 NumberOfSections,
+ WebRtc_Word32 *FilterState) //Q16
+{
+ int n, j;
+ WebRtc_Word32 a, b;
+
+ for (j=0; j<NumberOfSections; j++) {
+ for (n=0;n<lengthInOut;n++) {
+
+
+ a = WEBRTC_SPL_MUL_16_16(APSectionFactors[j], InOut16[n]); //Q15*Q0=Q15
+ a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16
+ b = WEBRTC_SPL_ADD_SAT_W32(a, FilterState[j]); //Q16+Q16=Q16
+ a = WEBRTC_SPL_MUL_16_16_RSFT(-APSectionFactors[j], (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16), 0); //Q15*Q0=Q15
+ FilterState[j] = WEBRTC_SPL_ADD_SAT_W32(WEBRTC_SPL_LSHIFT_W32(a,1), WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)InOut16[n],16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
+ InOut16[n] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0
+
+ }
+ }
+
+}
+
+
+void WebRtcIsacfix_HighpassFilterFixDec32(int16_t *io,
+ int16_t len,
+ const int16_t *coefficient,
+ int32_t *state)
+{
+ int k;
+ WebRtc_Word32 a1 = 0, b1 = 0, c = 0, in = 0;
+ WebRtc_Word32 a2 = 0, b2 = 0;
+ WebRtc_Word32 state0 = state[0];
+ WebRtc_Word32 state1 = state[1];
+
+ for (k=0; k<len; k++) {
+ in = (WebRtc_Word32)io[k];
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ {
+ int tmp_coeff0 = 0;
+ int tmp_coeff1 = 0;
+ __asm __volatile(
+ "ldr %[tmp_coeff0], [%[coeff]]\n\t"
+ "ldr %[tmp_coeff1], [%[coeff], #4]\n\t"
+ "smmulr %[a2], %[tmp_coeff0], %[state0]\n\t"
+ "smmulr %[b2], %[tmp_coeff1], %[state1]\n\t"
+ "ldr %[tmp_coeff0], [%[coeff], #8]\n\t"
+ "ldr %[tmp_coeff1], [%[coeff], #12]\n\t"
+ "smmulr %[a1], %[tmp_coeff0], %[state0]\n\t"
+ "smmulr %[b1], %[tmp_coeff1], %[state1]\n\t"
+ :[a2]"+r"(a2),
+ [b2]"+r"(b2),
+ [a1]"+r"(a1),
+ [b1]"+r"(b1),
+ [tmp_coeff0]"+r"(tmp_coeff0),
+ [tmp_coeff1]"+r"(tmp_coeff1)
+ :[coeff]"r"(coefficient),
+ [state0]"r"(state0),
+ [state1]"r"(state1)
+ );
+ }
+#else
+ /* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */
+ a1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[5], coefficient[4], state0);
+ b1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[7], coefficient[6], state1);
+
+ /* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
+ a2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[1], coefficient[0], state0);
+ b2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[3], coefficient[2], state1);
+#endif
+
+ c = ((WebRtc_Word32)in) + WEBRTC_SPL_RSHIFT_W32(a1+b1, 7); // Q0
+ io[k] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(c); // Write output as Q0.
+
+ c = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)in, 2) - a2 - b2; // In Q2.
+ c = (WebRtc_Word32)WEBRTC_SPL_SAT(536870911, c, -536870912);
+
+ state1 = state0;
+ state0 = WEBRTC_SPL_LSHIFT_W32(c, 2); // Write state as Q4
+ }
+ state[0] = state0;
+ state[1] = state1;
+}
+
+
+void WebRtcIsacfix_SplitAndFilter1(WebRtc_Word16 *pin,
+ WebRtc_Word16 *LP16,
+ WebRtc_Word16 *HP16,
+ PreFiltBankstr *prefiltdata)
+{
+ /* Function WebRtcIsacfix_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'. */
+
+ int k;
+
+ WebRtc_Word16 tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD];
+ WebRtc_Word16 tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD];
+ WebRtc_Word32 tmpState[WEBRTC_SPL_MUL_16_16(2,(QORDER-1))]; /* 4 */
+
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
+
+
+ /* First Channel */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tempin_ch1[QLOOKAHEAD + k] = pin[1+WEBRTC_SPL_MUL_16_16(2, k)];
+ }
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch1[k]=prefiltdata->INLABUF1_fix[k];
+ prefiltdata->INLABUF1_fix[k]=pin[FRAMESAMPLES+1-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(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<FRAMESAMPLES/2;k++) {
+ tempin_ch2[QLOOKAHEAD+k] = pin[WEBRTC_SPL_MUL_16_16(2, k)];
+ }
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch2[k]=prefiltdata->INLABUF2_fix[k];
+ prefiltdata->INLABUF2_fix[k]=pin[FRAMESAMPLES-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(2, k)];
+ }
+
+
+ /*obtain polyphase components by forward all-pass filtering through each channel */
+ /* The all pass filtering automatically updates the filter states which are exported in the
+ prefiltdata structure */
+ AllpassFilter2FixDec16(tempin_ch1,WebRtcIsacfix_kUpperApFactorsQ15, FRAMESAMPLES/2 , NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_fix);
+ AllpassFilter2FixDec16(tempin_ch2,WebRtcIsacfix_kLowerApFactorsQ15, FRAMESAMPLES/2 , NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_fix);
+
+ for (k=0;k<WEBRTC_SPL_MUL_16_16(2, (QORDER-1));k++)
+ tmpState[k] = prefiltdata->INSTAT1_fix[k];
+ AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2,WebRtcIsacfix_kUpperApFactorsQ15, QLOOKAHEAD , NUMBEROFCHANNELAPSECTIONS, tmpState);
+ for (k=0;k<WEBRTC_SPL_MUL_16_16(2, (QORDER-1));k++)
+ tmpState[k] = prefiltdata->INSTAT2_fix[k];
+ AllpassFilter2FixDec16(tempin_ch2 + FRAMESAMPLES/2,WebRtcIsacfix_kLowerApFactorsQ15, QLOOKAHEAD , NUMBEROFCHANNELAPSECTIONS, tmpState);
+
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+ for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) {
+ WebRtc_Word32 tmp1, tmp2, tmp3;
+ tmp1 = (WebRtc_Word32)tempin_ch1[k]; // Q0 -> Q0
+ tmp2 = (WebRtc_Word32)tempin_ch2[k]; // Q0 -> Q0
+ tmp3 = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
+ LP16[k] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
+ tmp3 = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
+ HP16[k] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
+ }
+
+}/*end of WebRtcIsacfix_SplitAndFilter */
+
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+
+/* Without lookahead */
+void WebRtcIsacfix_SplitAndFilter2(WebRtc_Word16 *pin,
+ WebRtc_Word16 *LP16,
+ WebRtc_Word16 *HP16,
+ PreFiltBankstr *prefiltdata)
+{
+ /* Function WebRtcIsacfix_SplitAndFilter2 */
+ /* This function creates low-pass and high-pass decimated versions of part of
+ the input signal. */
+
+ int k;
+
+ WebRtc_Word16 tempin_ch1[FRAMESAMPLES/2];
+ WebRtc_Word16 tempin_ch2[FRAMESAMPLES/2];
+
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
+
+
+ /* First Channel */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tempin_ch1[k] = pin[1+WEBRTC_SPL_MUL_16_16(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<FRAMESAMPLES/2;k++) {
+ tempin_ch2[k] = pin[WEBRTC_SPL_MUL_16_16(2, k)];
+ }
+
+
+ /*obtain polyphase components by forward all-pass filtering through each channel */
+ /* The all pass filtering automatically updates the filter states which are exported in the
+ prefiltdata structure */
+ AllpassFilter2FixDec16(tempin_ch1,WebRtcIsacfix_kUpperApFactorsQ15, FRAMESAMPLES/2 , NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_fix);
+ AllpassFilter2FixDec16(tempin_ch2,WebRtcIsacfix_kLowerApFactorsQ15, FRAMESAMPLES/2 , NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_fix);
+
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ WebRtc_Word32 tmp1, tmp2, tmp3;
+ tmp1 = (WebRtc_Word32)tempin_ch1[k]; // Q0 -> Q0
+ tmp2 = (WebRtc_Word32)tempin_ch2[k]; // Q0 -> Q0
+ tmp3 = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
+ LP16[k] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
+ tmp3 = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
+ HP16[k] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
+ }
+
+}/*end of WebRtcIsacfix_SplitAndFilter */
+
+#endif
+
+
+
+//////////////////////////////////////////////////////////
+////////// Combining
+/* Function WebRtcIsacfix_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+ length FRAMESAMPLES/2 input low-pass and
+ high-pass signals and creates a reconstructed fullband
+ output signal of length FRAMESAMPLES. WebRtcIsacfix_FilterAndCombine
+ is the sibling function of WebRtcIsacfix_SplitAndFilter */
+/* INPUTS:
+ inLP: a length FRAMESAMPLES/2 array of input low-pass
+ samples.
+ inHP: a length FRAMESAMPLES/2 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 WebRtcIsacfix_FilterAndCombine1(WebRtc_Word16 *tempin_ch1,
+ WebRtc_Word16 *tempin_ch2,
+ WebRtc_Word16 *out16,
+ PostFiltBankstr *postfiltdata)
+{
+ int k;
+ WebRtc_Word16 in[FRAMESAMPLES];
+
+ /* 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.*/
+
+ AllpassFilter2FixDec16(tempin_ch1, WebRtcIsacfix_kLowerApFactorsQ15, FRAMESAMPLES/2, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_fix);
+
+ /* 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 (kUpperApFactors) are used to filter this new lower channel signal */
+
+ AllpassFilter2FixDec16(tempin_ch2, WebRtcIsacfix_kUpperApFactorsQ15, FRAMESAMPLES/2, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_fix);
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k];
+ in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k];
+ }
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
+ WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ out16[k] = in[k];
+ }
+}
+
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+/* Function WebRtcIsacfix_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+ length len/2 input low-pass and
+ high-pass signals and creates a reconstructed fullband
+ output signal of length len. WebRtcIsacfix_FilterAndCombine
+ is the sibling function of WebRtcIsacfix_SplitAndFilter */
+/* INPUTS:
+ inLP: a length len/2 array of input low-pass
+ samples.
+ inHP: a length len/2 array of input high-pass
+ samples.
+ postfiltdata: input data structure containing the filterbank
+ states from the previous decoding iteration.
+ OUTPUTS:
+ Out: a length len 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 WebRtcIsacfix_FilterAndCombine2(WebRtc_Word16 *tempin_ch1,
+ WebRtc_Word16 *tempin_ch2,
+ WebRtc_Word16 *out16,
+ PostFiltBankstr *postfiltdata,
+ WebRtc_Word16 len)
+{
+ int k;
+ WebRtc_Word16 in[FRAMESAMPLES];
+
+ /* 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.*/
+
+ AllpassFilter2FixDec16(tempin_ch1, WebRtcIsacfix_kLowerApFactorsQ15,(WebRtc_Word16) (len/2), NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_fix);
+
+ /* 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 (kUpperApFactors) are used to filter this new lower channel signal */
+
+ AllpassFilter2FixDec16(tempin_ch2, WebRtcIsacfix_kUpperApFactorsQ15, (WebRtc_Word16) (len/2), NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_fix);
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;k<len/2;k++) {
+ in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k];
+ in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k];
+ }
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
+ WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
+
+ for (k=0;k<len;k++) {
+ out16[k] = in[k];
+ }
+}
+
+#endif
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filters.c b/src/modules/audio_coding/codecs/isac/fix/source/filters.c
new file mode 100644
index 0000000..6ee0477
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filters.c
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+/*
+ * filters.c
+ *
+ * This file contains function WebRtcIsacfix_AutocorrC,
+ * AllpassFilterForDec32, and WebRtcIsacfix_DecimateAllpass32
+ *
+ */
+
+#include <string.h>
+
+#include "pitch_estimator.h"
+#include "lpc_masking_model.h"
+#include "codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrC(WebRtc_Word32* __restrict r,
+ const WebRtc_Word16* __restrict x,
+ WebRtc_Word16 N,
+ WebRtc_Word16 order,
+ WebRtc_Word16* __restrict scale) {
+ int i = 0;
+ int j = 0;
+ int16_t scaling = 0;
+ int32_t sum = 0;
+ uint32_t temp = 0;
+ int64_t prod = 0;
+
+ // Calculate r[0].
+ for (i = 0; i < N; i++) {
+ prod += WEBRTC_SPL_MUL_16_16(x[i], x[i]);
+ }
+
+ // Calculate scaling (the value of shifting).
+ temp = (uint32_t)(prod >> 31);
+ if(temp == 0) {
+ scaling = 0;
+ } else {
+ scaling = 32 - WebRtcSpl_NormU32(temp);
+ }
+ r[0] = (int32_t)(prod >> scaling);
+
+ // Perform the actual correlation calculation.
+ for (i = 1; i < order + 1; i++) {
+ prod = 0;
+ for (j = 0; j < N - i; j++) {
+ prod += WEBRTC_SPL_MUL_16_16(x[j], x[i + j]);
+ }
+ sum = (int32_t)(prod >> scaling);
+ r[i] = sum;
+ }
+
+ *scale = scaling;
+
+ return(order + 1);
+}
+
+static const WebRtc_Word32 kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
+static const WebRtc_Word32 kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
+
+
+static void AllpassFilterForDec32(WebRtc_Word16 *InOut16, //Q0
+ const WebRtc_Word32 *APSectionFactors, //Q15
+ WebRtc_Word16 lengthInOut,
+ WebRtc_Word32 *FilterState) //Q16
+{
+ int n, j;
+ WebRtc_Word32 a, b;
+
+ for (j=0; j<ALLPASSSECTIONS; j++) {
+ for (n=0;n<lengthInOut;n+=2){
+ a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
+ a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16
+ b = WEBRTC_SPL_ADD_SAT_W32(a, FilterState[j]); //Q16+Q16=Q16
+ a = WEBRTC_SPL_MUL_16_32_RSFT16(
+ (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16),
+ -APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
+ FilterState[j] = WEBRTC_SPL_ADD_SAT_W32(
+ WEBRTC_SPL_LSHIFT_W32(a,1),
+ WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
+ InOut16[n] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0
+ }
+ }
+}
+
+
+
+
+void WebRtcIsacfix_DecimateAllpass32(const WebRtc_Word16 *in,
+ WebRtc_Word32 *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ WebRtc_Word16 N, /* number of input samples */
+ WebRtc_Word16 *out) /* array of size N/2 */
+{
+ int n;
+ WebRtc_Word16 data_vec[PITCH_FRAME_LEN];
+
+ /* copy input */
+ memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), (N-1)));
+
+
+ data_vec[0] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)],16); //the z^(-1) state
+ state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)] = WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)in[N-1],16);
+
+
+
+ AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in);
+ AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS);
+
+ for (n=0;n<N/2;n++) {
+ out[n]=WEBRTC_SPL_ADD_SAT_W16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)], data_vec[WEBRTC_SPL_MUL_16_16(2, n)+1]);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/filters_neon.c b/src/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
new file mode 100644
index 0000000..93143fe
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+/*
+ * filters_neon.c
+ *
+ * This file contains function WebRtcIsacfix_AutocorrNeon, optimized for
+ * ARM Neon platform.
+ *
+ */
+
+#include <arm_neon.h>
+#include <assert.h>
+
+#include "codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrNeon(
+ WebRtc_Word32* __restrict r,
+ const WebRtc_Word16* __restrict x,
+ WebRtc_Word16 N,
+ WebRtc_Word16 order,
+ WebRtc_Word16* __restrict scale) {
+
+ // The 1st for loop assumed N % 4 == 0.
+ assert(N % 4 == 0);
+
+ int i = 0;
+ int zeros_low = 0;
+ int zeros_high = 0;
+ int16_t scaling = 0;
+ int32_t sum = 0;
+
+ // Step 1, calculate r[0] and how much scaling is needed.
+
+ int16x4_t reg16x4;
+ int64x1_t reg64x1a;
+ int64x1_t reg64x1b;
+ int32x4_t reg32x4;
+ int64x2_t reg64x2 = vdupq_n_s64(0); // zeros
+
+ // Loop over the samples and do:
+ // sum += WEBRTC_SPL_MUL_16_16(x[i], x[i]);
+ for (i = 0; i < N; i += 4) {
+ reg16x4 = vld1_s16(&x[i]);
+ reg32x4 = vmull_s16(reg16x4, reg16x4);
+ reg64x2 = vpadalq_s32(reg64x2, reg32x4);
+ }
+ reg64x1a = vget_low_s64(reg64x2);
+ reg64x1b = vget_high_s64(reg64x2);
+ reg64x1a = vadd_s64(reg64x1a, reg64x1b);
+
+ // Calculate the value of shifting (scaling).
+ __asm__ __volatile__(
+ "vmov %[z_l], %[z_h], %P[reg]\n\t"
+ "clz %[z_l], %[z_l]\n\t"
+ "clz %[z_h], %[z_h]\n\t"
+ :[z_l]"+r"(zeros_low),
+ [z_h]"+r"(zeros_high)
+ :[reg]"w"(reg64x1a)
+ );
+ if (zeros_high != 32) {
+ scaling = (32 - zeros_high + 1);
+ } else if (zeros_low == 0) {
+ scaling = 1;
+ }
+ reg64x1b = -scaling;
+ reg64x1a = vshl_s64(reg64x1a, reg64x1b);
+
+ // Record the result.
+ r[0] = (int32_t)vget_lane_s64(reg64x1a, 0);
+
+
+ // Step 2, perform the actual correlation calculation.
+
+ /* Original C code (for the rest of the function):
+ for (i = 1; i < order + 1; i++) {
+ prod = 0;
+ for (j = 0; j < N - i; j++) {
+ prod += WEBRTC_SPL_MUL_16_16(x[j], x[i + j]);
+ }
+ sum = (int32_t)(prod >> scaling);
+ r[i] = sum;
+ }
+ */
+
+ for (i = 1; i < order + 1; i++) {
+ int32_t prod_lower = 0;
+ int32_t prod_upper = 0;
+ const int16_t* ptr0 = &x[0];
+ const int16_t* ptr1 = &x[i];
+ int32_t tmp = 0;
+
+ // Initialize the sum (q9) to zero.
+ __asm__ __volatile__("vmov.i32 q9, #0\n\t":::"q9");
+
+ // Calculate the major block of the samples (a multiple of 8).
+ for (; ptr0 < &x[N - i - 7];) {
+ __asm__ __volatile__(
+ "vld1.16 {d20, d21}, [%[ptr0]]!\n\t"
+ "vld1.16 {d22, d23}, [%[ptr1]]!\n\t"
+ "vmull.s16 q12, d20, d22\n\t"
+ "vmull.s16 q13, d21, d23\n\t"
+ "vpadal.s32 q9, q12\n\t"
+ "vpadal.s32 q9, q13\n\t"
+
+ // Specify constraints.
+ :[ptr0]"+r"(ptr0),
+ [ptr1]"+r"(ptr1)
+ :
+ :"d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27"
+ );
+ }
+
+ // Calculate the rest of the samples.
+ for (; ptr0 < &x[N - i]; ptr0++, ptr1++) {
+ __asm__ __volatile__(
+ "smulbb %[tmp], %[ptr0], %[ptr1]\n\t"
+ "adds %[prod_lower], %[prod_lower], %[tmp]\n\t"
+ "adc %[prod_upper], %[prod_upper], %[tmp], asr #31\n\t"
+
+ // Specify constraints.
+ :[prod_lower]"+r"(prod_lower),
+ [prod_upper]"+r"(prod_upper),
+ [tmp]"+r"(tmp)
+ :[ptr0]"r"(*ptr0),
+ [ptr1]"r"(*ptr1)
+ );
+ }
+
+ // Sum the results up, and do shift.
+ __asm__ __volatile__(
+ "vadd.i64 d18, d19\n\t"
+ "vmov.32 d17[0], %[prod_lower]\n\t"
+ "vmov.32 d17[1], %[prod_upper]\n\t"
+ "vadd.i64 d17, d18\n\t"
+ "mov %[tmp], %[scaling], asr #31\n\t"
+ "vmov.32 d16, %[scaling], %[tmp]\n\t"
+ "vshl.s64 d17, d16\n\t"
+ "vmov.32 %[sum], d17[0]\n\t"
+
+ // Specify constraints.
+ :[sum]"=r"(sum),
+ [tmp]"+r"(tmp)
+ :[prod_upper]"r"(prod_upper),
+ [prod_lower]"r"(prod_lower),
+ [scaling]"r"(-scaling)
+ :"d16", "d17", "d18", "d19"
+ );
+
+ // Record the result.
+ r[i] = sum;
+ }
+
+ // Record the result.
+ *scale = scaling;
+
+ return(order + 1);
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/initialize.c b/src/modules/audio_coding/codecs/isac/fix/source/initialize.c
new file mode 100644
index 0000000..4d11af5
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/initialize.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.
+ */
+
+/*
+ * initialize.c
+ *
+ * Internal initfunctions
+ *
+ */
+
+#include "codec.h"
+#include "structs.h"
+#include "pitch_estimator.h"
+
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc *maskdata) {
+
+ int k;
+
+ for (k = 0; k < WINLEN; k++) {
+ maskdata->DataBufferLoQ0[k] = (WebRtc_Word16) 0;
+ maskdata->DataBufferHiQ0[k] = (WebRtc_Word16) 0;
+ }
+ for (k = 0; k < ORDERLO+1; k++) {
+ maskdata->CorrBufLoQQ[k] = (WebRtc_Word32) 0;
+ maskdata->CorrBufLoQdom[k] = 0;
+
+ maskdata->PreStateLoGQ15[k] = 0;
+
+ }
+ for (k = 0; k < ORDERHI+1; k++) {
+ maskdata->CorrBufHiQQ[k] = (WebRtc_Word32) 0;
+ maskdata->CorrBufHiQdom[k] = 0;
+ maskdata->PreStateHiGQ15[k] = 0;
+ }
+
+ maskdata->OldEnergy = 10;
+
+ return;
+}
+
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec *maskdata) {
+
+ int k;
+
+ for (k = 0; k < ORDERLO+1; k++)
+ {
+ maskdata->PostStateLoGQ0[k] = 0;
+ }
+ for (k = 0; k < ORDERHI+1; k++)
+ {
+ maskdata->PostStateHiGQ0[k] = 0;
+ }
+
+ maskdata->OldEnergy = 10;
+
+ return;
+}
+
+
+
+
+
+
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr *prefiltdata)
+{
+ int k;
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ prefiltdata->INLABUF1_fix[k] = 0;
+ prefiltdata->INLABUF2_fix[k] = 0;
+ }
+ for (k = 0; k < WEBRTC_SPL_MUL_16_16(2,(QORDER-1)); k++) {
+
+ prefiltdata->INSTAT1_fix[k] = 0;
+ prefiltdata->INSTAT2_fix[k] = 0;
+ }
+
+ /* High pass filter states */
+ prefiltdata->HPstates_fix[0] = 0;
+ prefiltdata->HPstates_fix[1] = 0;
+
+ return;
+}
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+ int k;
+
+ for (k = 0; k < WEBRTC_SPL_MUL_16_16(2, POSTQORDER); k++) {
+
+ postfiltdata->STATE_0_LOWER_fix[k] = 0;
+ postfiltdata->STATE_0_UPPER_fix[k] = 0;
+ }
+
+ /* High pass filter states */
+
+ postfiltdata->HPstates1_fix[0] = 0;
+ postfiltdata->HPstates1_fix[1] = 0;
+
+ postfiltdata->HPstates2_fix[0] = 0;
+ postfiltdata->HPstates2_fix[1] = 0;
+
+ return;
+}
+
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr *pitchfiltdata)
+{
+ int k;
+
+ for (k = 0; k < PITCH_BUFFSIZE; k++)
+ pitchfiltdata->ubufQQ[k] = 0;
+ for (k = 0; k < (PITCH_DAMPORDER); k++)
+ pitchfiltdata->ystateQQ[k] = 0;
+
+ pitchfiltdata->oldlagQ7 = 6400; /* 50.0 in Q7 */
+ pitchfiltdata->oldgainQ12 = 0;
+}
+
+void WebRtcIsacfix_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_buffer16[k] = 0;
+ }
+ for (k = 0; k < WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)+1; k++) {
+ State->decimator_state32[k] = 0;
+ }
+
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = 0;
+
+ WebRtcIsacfix_InitPitchFilter(&(State->PFstr_wght));
+
+ WebRtcIsacfix_InitPitchFilter(&(State->PFstr));
+}
+
+
+void WebRtcIsacfix_InitPlc( PLCstr *State )
+{
+ State->decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX;
+ State->decayCoeffNoise = WEBRTC_SPL_WORD16_MAX;
+
+ State->used = PLC_WAS_USED;
+
+ WebRtcSpl_ZerosArrayW16(State->overlapLP, RECOVERY_OVERLAP);
+ WebRtcSpl_ZerosArrayW16(State->lofilt_coefQ15, ORDERLO);
+ WebRtcSpl_ZerosArrayW16(State->hifilt_coefQ15, ORDERHI );
+
+ State->AvgPitchGain_Q12 = 0;
+ State->lastPitchGain_Q12 = 0;
+ State->lastPitchLag_Q7 = 0;
+ State->gain_lo_hiQ17[0]=State->gain_lo_hiQ17[1] = 0;
+ WebRtcSpl_ZerosArrayW16(State->prevPitchInvIn, FRAMESAMPLES/2);
+ WebRtcSpl_ZerosArrayW16(State->prevPitchInvOut, PITCH_MAX_LAG + 10 );
+ WebRtcSpl_ZerosArrayW32(State->prevHP, PITCH_MAX_LAG + 10 );
+ State->pitchCycles = 0;
+ State->A = 0;
+ State->B = 0;
+ State->pitchIndex = 0;
+ State->stretchLag = 240;
+ State->seed = 4447;
+
+
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c
new file mode 100644
index 0000000..8786b12
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c
@@ -0,0 +1,1551 @@
+/*
+ * 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.
+ */
+
+/*
+ * isacfix.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
+
+#include <stdlib.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "system_wrappers/interface/cpu_features_wrapper.h"
+
+
+/**************************************************************************
+ * WebRtcIsacfix_AssignSize(...)
+ *
+ * Functions used when malloc is not allowed
+ * Returns number of bytes needed to allocate for iSAC struct.
+ *
+ */
+
+WebRtc_Word16 WebRtcIsacfix_AssignSize(int *sizeinbytes) {
+ *sizeinbytes=sizeof(ISACFIX_SubStruct)*2/sizeof(WebRtc_Word16);
+ return(0);
+}
+
+/***************************************************************************
+ * WebRtcIsacfix_Assign(...)
+ *
+ * Functions used when malloc is not allowed
+ * Place struct at given address
+ *
+ * If successful, Return 0, else Return -1
+ */
+
+WebRtc_Word16 WebRtcIsacfix_Assign(ISACFIX_MainStruct **inst, void *ISACFIX_inst_Addr) {
+ if (ISACFIX_inst_Addr!=NULL) {
+ *inst = (ISACFIX_MainStruct*)ISACFIX_inst_Addr;
+ (*(ISACFIX_SubStruct**)inst)->errorcode = 0;
+ (*(ISACFIX_SubStruct**)inst)->initflag = 0;
+ (*(ISACFIX_SubStruct**)inst)->ISACenc_obj.SaveEnc_ptr = NULL;
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+
+#ifndef ISACFIX_NO_DYNAMIC_MEM
+
+/****************************************************************************
+ * WebRtcIsacfix_Create(...)
+ *
+ * This function creates a 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 WebRtcIsacfix_Create(ISACFIX_MainStruct **ISAC_main_inst)
+{
+ ISACFIX_SubStruct *tempo;
+ tempo = malloc(1 * sizeof(ISACFIX_SubStruct));
+ *ISAC_main_inst = (ISACFIX_MainStruct *)tempo;
+ if (*ISAC_main_inst!=NULL) {
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->errorcode = 0;
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->initflag = 0;
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->ISACenc_obj.SaveEnc_ptr = NULL;
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Allocate memory for storing encoder data */
+ ISAC_inst->ISACenc_obj.SaveEnc_ptr = malloc(1 * sizeof(ISAC_SaveEncData_t));
+
+ if (ISAC_inst->ISACenc_obj.SaveEnc_ptr!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+
+#endif
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Free(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ free(ISAC_main_inst);
+ return(0);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Release memory */
+ free(ISAC_inst->ISACenc_obj.SaveEnc_ptr);
+
+ return(0);
+}
+
+/****************************************************************************
+ * WebRtcAecm_InitNeon(...)
+ *
+ * This function initializes function pointers for ARM Neon platform.
+ */
+
+#if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON)
+static void WebRtcIsacfix_InitNeon(void) {
+ WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrNeon;
+ WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopNeon;
+ WebRtcIsacfix_CalculateResidualEnergy =
+ WebRtcIsacfix_CalculateResidualEnergyNeon;
+}
+#endif
+
+/****************************************************************************
+ * WebRtcIsacfix_EncoderInit(...)
+ *
+ * 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.
+ * 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 WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 CodingMode)
+{
+ int k;
+ WebRtc_Word16 statusInit;
+ ISACFIX_SubStruct *ISAC_inst;
+
+ statusInit = 0;
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* flag encoder init */
+ ISAC_inst->initflag |= 2;
+
+ if (CodingMode == 0)
+ /* Adaptive mode */
+ ISAC_inst->ISACenc_obj.new_framelength = INITIAL_FRAMESAMPLES;
+ else if (CodingMode == 1)
+ /* Instantaneous mode */
+ ISAC_inst->ISACenc_obj.new_framelength = 480; /* default for I-mode */
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_CODING_MODE;
+ statusInit = -1;
+ }
+
+ ISAC_inst->CodingMode = CodingMode;
+
+ WebRtcIsacfix_InitMaskingEnc(&ISAC_inst->ISACenc_obj.maskfiltstr_obj);
+ WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACenc_obj.prefiltbankstr_obj);
+ WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACenc_obj.pitchfiltstr_obj);
+ WebRtcIsacfix_InitPitchAnalysis(&ISAC_inst->ISACenc_obj.pitchanalysisstr_obj);
+
+
+ WebRtcIsacfix_InitBandwidthEstimator(&ISAC_inst->bwestimator_obj);
+ WebRtcIsacfix_InitRateModel(&ISAC_inst->ISACenc_obj.rate_data_obj);
+
+
+ ISAC_inst->ISACenc_obj.buffer_index = 0;
+ ISAC_inst->ISACenc_obj.frame_nb = 0;
+ ISAC_inst->ISACenc_obj.BottleNeck = 32000; /* default for I-mode */
+ ISAC_inst->ISACenc_obj.MaxDelay = 10; /* default for I-mode */
+ ISAC_inst->ISACenc_obj.current_framesamples = 0;
+ ISAC_inst->ISACenc_obj.s2nr = 0;
+ ISAC_inst->ISACenc_obj.MaxBits = 0;
+ ISAC_inst->ISACenc_obj.bitstr_seed = 4447;
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = STREAM_MAXW16_30MS << 1;
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = STREAM_MAXW16_60MS << 1;
+ ISAC_inst->ISACenc_obj.maxPayloadBytes = STREAM_MAXW16_60MS << 1;
+ ISAC_inst->ISACenc_obj.maxRateInBytes = STREAM_MAXW16_30MS << 1;
+ ISAC_inst->ISACenc_obj.enforceFrameSize = 0;
+
+ /* Init the bistream data area to zero */
+ for (k=0; k<STREAM_MAXW16_60MS; k++){
+ ISAC_inst->ISACenc_obj.bitstr_obj.stream[k] = 0;
+ }
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj);
+#endif
+
+ // Initiaze function pointers.
+ WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
+ WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
+ WebRtcIsacfix_CalculateResidualEnergy =
+ WebRtcIsacfix_CalculateResidualEnergyC;
+
+#ifdef WEBRTC_DETECT_ARM_NEON
+ if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
+ WebRtcIsacfix_InitNeon();
+ }
+#elif defined(WEBRTC_ARCH_ARM_NEON)
+ WebRtcIsacfix_InitNeon();
+#endif
+
+ return statusInit;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_Word16 *speechIn,
+ WebRtc_Word16 *encoded)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ WebRtc_Word16 stream_len;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ stream_len = WebRtcIsacfix_EncodeImpl((WebRtc_Word16*)speechIn,
+ &ISAC_inst->ISACenc_obj,
+ &ISAC_inst->bwestimator_obj,
+ ISAC_inst->CodingMode);
+ if (stream_len<0) {
+ ISAC_inst->errorcode = - stream_len;
+ return -1;
+ }
+
+
+ /* convert from bytes to WebRtc_Word16 */
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0;k<(stream_len+1)>>1;k++) {
+ encoded[k] = (WebRtc_Word16)( ( (WebRtc_UWord16)(ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] >> 8 )
+ | (((ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] & 0x00FF) << 8));
+ }
+
+#else
+ WEBRTC_SPL_MEMCPY_W16(encoded, (ISAC_inst->ISACenc_obj.bitstr_obj).stream, (stream_len + 1)>>1);
+#endif
+
+
+
+ return stream_len;
+
+}
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncodeNb(...)
+ *
+ * This function encodes 10ms narrow band (8 kHz sampling) frame(s) and inserts
+ * it into a package. Input speech length has to be 80 samples (10ms). The encoder
+ * interpolates into wide-band (16 kHz sampling) buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 wide-band samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * 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
+ */
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+WebRtc_Word16 WebRtcIsacfix_EncodeNb(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_Word16 *speechIn,
+ WebRtc_Word16 *encoded)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ WebRtc_Word16 stream_len;
+ WebRtc_Word16 speechInWB[FRAMESAMPLES_10ms];
+ WebRtc_Word16 Vector_Word16_1[FRAMESAMPLES_10ms/2];
+ WebRtc_Word16 Vector_Word16_2[FRAMESAMPLES_10ms/2];
+
+ int k;
+
+
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+
+ /* Oversample to WB */
+
+ /* Form polyphase signals, and compensate for DC offset */
+ for (k=0;k<FRAMESAMPLES_10ms/2;k++) {
+ Vector_Word16_1[k] = speechIn[k] + 1;
+ Vector_Word16_2[k] = speechIn[k];
+ }
+ WebRtcIsacfix_FilterAndCombine2(Vector_Word16_1, Vector_Word16_2, speechInWB, &ISAC_inst->ISACenc_obj.interpolatorstr_obj, FRAMESAMPLES_10ms);
+
+
+ /* Encode WB signal */
+ stream_len = WebRtcIsacfix_EncodeImpl((WebRtc_Word16*)speechInWB,
+ &ISAC_inst->ISACenc_obj,
+ &ISAC_inst->bwestimator_obj,
+ ISAC_inst->CodingMode);
+ if (stream_len<0) {
+ ISAC_inst->errorcode = - stream_len;
+ return -1;
+ }
+
+
+ /* convert from bytes to WebRtc_Word16 */
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0;k<(stream_len+1)>>1;k++) {
+ encoded[k] = (WebRtc_Word16)(((WebRtc_UWord16)(ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] >> 8)
+ | (((ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] & 0x00FF) << 8));
+ }
+
+#else
+ WEBRTC_SPL_MEMCPY_W16(encoded, (ISAC_inst->ISACenc_obj.bitstr_obj).stream, (stream_len + 1)>>1);
+#endif
+
+
+
+ return stream_len;
+}
+#endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the recieved bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : index of bandwidth estimate to put in new bitstream
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 bweIndex,
+ float scale,
+ WebRtc_Word16 *encoded)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ WebRtc_Word16 stream_len;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ stream_len = WebRtcIsacfix_EncodeStoredData(&ISAC_inst->ISACenc_obj,
+ bweIndex,
+ scale);
+ if (stream_len<0) {
+ ISAC_inst->errorcode = - stream_len;
+ return -1;
+ }
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0;k<(stream_len+1)>>1;k++) {
+ encoded[k] = (WebRtc_Word16)( ( (WebRtc_UWord16)(ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] >> 8 )
+ | (((ISAC_inst->ISACenc_obj.bitstr_obj).stream[k] & 0x00FF) << 8));
+ }
+
+#else
+ WEBRTC_SPL_MEMCPY_W16(encoded, (ISAC_inst->ISACenc_obj.bitstr_obj).stream, (stream_len + 1)>>1);
+#endif
+
+ return stream_len;
+
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecoderInit(...)
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ *
+ * Return value
+ * : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* flag decoder init */
+ ISAC_inst->initflag |= 1;
+
+
+ WebRtcIsacfix_InitMaskingDec(&ISAC_inst->ISACdec_obj.maskfiltstr_obj);
+ WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACdec_obj.postfiltbankstr_obj);
+ WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACdec_obj.pitchfiltstr_obj);
+
+ /* TS */
+ WebRtcIsacfix_InitPlc( &ISAC_inst->ISACdec_obj.plcstr_obj );
+
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACdec_obj.decimatorstr_obj);
+#endif
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * 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 WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 arr_ts)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ Bitstr_dec streamdata;
+ WebRtc_UWord16 partOfStream[5];
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ /* Set stream pointer to point at partOfStream */
+ streamdata.stream = (WebRtc_UWord16 *)partOfStream;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Sanity check of packet length */
+ if (packet_size <= 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (packet_size > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+ streamdata.full = 1;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<5; k++) {
+ streamdata.stream[k] = (WebRtc_UWord16) (((WebRtc_UWord16)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+#else
+ memcpy(streamdata.stream, encoded, 5);
+#endif
+
+ if (packet_size == 0)
+ {
+ /* return error code if the packet length is null */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+ &streamdata,
+ packet_size,
+ rtp_seq_number,
+ 0,
+ arr_ts);
+
+
+ if (err < 0)
+ {
+ /* return error code if something went wrong */
+ ISAC_inst->errorcode = -err;
+ return -1;
+ }
+
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_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 : Send Time Stamp from RTP header
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ Bitstr_dec streamdata;
+ WebRtc_UWord16 partOfStream[5];
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ /* Set stream pointer to point at partOfStream */
+ streamdata.stream = (WebRtc_UWord16 *)partOfStream;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Sanity check of packet length */
+ if (packet_size <= 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (packet_size > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+ streamdata.full = 1;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<5; k++) {
+ streamdata.stream[k] = (WebRtc_UWord16) ((encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+#else
+ memcpy(streamdata.stream, encoded, 5);
+#endif
+
+ if (packet_size == 0)
+ {
+ /* return error code if the packet length is null */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+ &streamdata,
+ packet_size,
+ rtp_seq_number,
+ send_ts,
+ arr_ts);
+
+ if (err < 0)
+ {
+ /* return error code if something went wrong */
+ ISAC_inst->errorcode = -err;
+ return -1;
+ }
+
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 *speechType)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* number of samples (480 or 960), output from decoder */
+ /* that were actually used in the encoder/decoder (determined on the fly) */
+ WebRtc_Word16 number_of_samples;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 declen = 0;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ /* Sanity check of packet length */
+ if (len <= 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (len > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream = (WebRtc_UWord16 *)encoded;
+
+ /* convert bitstream from WebRtc_Word16 to bytes */
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<(len>>1); k++) {
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (WebRtc_UWord16) ((encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+ if (len & 0x0001)
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (WebRtc_UWord16) ((encoded[k] & 0xFF)<<8);
+#endif
+
+ /* added for NetEq purposes (VAD/DTX related) */
+ *speechType=1;
+
+ declen = WebRtcIsacfix_DecodeImpl(decoded,&ISAC_inst->ISACdec_obj, &number_of_samples);
+
+ if (declen < 0) {
+ /* Some error inside the decoder */
+ ISAC_inst->errorcode = -declen;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * MAX_FRAMESAMPLES);
+ return -1;
+ }
+
+ /* error check */
+
+ if (declen & 0x0001) {
+ if (len != declen && len != declen + (((ISAC_inst->ISACdec_obj.bitstr_obj).stream[declen>>1]) & 0x00FF) ) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * number_of_samples);
+ return -1;
+ }
+ } else {
+ if (len != declen && len != declen + (((ISAC_inst->ISACdec_obj.bitstr_obj).stream[declen>>1]) >> 8) ) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * number_of_samples);
+ return -1;
+ }
+ }
+
+ return number_of_samples;
+}
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodeNb(...)
+ *
+ * This function decodes a ISAC frame in narrow-band (8 kHz sampling).
+ * Output speech length will be a multiple of 240 samples: 240 or 480 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * 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
+ */
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+WebRtc_Word16 WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
+ const WebRtc_UWord16 *encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 *speechType)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* twice the number of samples (480 or 960), output from decoder */
+ /* that were actually used in the encoder/decoder (determined on the fly) */
+ WebRtc_Word16 number_of_samples;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 declen = 0;
+ WebRtc_Word16 dummy[FRAMESAMPLES/2];
+
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ if (len == 0)
+ { /* return error code if the packet length is null */
+
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream = (WebRtc_UWord16 *)encoded;
+
+ /* convert bitstream from WebRtc_Word16 to bytes */
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<(len>>1); k++) {
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (WebRtc_UWord16) ((encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+ if (len & 0x0001)
+ (ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (WebRtc_UWord16) ((encoded[k] & 0xFF)<<8);
+#endif
+
+ /* added for NetEq purposes (VAD/DTX related) */
+ *speechType=1;
+
+ declen = WebRtcIsacfix_DecodeImpl(decoded,&ISAC_inst->ISACdec_obj, &number_of_samples);
+
+ if (declen < 0) {
+ /* Some error inside the decoder */
+ ISAC_inst->errorcode = -declen;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * FRAMESAMPLES);
+ return -1;
+ }
+
+ /* error check */
+
+ if (declen & 0x0001) {
+ if (len != declen && len != declen + (((ISAC_inst->ISACdec_obj.bitstr_obj).stream[declen>>1]) & 0x00FF) ) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * number_of_samples);
+ return -1;
+ }
+ } else {
+ if (len != declen && len != declen + (((ISAC_inst->ISACdec_obj.bitstr_obj).stream[declen>>1]) >> 8) ) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(WebRtc_Word16) * number_of_samples);
+ return -1;
+ }
+ }
+
+ WebRtcIsacfix_SplitAndFilter2(decoded, decoded, dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj);
+
+ if (number_of_samples>FRAMESAMPLES) {
+ WebRtcIsacfix_SplitAndFilter2(decoded + FRAMESAMPLES, decoded + FRAMESAMPLES/2,
+ dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj);
+ }
+
+ return number_of_samples/2;
+}
+#endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlcNb(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in narrow-band (8kHz sampling).
+ * Output speech length will be "240*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * The function is enabled if WEBRTC_ISAC_FIX_NB_CALLS_ENABLED is defined
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (240 sample=30ms) to produce
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+WebRtc_Word16 WebRtcIsacfix_DecodePlcNb(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 noOfLostFrames )
+{
+ WebRtc_Word16 no_of_samples, declen, k, ok;
+ WebRtc_Word16 outframeNB[FRAMESAMPLES];
+ WebRtc_Word16 outframeWB[FRAMESAMPLES];
+ WebRtc_Word16 dummy[FRAMESAMPLES/2];
+
+
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */
+ if (noOfLostFrames > 2){
+ noOfLostFrames = 2;
+ }
+
+ k = 0;
+ declen = 0;
+ while( noOfLostFrames > 0 )
+ {
+ ok = WebRtcIsacfix_DecodePlcImpl( outframeWB, &ISAC_inst->ISACdec_obj, &no_of_samples );
+ if(ok)
+ return -1;
+
+ WebRtcIsacfix_SplitAndFilter2(outframeWB, &(outframeNB[k*240]), dummy, &ISAC_inst->ISACdec_obj.decimatorstr_obj);
+
+ declen += no_of_samples;
+ noOfLostFrames--;
+ k++;
+ }
+
+ declen>>=1;
+
+ for (k=0;k<declen;k++) {
+ decoded[k] = outframeNB[k];
+ }
+
+ return declen;
+}
+#endif /* WEBRTC_ISAC_FIX_NB_CALLS_ENABLED */
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (480sample = 30ms)
+ * to produce
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 *decoded,
+ WebRtc_Word16 noOfLostFrames)
+{
+
+ WebRtc_Word16 no_of_samples, declen, k, ok;
+ WebRtc_Word16 outframe16[MAX_FRAMESAMPLES];
+
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */
+ if (noOfLostFrames > 2) {
+ noOfLostFrames = 2;
+ }
+ k = 0;
+ declen = 0;
+ while( noOfLostFrames > 0 )
+ {
+ ok = WebRtcIsacfix_DecodePlcImpl( &(outframe16[k*480]), &ISAC_inst->ISACdec_obj, &no_of_samples );
+ if(ok)
+ return -1;
+ declen += no_of_samples;
+ noOfLostFrames--;
+ k++;
+ }
+
+ for (k=0;k<declen;k++) {
+ decoded[k] = outframe16[k];
+ }
+
+ return declen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * 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
+ */
+
+WebRtc_Word16 WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 rate,
+ WebRtc_Word16 framesize)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if (ISAC_inst->CodingMode == 0)
+ {
+ /* in adaptive mode */
+ ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+
+
+ if (rate >= 10000 && rate <= 32000)
+ ISAC_inst->ISACenc_obj.BottleNeck = rate;
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+ return -1;
+ }
+
+
+
+ if (framesize == 30 || framesize == 60)
+ ISAC_inst->ISACenc_obj.new_framelength = (FS/1000) * framesize;
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 rateBPS,
+ WebRtc_Word16 frameSizeMs,
+ WebRtc_Word16 enforceFrameSize)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* Typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ /* Check that we are in channel-adaptive mode, otherwise, return -1 */
+ if (ISAC_inst->CodingMode != 0) {
+ ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+ return (-1);
+ }
+
+ /* Set struct variable if enforceFrameSize is set. ISAC will then keep the */
+ /* chosen frame size. */
+ ISAC_inst->ISACenc_obj.enforceFrameSize = (enforceFrameSize != 0)? 1:0;
+
+ /* Set initial rate, if value between 10000 and 32000, */
+ /* if rateBPS is 0, keep the default initial bottleneck value (15000) */
+ if ((rateBPS >= 10000) && (rateBPS <= 32000)) {
+ ISAC_inst->bwestimator_obj.sendBwAvg = (((WebRtc_UWord32)rateBPS) << 7);
+ } else if (rateBPS != 0) {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+ return -1;
+ }
+
+ /* Set initial framesize. If enforceFrameSize is set the frame size will not change */
+ if ((frameSizeMs == 30) || (frameSizeMs == 60)) {
+ ISAC_inst->ISACenc_obj.new_framelength = (FS/1000) * frameSizeMs;
+ } else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst: iSAC struct
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+WebRtc_Word16 WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+ WebRtc_Word16* rateIndex)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Call function to get Bandwidth Estimate */
+ *rateIndex = WebRtcIsacfix_GetDownlinkBwIndexImpl(&ISAC_inst->bwestimator_obj);
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_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
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ */
+
+WebRtc_Word16 WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+ WebRtc_Word16 rateIndex)
+{
+ WebRtc_Word16 err = 0;
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Call function to update BWE with received Bandwidth Estimate */
+ err = WebRtcIsacfix_UpdateUplinkBwRec(&ISAC_inst->bwestimator_obj, rateIndex);
+ if (err < 0) {
+ ISAC_inst->errorcode = -err;
+ return (-1);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_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 WebRtcIsacfix_ReadFrameLen(const WebRtc_Word16* encoded,
+ WebRtc_Word16* frameLength)
+{
+ Bitstr_dec streamdata;
+ WebRtc_UWord16 partOfStream[5];
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ /* Set stream pointer to point at partOfStream */
+ streamdata.stream = (WebRtc_UWord16 *)partOfStream;
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+ streamdata.full = 1;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<5; k++) {
+ streamdata.stream[k] = (WebRtc_UWord16) (((WebRtc_UWord16)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+#else
+ memcpy(streamdata.stream, encoded, 5);
+#endif
+
+ /* decode frame length */
+ err = WebRtcIsacfix_DecodeFrameLen(&streamdata, frameLength);
+ if (err<0) // error check
+ return err;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_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)
+ * - rateIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+WebRtc_Word16 WebRtcIsacfix_ReadBwIndex(const WebRtc_Word16* encoded,
+ WebRtc_Word16* rateIndex)
+{
+ Bitstr_dec streamdata;
+ WebRtc_UWord16 partOfStream[5];
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ /* Set stream pointer to point at partOfStream */
+ streamdata.stream = (WebRtc_UWord16 *)partOfStream;
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+ streamdata.full = 1;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<5; k++) {
+ streamdata.stream[k] = (WebRtc_UWord16) (((WebRtc_UWord16)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
+ }
+#else
+ memcpy(streamdata.stream, encoded, 5);
+#endif
+
+ /* decode frame length, needed to get to the rateIndex in the bitstream */
+ err = WebRtcIsacfix_DecodeFrameLen(&streamdata, rateIndex);
+ if (err<0) // error check
+ return err;
+
+ /* decode BW estimation */
+ err = WebRtcIsacfix_DecodeSendBandwidth(&streamdata, rateIndex);
+ if (err<0) // error check
+ return err;
+
+ return 0;
+}
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_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 occured in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+WebRtc_Word16 WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ return ISAC_inst->errorcode;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function returns the inst quantized iSAC send bitrate
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : bitrate
+ */
+
+WebRtc_Word32 WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+ BwEstimatorstr * bw = (BwEstimatorstr*)&(ISAC_inst->bwestimator_obj);
+
+ return (WebRtc_Word32) WebRtcIsacfix_GetUplinkBandwidth(bw);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : frame lenght in samples
+ */
+
+WebRtc_Word16 WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+ return ISAC_inst->ISACenc_obj.new_framelength;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+WebRtc_Word16 WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word16 maxPayloadBytes)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if((maxPayloadBytes < 100) || (maxPayloadBytes > 400))
+ {
+ /* maxPayloadBytes is out of valid range */
+ return -1;
+ }
+ else
+ {
+ /* Set new absolute max, which will not change unless this function
+ is called again with a new value */
+ ISAC_inst->ISACenc_obj.maxPayloadBytes = maxPayloadBytes;
+
+ /* Set new maximum values for 30 and 60 msec packets */
+ if (maxPayloadBytes < ISAC_inst->ISACenc_obj.maxRateInBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxPayloadBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxRateInBytes;
+ }
+
+ if ( maxPayloadBytes < (ISAC_inst->ISACenc_obj.maxRateInBytes << 1)) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = maxPayloadBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (ISAC_inst->ISACenc_obj.maxRateInBytes << 1);
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRateInBytes : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+WebRtc_Word16 WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst,
+ WebRtc_Word32 maxRate)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ WebRtc_Word16 maxRateInBytes;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if((maxRate < 32000) || (maxRate > 53400))
+ {
+ /* maxRate is out of valid range */
+ return -1;
+ }
+ else
+ {
+ /* 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 msec,
+ divide by 8 to get number of bytes per 30 msec:
+ maxRateInBytes = floor((maxRate * 30/1000) / 8); */
+ maxRateInBytes = (WebRtc_Word16)( WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_MUL(maxRate, 3), 800) );
+
+ /* Store the value for usage in the WebRtcIsacfix_SetMaxPayloadSize-function */
+ ISAC_inst->ISACenc_obj.maxRateInBytes = maxRateInBytes;
+
+ /* For 30 msec packets: if the new limit is below the maximum
+ payload size, set a new limit */
+ if (maxRateInBytes < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxRateInBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+ }
+
+ /* For 60 msec packets: if the new limit (times 2) is below the
+ maximum payload size, set a new limit */
+ if ( (maxRateInBytes << 1) < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (maxRateInBytes << 1);
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+void WebRtcIsacfix_version(char *version)
+{
+ strcpy(version, "3.6.0");
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi
new file mode 100644
index 0000000..739b2e1
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi
@@ -0,0 +1,108 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'iSACFix',
+ 'type': '<(library)',
+ 'dependencies': [
+ '<(webrtc_root)/common_audio/common_audio.gyp:signal_processing',
+ '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+ ],
+ 'include_dirs': [
+ '../interface',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../interface',
+ ],
+ },
+ 'sources': [
+ '../interface/isacfix.h',
+ 'arith_routines.c',
+ 'arith_routines_hist.c',
+ 'arith_routines_logist.c',
+ 'bandwidth_estimator.c',
+ 'decode.c',
+ 'decode_bwe.c',
+ 'decode_plc.c',
+ 'encode.c',
+ 'entropy_coding.c',
+ 'fft.c',
+ 'filterbank_tables.c',
+ 'filterbanks.c',
+ 'filters.c',
+ 'initialize.c',
+ 'isacfix.c',
+ 'lattice.c',
+ 'lattice_c.c',
+ 'lpc_masking_model.c',
+ 'lpc_tables.c',
+ 'pitch_estimator.c',
+ 'pitch_filter.c',
+ 'pitch_filter_c.c',
+ 'pitch_gain_tables.c',
+ 'pitch_lag_tables.c',
+ 'spectrum_ar_model_tables.c',
+ 'transform.c',
+ 'arith_routins.h',
+ 'bandwidth_estimator.h',
+ 'codec.h',
+ 'entropy_coding.h',
+ 'fft.h',
+ 'filterbank_tables.h',
+ 'lpc_masking_model.h',
+ 'lpc_tables.h',
+ 'pitch_estimator.h',
+ 'pitch_gain_tables.h',
+ 'pitch_lag_tables.h',
+ 'settings.h',
+ 'spectrum_ar_model_tables.h',
+ 'structs.h',
+ ],
+ 'conditions': [
+ ['OS!="win"', {
+ 'defines': [
+ 'WEBRTC_LINUX',
+ ],
+ }],
+ ['target_arch=="arm" and armv7==1', {
+ 'dependencies': [ 'isac_neon', ],
+ 'sources': [
+ 'lattice_armv7.S',
+ 'pitch_filter_armv6.S',
+ ],
+ 'sources!': [
+ 'lattice_c.c',
+ 'pitch_filter_c.c',
+ ],
+ }],
+ ],
+ },
+ ],
+ 'conditions': [
+ ['target_arch=="arm" and armv7==1', {
+ 'targets': [
+ {
+ 'target_name': 'isac_neon',
+ 'type': '<(library)',
+ 'includes': ['../../../../../../build/arm_neon.gypi',],
+ 'dependencies': [
+ '<(webrtc_root)/common_audio/common_audio.gyp:signal_processing',
+ ],
+ 'sources': [
+ 'filters_neon.c',
+ 'lattice_neon.S',
+ 'lpc_masking_model_neon.S',
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lattice.c b/src/modules/audio_coding/codecs/isac/fix/source/lattice.c
new file mode 100644
index 0000000..14588d0
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lattice.c
@@ -0,0 +1,314 @@
+/*
+ * 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 "codec.h"
+#include "settings.h"
+
+#define LATTICE_MUL_32_32_RSFT16(a32a, a32b, b32) \
+ ((WebRtc_Word32)(WEBRTC_SPL_MUL(a32a, b32) + (WEBRTC_SPL_MUL_16_32_RSFT16(a32b, b32))))
+/* This macro is FORBIDDEN to use elsewhere than in a function in this file and
+ its corresponding neon version. It might give unpredictable results, since a
+ general WebRtc_Word32*WebRtc_Word32 multiplication results in a 64 bit value.
+ The result is then shifted just 16 steps to the right, giving need for 48
+ bits, i.e. in the generel case, it will NOT fit in a WebRtc_Word32. In the
+ cases used in here, the WebRtc_Word32 will be enough, since (for a good
+ reason) the involved multiplicands aren't big enough to overflow a
+ WebRtc_Word32 after shifting right 16 bits. I have compared the result of a
+ multiplication between t32 and tmp32, done in two ways:
+ 1) Using (WebRtc_Word32) (((float)(tmp32))*((float)(tmp32b))/65536.0);
+ 2) Using LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+ By running 25 files, I haven't found any bigger diff than 64 - this was in the
+ case when method 1) gave 650235648 and 2) gave 650235712.
+*/
+
+/* Function prototype: filtering ar_g_Q0[] and ar_f_Q0[] through an AR filter
+ with coefficients cth_Q15[] and sth_Q15[].
+ Implemented for both generic and ARMv7 platforms.
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0,
+ int16_t* ar_f_Q0,
+ int16_t* cth_Q15,
+ int16_t* sth_Q15,
+ int16_t order_coef);
+
+/* Inner loop used for function WebRtcIsacfix_NormLatticeFilterMa(). It does:
+ for 0 <= n < HALF_SUBFRAMELEN - 1:
+ *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+ *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+ Note, function WebRtcIsacfix_FilterMaLoopNeon and WebRtcIsacfix_FilterMaLoopC
+ are not bit-exact. The accuracy by the ARM Neon function is same or better.
+*/
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0, // Filter coefficient
+ int16_t input1, // Filter coefficient
+ int32_t input2, // Inverse coeff. (1/input1)
+ int32_t* ptr0, // Sample buffer
+ int32_t* ptr1, // Sample buffer
+ int32_t* ptr2) { // Sample buffer
+ int n = 0;
+
+ // Separate the 32-bit variable input2 into two 16-bit integers (high 16 and
+ // low 16 bits), for using LATTICE_MUL_32_32_RSFT16 in the loop.
+ int16_t t16a = (int16_t)(input2 >> 16);
+ int16_t t16b = (int16_t)input2;
+ if (t16b < 0) t16a++;
+
+ // The loop filtering the samples *ptr0, *ptr1, *ptr2 with filter coefficients
+ // input0, input1, and input2.
+ for(n = 0; n < HALF_SUBFRAMELEN - 1; n++, ptr0++, ptr1++, ptr2++) {
+ int32_t tmp32a = 0;
+ int32_t tmp32b = 0;
+
+ // Calculate *ptr2 = input2 * (*ptr2 + input0 * (*ptr0));
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr0); // Q15 * Q15 >> 15 = Q15
+ tmp32b = *ptr2 + tmp32a; // Q15 + Q15 = Q15
+ *ptr2 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+
+ // Calculate *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input1, *ptr0); // Q15*Q15>>15 = Q15
+ tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr2); // Q15*Q15>>15 = Q15
+ *ptr1 = tmp32a + tmp32b; // Q15 + Q15 = Q15
+ }
+}
+
+// Declare a function pointer.
+FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsacfix_NormLatticeFilterMa(WebRtc_Word16 orderCoef,
+ WebRtc_Word32 *stateGQ15,
+ WebRtc_Word16 *lat_inQ0,
+ WebRtc_Word16 *filt_coefQ15,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 lo_hi,
+ WebRtc_Word16 *lat_outQ9)
+{
+ WebRtc_Word16 sthQ15[MAX_AR_MODEL_ORDER];
+ WebRtc_Word16 cthQ15[MAX_AR_MODEL_ORDER];
+
+ int u, i, k, n;
+ WebRtc_Word16 temp2,temp3;
+ WebRtc_Word16 ord_1 = orderCoef+1;
+ WebRtc_Word32 inv_cthQ16[MAX_AR_MODEL_ORDER];
+
+ WebRtc_Word32 gain32, fQtmp;
+ WebRtc_Word16 gain16;
+ WebRtc_Word16 gain_sh;
+
+ WebRtc_Word32 tmp32, tmp32b;
+ WebRtc_Word32 fQ15vec[HALF_SUBFRAMELEN];
+ WebRtc_Word32 gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ WebRtc_Word16 sh;
+ WebRtc_Word16 t16a;
+ WebRtc_Word16 t16b;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN);
+
+ /* set the Direct Form coefficients */
+ temp2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(u, orderCoef);
+ temp3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(2, u)+lo_hi;
+
+ /* compute lattice filter coefficients */
+ memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(WebRtc_Word16));
+
+ WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+ /* compute the gain */
+ gain32 = gain_lo_hiQ17[temp3];
+ gain_sh = WebRtcSpl_NormW32(gain32);
+ gain32 = WEBRTC_SPL_LSHIFT_W32(gain32, gain_sh); //Q(17+gain_sh)
+
+ for (k=0;k<orderCoef;k++)
+ {
+ gain32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], gain32); //Q15*Q(17+gain_sh)>>15 = Q(17+gain_sh)
+ inv_cthQ16[k] = WebRtcSpl_DivW32W16((WebRtc_Word32)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16
+ }
+ gain16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(gain32, 16); //Q(1+gain_sh)
+
+ /* normalized lattice filter */
+ /*****************************/
+
+ /* initial conditions */
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ fQ15vec[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)lat_inQ0[i + temp1], 15); //Q15
+ gQ15[0][i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)lat_inQ0[i + temp1], 15); //Q15
+ }
+
+
+ fQtmp = fQ15vec[0];
+
+ /* get the state of f&g for the first input, for all orders */
+ for (i=1;i<ord_1;i++)
+ {
+ // Calculate f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], stateGQ15[i-1]);//Q15*Q15>>15 = Q15
+ tmp32b= fQtmp + tmp32; //Q15+Q15=Q15
+ tmp32 = inv_cthQ16[i-1]; //Q16
+ t16a = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
+ t16b = (WebRtc_Word16) (tmp32-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)t16a), 16));
+ if (t16b<0) t16a++;
+ tmp32 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+ fQtmp = tmp32; // Q15
+
+ // Calculate g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[i-1], stateGQ15[i-1]); //Q15*Q15>>15 = Q15
+ tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], fQtmp); //Q15*Q15>>15 = Q15
+ tmp32 = tmp32 + tmp32b;//Q15+Q15 = Q15
+ gQ15[i][0] = tmp32; // Q15
+ }
+
+ /* filtering */
+ /* save the states */
+ for(k=0;k<orderCoef;k++)
+ {
+ // for 0 <= n < HALF_SUBFRAMELEN - 1:
+ // 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];
+ WebRtcIsacfix_FilterMaLoopFix(sthQ15[k], cthQ15[k], inv_cthQ16[k],
+ &gQ15[k][0], &gQ15[k+1][1], &fQ15vec[1]);
+ }
+
+ fQ15vec[0] = fQtmp;
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ //gain32 = WEBRTC_SPL_RSHIFT_W32(gain32, gain_sh); // Q(17+gain_sh) -> Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(gain16, fQ15vec[n]); //Q(1+gain_sh)*Q15>>16 = Q(gain_sh)
+ sh = 9-gain_sh; //number of needed shifts to reach Q9
+ t16a = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32, sh);
+ lat_outQ9[n + temp1] = t16a;
+ }
+
+ /* save the states */
+ for (i=0;i<ord_1;i++)
+ {
+ stateGQ15[i] = gQ15[i][HALF_SUBFRAMELEN-1];
+ }
+ //process next frame
+ }
+
+ return;
+}
+
+
+
+
+
+/* ----------------AR filter-------------------------*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsacfix_NormLatticeFilterAr(WebRtc_Word16 orderCoef,
+ WebRtc_Word16 *stateGQ0,
+ WebRtc_Word32 *lat_inQ25,
+ WebRtc_Word16 *filt_coefQ15,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 lo_hi,
+ WebRtc_Word16 *lat_outQ0)
+{
+ int ii,n,k,i,u;
+ WebRtc_Word16 sthQ15[MAX_AR_MODEL_ORDER];
+ WebRtc_Word16 cthQ15[MAX_AR_MODEL_ORDER];
+ WebRtc_Word32 tmp32;
+
+
+ WebRtc_Word16 tmpAR;
+ WebRtc_Word16 ARfQ0vec[HALF_SUBFRAMELEN];
+ WebRtc_Word16 ARgQ0vec[MAX_AR_MODEL_ORDER+1];
+
+ WebRtc_Word32 inv_gain32;
+ WebRtc_Word16 inv_gain16;
+ WebRtc_Word16 den16;
+ WebRtc_Word16 sh;
+
+ WebRtc_Word16 temp2,temp3;
+ WebRtc_Word16 ord_1 = orderCoef+1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN);
+
+ //set the denominator and numerator of the Direct Form
+ temp2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(u, orderCoef);
+ temp3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(2, u) + lo_hi;
+
+ for (ii=0; ii<orderCoef; ii++) {
+ sthQ15[ii] = filt_coefQ15[temp2+ii];
+ }
+
+ WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+ /* Simulation of the 25 files shows that maximum value in
+ the vector gain_lo_hiQ17[] is 441344, which means that
+ it is log2((2^31)/441344) = 12.2 shifting bits from
+ saturation. Therefore, it should be safe to use Q27 instead
+ of Q17. */
+
+ tmp32 = WEBRTC_SPL_LSHIFT_W32(gain_lo_hiQ17[temp3], 10); // Q27
+
+ for (k=0;k<orderCoef;k++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], tmp32); // Q15*Q27>>15 = Q27
+ }
+
+ sh = WebRtcSpl_NormW32(tmp32); // tmp32 is the gain
+ den16 = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits)
+ inv_gain32 = WebRtcSpl_DivW32W16((WebRtc_Word32)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh)
+
+ //initial conditions
+ inv_gain16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(inv_gain32, 2); // 1/gain in Q(20-sh-2) = Q(18-sh)
+
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+
+ tmp32 = WEBRTC_SPL_LSHIFT_W32(lat_inQ25[i + temp1], 1); //Q25->Q26
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(inv_gain16, tmp32); //lat_in[]*inv_gain in (Q(18-sh)*Q26)>>16 = Q(28-sh)
+ tmp32 = WEBRTC_SPL_SHIFT_W32(tmp32, -(28-sh)); // lat_in[]*inv_gain in Q0
+
+ ARfQ0vec[i] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+ }
+
+ for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
+ {
+ tmp32 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(cthQ15[i],ARfQ0vec[0])) - (WEBRTC_SPL_MUL_16_16(sthQ15[i],stateGQ0[i])) + 16384), 15);
+ tmpAR = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+
+ tmp32 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(sthQ15[i],ARfQ0vec[0])) + (WEBRTC_SPL_MUL_16_16(cthQ15[i], stateGQ0[i])) + 16384), 15);
+ ARgQ0vec[i+1] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+ ARfQ0vec[0] = tmpAR;
+ }
+ ARgQ0vec[0] = ARfQ0vec[0];
+
+ // Filter ARgQ0vec[] and ARfQ0vec[] through coefficients cthQ15[] and sthQ15[].
+ WebRtcIsacfix_FilterArLoop(ARgQ0vec, ARfQ0vec, cthQ15, sthQ15, orderCoef);
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ lat_outQ0[n + temp1] = ARfQ0vec[n];
+ }
+
+
+ /* cannot use memcpy in the following */
+
+ for (i=0;i<ord_1;i++)
+ {
+ stateGQ0[i] = ARgQ0vec[i];
+ }
+ }
+
+ return;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S b/src/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
new file mode 100644
index 0000000..1cd3a76
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
@@ -0,0 +1,82 @@
+@
+@ 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.
+@
+
+@ Contains a function for the core loop in the normalized lattice AR
+@ filter routine for iSAC codec, optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in lattic_c.c
+@
+@ Register usage:
+@
+@ r0: &ar_g_Q0
+@ r1: &ar_f_Q0
+@ r2: &cth_Q15
+@ r3: &sth_Q15
+@ r4: out loop counter
+@ r5: tmpAR
+@ r9: inner loop counter
+@ r12: constant #16384
+@ r6, r7, r8, r10, r11: scratch
+
+#include "settings.h"
+
+.arch armv7-a
+.global WebRtcIsacfix_FilterArLoop
+.align 2
+
+WebRtcIsacfix_FilterArLoop:
+.fnstart
+
+.save {r4-r11}
+ push {r4-r11}
+
+ add r1, #2 @ &ar_f_Q0[1]
+ mov r12, #16384
+ mov r4, #HALF_SUBFRAMELEN
+ sub r4, #1 @ Outer loop counter = HALF_SUBFRAMELEN - 1
+
+HALF_SUBFRAME_LOOP: @ for(n = 0; n < HALF_SUBFRAMELEN - 1; n++)
+
+ ldr r9, [sp, #32] @ Restore the inner loop counter to order_coef
+ ldrh r5, [r1] @ tmpAR = ar_f_Q0[n+1]
+ add r0, r9, asl #1 @ Restore r0 to &ar_g_Q0[order_coef]
+ add r2, r9, asl #1 @ Restore r2 to &cth_Q15[order_coef]
+ add r3, r9, asl #1 @ Restore r3 to &sth_Q15[order_coef]
+
+ORDER_COEF_LOOP: @ for(k = order_coef - 1 ; k >= 0; k--)
+
+ ldrh r7, [r3, #-2]! @ sth_Q15[k]
+ ldrh r6, [r2, #-2]! @ cth_Q15[k]
+
+ ldrh r8, [r0, #-2] @ ar_g_Q0[k]
+ smlabb r11, r7, r5, r12 @ sth_Q15[k] * tmpAR + 16384
+ smlabb r10, r6, r5, r12 @ cth_Q15[k] * tmpAR + 16384
+ smulbb r7, r7, r8 @ sth_Q15[k] * ar_g_Q0[k]
+ smlabb r11, r6, r8, r11 @ cth_Q15[k]*ar_g_Q0[k]+(sth_Q15[k]*tmpAR+16384)
+
+ sub r10, r10, r7 @ cth_Q15[k]*tmpAR+16384-(sth_Q15[k]*ar_g_Q0[k])
+ ssat r11, #16, r11, asr #15
+ ssat r5, #16, r10, asr #15
+ strh r11, [r0], #-2 @ Output: ar_g_Q0[k+1]
+
+ subs r9, #1
+ bgt ORDER_COEF_LOOP
+
+ strh r5, [r0] @ Output: ar_g_Q0[0] = tmpAR;
+ strh r5, [r1], #2 @ Output: ar_f_Q0[n+1] = tmpAR;
+
+ subs r4, #1
+ bne HALF_SUBFRAME_LOOP
+
+ pop {r4-r11}
+ bx lr
+
+.fnend
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lattice_c.c b/src/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
new file mode 100644
index 0000000..80ccf39
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
@@ -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.
+ */
+
+/*
+ * Contains the core loop function for the lattice filter AR routine
+ * for iSAC codec.
+ *
+ */
+
+#include "settings.h"
+#include "signal_processing_library.h"
+#include "typedefs.h"
+
+/* Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
+ * cth_Q15[] and sth_Q15[].
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0, // Input samples
+ int16_t* ar_f_Q0, // Input samples
+ int16_t* cth_Q15, // Filter coefficients
+ int16_t* sth_Q15, // Filter coefficients
+ int16_t order_coef) { // order of the filter
+ int n = 0;
+
+ for (n = 0; n < HALF_SUBFRAMELEN - 1; n++) {
+ int k = 0;
+ int16_t tmpAR = 0;
+ int32_t tmp32 = 0;
+ int32_t tmp32_2 = 0;
+
+ tmpAR = ar_f_Q0[n + 1];
+ for (k = order_coef - 1; k >= 0; k--) {
+ tmp32 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(cth_Q15[k], tmpAR))
+ - (WEBRTC_SPL_MUL_16_16(sth_Q15[k], ar_g_Q0[k])) + 16384), 15);
+ tmp32_2 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(sth_Q15[k], tmpAR))
+ + (WEBRTC_SPL_MUL_16_16(cth_Q15[k], ar_g_Q0[k])) + 16384), 15);
+ tmpAR = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp32);
+ ar_g_Q0[k + 1] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmp32_2);
+ }
+ ar_f_Q0[n + 1] = tmpAR;
+ ar_g_Q0[0] = tmpAR;
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lattice_neon.S b/src/modules/audio_coding/codecs/isac/fix/source/lattice_neon.S
new file mode 100644
index 0000000..a59b6e3
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lattice_neon.S
@@ -0,0 +1,155 @@
+@
+@ 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_neon.s
+@
+@ Contains a function for the core loop in the normalized lattice MA
+@ filter routine for iSAC codec, optimized for ARM Neon platform.
+@ void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
+@ int16_t input1,
+@ int32_t input2,
+@ int32_t* ptr0,
+@ int32_t* ptr1,
+@ int32_t* __restrict ptr2);
+@ It calculates
+@ *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+@ *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+@ in Q15 domain.
+@
+@ Reference code in lattice.c.
+@ Output is not bit-exact with the reference C code, due to the replacement
+@ of WEBRTC_SPL_MUL_16_32_RSFT15 and LATTICE_MUL_32_32_RSFT16 with Neon
+@ instructions, smulwb, and smull. Speech quality was not degraded by
+@ testing speech and tone vectors.
+
+.arch armv7-a
+.fpu neon
+
+#include "settings.h"
+
+.global WebRtcIsacfix_FilterMaLoopNeon
+
+.align 2
+
+WebRtcIsacfix_FilterMaLoopNeon:
+.fnstart
+
+.save {r4-r8}
+ push {r4-r8}
+
+ vdup.32 d28, r0 @ Initialize Neon register with input0
+ vdup.32 d29, r1 @ Initialize Neon register with input1
+ vdup.32 d30, r2 @ Initialize Neon register with input2
+ ldr r4, [sp, #20] @ ptr1
+ ldr r12, [sp, #24] @ ptr2
+
+ @ Number of loop iterations after unrolling: r5 = (HALF_SUBFRAMELEN - 1) >> 2
+ @ Leftover samples after the loop, in r6:
+ @ r6 = (HALF_SUBFRAMELEN - 1) - (HALF_SUBFRAMELEN - 1) >> 2 << 2
+ mov r6, #HALF_SUBFRAMELEN
+ sub r6, #1
+ lsr r5, r6, #2
+ sub r6, r5, lsl #2
+
+ @ First r5 iterations in a loop.
+
+LOOP:
+ vld1.32 {d0, d1}, [r3]! @ *ptr0
+
+ vmull.s32 q10, d0, d28 @ tmp32a = input0 * (*ptr0)
+ vmull.s32 q11, d1, d28 @ tmp32a = input0 * (*ptr0)
+ vmull.s32 q12, d0, d29 @ input1 * (*ptr0)
+ vmull.s32 q13, d1, d29 @ input1 * (*ptr0)
+
+ vrshrn.i64 d4, q10, #15
+ vrshrn.i64 d5, q11, #15
+
+ vld1.32 {d2, d3}, [r12] @ *ptr2
+ vadd.i32 q3, q2, q1 @ tmp32b = *ptr2 + tmp32a
+
+ vrshrn.i64 d0, q12, #15
+
+ vmull.s32 q10, d6, d30 @ input2 * (*ptr2 + tmp32b)
+ vmull.s32 q11, d7, d30 @ input2 * (*ptr2 + tmp32b)
+
+ vrshrn.i64 d16, q10, #16
+ vrshrn.i64 d17, q11, #16
+
+ vmull.s32 q10, d16, d28 @ input0 * (*ptr2)
+ vmull.s32 q11, d17, d28 @ input0 * (*ptr2)
+
+ vrshrn.i64 d1, q13, #15
+ vrshrn.i64 d18, q10, #15
+ vrshrn.i64 d19, q11, #15
+
+ vst1.32 {d16, d17}, [r12]! @ *ptr2
+
+ vadd.i32 q9, q0, q9
+ subs r5, #1
+ vst1.32 {d18, d19}, [r4]! @ *ptr1
+
+ bgt LOOP
+
+ @ Check how many samples still need to be processed.
+ subs r6, #2
+ blt LAST_SAMPLE
+
+ @ Process two more samples:
+ vld1.32 d0, [r3]! @ *ptr0
+
+ vmull.s32 q11, d0, d28 @ tmp32a = input0 * (*ptr0)
+ vmull.s32 q13, d0, d29 @ input1 * (*ptr0)
+
+ vld1.32 d18, [r12] @ *ptr2
+ vrshrn.i64 d4, q11, #15
+
+ vadd.i32 d7, d4, d18 @ tmp32b = *ptr2 + tmp32a
+ vmull.s32 q11, d7, d30 @ input2 * (*ptr2 + tmp32b)
+ vrshrn.i64 d16, q11, #16
+
+ vmull.s32 q11, d16, d28 @ input0 * (*ptr2)
+ vst1.32 d16, [r12]! @ *ptr2
+
+ vrshrn.i64 d0, q13, #15
+ vrshrn.i64 d19, q11, #15
+ vadd.i32 d19, d0, d19
+
+ vst1.32 d19, [r4]! @ *ptr1
+
+ @ If there's still one more sample, process it here.
+LAST_SAMPLE:
+ cmp r6, #1
+ bne END
+
+ @ *ptr2 = input2 * (*ptr2 + input0 * (*ptr0));
+
+ ldr r7, [r3] @ *ptr0
+ ldr r8, [r12] @ *ptr2
+
+ smulwb r5, r7, r0 @ tmp32a = *ptr0 * input0 >> 16
+ add r8, r8, r5, lsl #1 @ tmp32b = *ptr2 + (tmp32a << 1)
+ smull r5, r6, r8, r2 @ tmp32b * input2, in 64 bits
+ lsl r6, #16
+ add r6, r5, lsr #16 @ Only take the middle 32 bits
+ str r6, [r12] @ Output (*ptr2, as 32 bits)
+
+ @ *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+
+ smulwb r5, r7, r1 @ tmp32a = *ptr0 * input1 >> 16
+ smulwb r6, r6, r0 @ tmp32b = *ptr2 * input0 >> 16
+ lsl r5, r5, #1
+ add r5, r6, lsl #1
+ str r5, [r4] @ Output (*ptr1)
+
+END:
+ pop {r4-r8}
+ bx lr
+
+.fnend
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
new file mode 100644
index 0000000..4be438e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
@@ -0,0 +1,957 @@
+/*
+ * 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_masking_model.c
+ *
+ * LPC analysis and filtering functions
+ *
+ */
+
+#include "lpc_masking_model.h"
+
+#include <limits.h> /* For LLONG_MAX and LLONG_MIN. */
+#include "codec.h"
+#include "entropy_coding.h"
+#include "settings.h"
+
+/* The conversion is implemented by the step-down algorithm */
+void WebRtcSpl_AToK_JSK(
+ WebRtc_Word16 *a16, /* Q11 */
+ WebRtc_Word16 useOrder,
+ WebRtc_Word16 *k16 /* Q15 */
+ )
+{
+ int m, k;
+ WebRtc_Word32 tmp32[MAX_AR_MODEL_ORDER];
+ WebRtc_Word32 tmp32b;
+ WebRtc_Word32 tmp_inv_denum32;
+ WebRtc_Word16 tmp_inv_denum16;
+
+ k16[useOrder-1]= WEBRTC_SPL_LSHIFT_W16(a16[useOrder], 4); //Q11<<4 => Q15
+
+ for (m=useOrder-1; m>0; m--) {
+ tmp_inv_denum32 = ((WebRtc_Word32) 1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]); // (1 - k^2) in Q30
+ tmp_inv_denum16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp_inv_denum32, 15); // (1 - k^2) in Q15
+
+ for (k=1; k<=m; k++) {
+ tmp32b = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)a16[k], 16) -
+ WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(k16[m], a16[m-k+1]), 1);
+
+ tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12
+ }
+
+ for (k=1; k<m; k++) {
+ a16[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q12>>1 => Q11
+ }
+
+ tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092);
+ k16[m-1] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmp32[m], 3); //Q12<<3 => Q15
+ }
+
+ return;
+}
+
+
+
+
+
+WebRtc_Word16 WebRtcSpl_LevinsonW32_JSK(
+ WebRtc_Word32 *R, /* (i) Autocorrelation of length >= order+1 */
+ WebRtc_Word16 *A, /* (o) A[0..order] LPC coefficients (Q11) */
+ WebRtc_Word16 *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */
+ WebRtc_Word16 order /* (i) filter order */
+ ) {
+ WebRtc_Word16 i, j;
+ WebRtc_Word16 R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
+ /* Aurocorr coefficients in high precision */
+ WebRtc_Word16 A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
+ /* LPC coefficients in high precicion */
+ WebRtc_Word16 A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
+ /* LPC coefficients for next iteration */
+ WebRtc_Word16 K_hi, K_low; /* reflection coefficient in high precision */
+ WebRtc_Word16 Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
+ and with scale factor */
+ WebRtc_Word16 tmp_hi, tmp_low;
+ WebRtc_Word32 temp1W32, temp2W32, temp3W32;
+ WebRtc_Word16 norm;
+
+ /* Normalize the autocorrelation R[0]...R[order+1] */
+
+ norm = WebRtcSpl_NormW32(R[0]);
+
+ for (i=order;i>=0;i--) {
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
+ /* Put R in hi and low format */
+ R_hi[i] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ R_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)), 1);
+ }
+
+ /* K = A[1] = -R[1] / R[0] */
+
+ temp2W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[1],16) +
+ WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[1],1); /* R[1] in Q31 */
+ temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); /* abs R[1] */
+ temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */
+ /* Put back the sign on R[1] */
+ if (temp2W32 > 0) {
+ temp1W32 = -temp1W32;
+ }
+
+ /* Put K in hi and low format */
+ K_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ /* Store first reflection coefficient */
+ K[0] = K_hi;
+
+ temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4); /* A[1] in Q27 */
+
+ /* Put A[1] in hi and low format */
+ A_hi[1] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_low[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[1], 16)), 1);
+
+ /* Alpha = R[0] * (1-K^2) */
+
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
+ WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* temp1W32 = k^2 in Q31 */
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */
+
+ /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
+ tmp_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ /* Calculate Alpha in Q31 */
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low), 15) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi), 15) ), 1);
+
+ /* Normalize Alpha and put it in hi and low format */
+
+ Alpha_exp = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
+ Alpha_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ /* Perform the iterative calculations in the
+ Levinson Durbin algorithm */
+
+ for (i=2; i<=order; i++)
+ {
+
+ /* ----
+ \
+ temp1W32 = R[i] + > R[j]*A[i-j]
+ /
+ ----
+ j=1..i-1
+ */
+
+ temp1W32 = 0;
+
+ for(j=1; j<i; j++) {
+ /* temp1W32 is in Q31 */
+ temp1W32 += (WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]), 1) +
+ WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]), 15) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]), 15) ), 1));
+ }
+
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
+ temp1W32 += (WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16) +
+ WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[i], 1));
+
+ /* K = -temp1W32 / Alpha */
+ temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* abs(temp1W32) */
+ temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */
+
+ /* Put the sign of temp1W32 back again */
+ if (temp1W32 > 0) {
+ temp3W32 = -temp3W32;
+ }
+
+ /* Use the Alpha shifts from earlier to denormalize */
+ norm = WebRtcSpl_NormW32(temp3W32);
+ if ((Alpha_exp <= norm)||(temp3W32==0)) {
+ temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
+ } else {
+ if (temp3W32 > 0)
+ {
+ temp3W32 = (WebRtc_Word32)0x7fffffffL;
+ } else
+ {
+ temp3W32 = (WebRtc_Word32)0x80000000L;
+ }
+ }
+
+ /* Put K on hi and low format */
+ K_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ /* Store Reflection coefficient in Q15 */
+ K[i-1] = K_hi;
+
+ /* Test for unstable filter. If unstable return 0 and let the
+ user decide what to do in that case
+ */
+
+ if ((WebRtc_Word32)WEBRTC_SPL_ABS_W16(K_hi) > (WebRtc_Word32)32740) {
+ return(-i); /* Unstable filter */
+ }
+
+ /*
+ Compute updated LPC coefficient: Anew[i]
+ Anew[j]= A[j] + K*A[i-j] for j=1..i-1
+ Anew[i]= K
+ */
+
+ for(j=1; j<i; j++)
+ {
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[j],16) +
+ WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[j],1); /* temp1W32 = A[j] in Q27 */
+
+ temp1W32 += WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j]) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]), 15) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]), 15) ), 1); /* temp1W32 += K*A[i-j] in Q27 */
+
+ /* Put Anew in hi and low format */
+ A_upd_hi[j] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_upd_low[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[j], 16)), 1);
+ }
+
+ temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4); /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */
+
+ /* Store Anew in hi and low format */
+ A_upd_hi[i] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ A_upd_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[i], 16)), 1);
+
+ /* Alpha = Alpha * (1-K^2) */
+
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
+ WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* K*K in Q31 */
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */
+
+ /* Convert 1- K^2 in hi and low format */
+ tmp_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ /* Calculate Alpha = Alpha * (1-K^2) in Q31 */
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low), 15) +
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi), 15)), 1);
+
+ /* Normalize Alpha and store it on hi and low format */
+
+ norm = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);
+
+ Alpha_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ /* Update the total nomalization of Alpha */
+ Alpha_exp = Alpha_exp + norm;
+
+ /* Update A[] */
+
+ for(j=1; j<=i; j++)
+ {
+ A_hi[j] =A_upd_hi[j];
+ A_low[j] =A_upd_low[j];
+ }
+ }
+
+ /*
+ Set A[0] to 1.0 and store the A[i] i=1...order in Q12
+ (Convert from Q27 and use rounding)
+ */
+
+ A[0] = 2048;
+
+ for(i=1; i<=order; i++) {
+ /* temp1W32 in Q27 */
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[i], 16) +
+ WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[i], 1);
+ /* Round and store upper word */
+ A[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32+(WebRtc_Word32)32768, 16);
+ }
+ return(1); /* Stable filters */
+}
+
+
+
+
+
+/* window */
+/* Matlab generation of floating point 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
+ * All values are multiplyed with 2^21 in fixed point code.
+ */
+static const WebRtc_Word16 kWindowAutocorr[WINLEN] = {
+ 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5, 6,
+ 8, 10, 12, 14, 17, 20, 24, 28, 33, 38, 43, 49,
+ 56, 63, 71, 79, 88, 98, 108, 119, 131, 143, 157, 171,
+ 186, 202, 219, 237, 256, 275, 296, 318, 341, 365, 390, 416,
+ 444, 472, 502, 533, 566, 600, 635, 671, 709, 748, 789, 831,
+ 875, 920, 967, 1015, 1065, 1116, 1170, 1224, 1281, 1339, 1399, 1461,
+ 1525, 1590, 1657, 1726, 1797, 1870, 1945, 2021, 2100, 2181, 2263, 2348,
+ 2434, 2523, 2614, 2706, 2801, 2898, 2997, 3099, 3202, 3307, 3415, 3525,
+ 3637, 3751, 3867, 3986, 4106, 4229, 4354, 4481, 4611, 4742, 4876, 5012,
+ 5150, 5291, 5433, 5578, 5725, 5874, 6025, 6178, 6333, 6490, 6650, 6811,
+ 6974, 7140, 7307, 7476, 7647, 7820, 7995, 8171, 8349, 8529, 8711, 8894,
+ 9079, 9265, 9453, 9642, 9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199,
+ 11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614,
+ 13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971,
+ 16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030,
+ 18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471,
+ 19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886,
+ 19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793,
+ 18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677,
+ 15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152,
+ 9583, 8998, 8399, 7787, 7162, 6527, 5883, 5231, 4576, 3919, 3265, 2620,
+ 1990, 1386, 825, 333
+};
+
+
+/* By using a hearing threshold level in dB of -28 dB (higher value gives more noise),
+ the H_T_H (in float) can be calculated as:
+ H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350
+ In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e.
+ H_T_H = 20872/524288.0, and H_T_HQ19 = 20872;
+*/
+
+
+/* The bandwidth expansion vectors are created from:
+ kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430];
+ kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144];
+ round(kPolyVecLo*32768)
+ round(kPolyVecHi*32768)
+*/
+static const WebRtc_Word16 kPolyVecLo[12] = {
+ 29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
+};
+static const WebRtc_Word16 kPolyVecHi[6] = {
+ 26214, 20972, 16777, 13422, 10737, 8590
+};
+
+static __inline WebRtc_Word32 log2_Q8_LPC( WebRtc_UWord32 x ) {
+
+ WebRtc_Word32 zeros, lg2;
+ WebRtc_Word16 frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
+
+ /* log2(x) */
+
+ lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
+ return lg2;
+
+}
+
+static const WebRtc_Word16 kMulPitchGain = -25; /* 200/256 in Q5 */
+static const WebRtc_Word16 kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
+static const WebRtc_Word16 kExp2 = 11819; /* 1/log(2) */
+const int kShiftLowerBand = 11; /* Shift value for lower band in Q domain. */
+const int kShiftHigherBand = 12; /* Shift value for higher band in Q domain. */
+
+void WebRtcIsacfix_GetVars(const WebRtc_Word16 *input, const WebRtc_Word16 *pitchGains_Q12,
+ WebRtc_UWord32 *oldEnergy, WebRtc_Word16 *varscale)
+{
+ int k;
+ WebRtc_UWord32 nrgQ[4];
+ WebRtc_Word16 nrgQlog[4];
+ WebRtc_Word16 tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
+ WebRtc_Word32 expPg32;
+ WebRtc_Word16 expPg, divVal;
+ WebRtc_Word16 tmp16_1, tmp16_2;
+
+ /* Calculate energies of first and second frame halfs */
+ nrgQ[0]=0;
+ for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[0] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
+ }
+ nrgQ[1]=0;
+ for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[1] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
+ }
+ nrgQ[2]=0;
+ for ( ; k < (WEBRTC_SPL_MUL_16_16(FRAMESAMPLES, 3)/4 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[2] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
+ }
+ nrgQ[3]=0;
+ for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+ nrgQ[3] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
+ }
+
+ for ( k=0; k<4; k++) {
+ nrgQlog[k] = (WebRtc_Word16)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
+ }
+ oldNrgQlog = (WebRtc_Word16)log2_Q8_LPC(*oldEnergy);
+
+ /* Calculate average level change */
+ chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]);
+ chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]);
+ chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]);
+ chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog);
+ tmp = chng1+chng2+chng3+chng4;
+ chngQ = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp, kChngFactor, 10); /* Q12 */
+ chngQ += 2926; /* + 1.0/1.4 in Q12 */
+
+ /* Find average pitch gain */
+ pgQ = 0;
+ for (k=0; k<4; k++)
+ {
+ pgQ += pitchGains_Q12[k];
+ }
+
+ pg3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pgQ,11); /* pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 */
+ pg3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pg3,13); /* Q17*Q14>>13 =>Q18 */
+ pg3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pg3, kMulPitchGain ,5); /* Q10 kMulPitchGain = -25 = -200 in Q-3. */
+
+ tmp16=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/
+ if (tmp16<0) {
+ tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+ tmp16_1 = (WEBRTC_SPL_RSHIFT_W16((WebRtc_UWord16)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
+ if (tmp16_1<0)
+ expPg=(WebRtc_Word16) -WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
+ else
+ expPg=(WebRtc_Word16) -WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
+ } else
+ expPg = (WebRtc_Word16) -16384; /* 1 in Q14, since 2^0=1 */
+
+ expPg32 = (WebRtc_Word32)WEBRTC_SPL_LSHIFT_W16((WebRtc_Word32)expPg, 8); /* Q22 */
+ divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
+
+ tmp16=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/
+ if (tmp16<0) {
+ tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+ tmp16_1 = (WEBRTC_SPL_RSHIFT_W16((WebRtc_UWord16)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
+ if (tmp16_1<0)
+ expPg=(WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
+ else
+ expPg=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
+ } else
+ expPg = (WebRtc_Word16) 16384; /* 1 in Q14, since 2^0=1 */
+
+ *varscale = expPg-1;
+ *oldEnergy = nrgQ[3];
+}
+
+
+
+static __inline WebRtc_Word16 exp2_Q10_T(WebRtc_Word16 x) { // Both in and out in Q10
+
+ WebRtc_Word16 tmp16_1, tmp16_2;
+
+ tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
+ tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
+ if(tmp16_1>0)
+ return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
+ else
+ return (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
+
+}
+
+
+// Declare function pointers.
+AutocorrFix WebRtcIsacfix_AutocorrFix;
+CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+/* This routine calculates the residual energy for LPC.
+ * Formula as shown in comments inside.
+ */
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy) {
+ int i = 0, j = 0;
+ int shift_internal = 0, shift_norm = 0;
+ int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
+ int64_t sum64 = 0, sum64_tmp = 0;
+
+ for (i = 0; i <= lpc_order; i++) {
+ for (j = i; j <= lpc_order; j++) {
+ /* For the case of i == 0: residual_energy +=
+ * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
+ * For the case of i != 0: residual_energy +=
+ * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
+ */
+
+ tmp32 = WEBRTC_SPL_MUL_16_16(a_polynomial[j], a_polynomial[j - i]);
+ /* tmp32 in Q(q_val_polynomial * 2). */
+ if (i != 0) {
+ tmp32 <<= 1;
+ }
+ sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i];
+ sum64_tmp >>= shift_internal;
+
+ /* Test overflow and sum the result. */
+ if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) ||
+ ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) {
+ /* Shift right for overflow. */
+ shift_internal += 1;
+ sum64 >>= 1;
+ sum64 += sum64_tmp >> 1;
+ } else {
+ sum64 += sum64_tmp;
+ }
+ }
+ }
+
+ word32_high = (int32_t)(sum64 >> 32);
+ word32_low = (int32_t)sum64;
+
+ // Calculate the value of shifting (shift_norm) for the 64-bit sum.
+ if(word32_high != 0) {
+ shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
+ residual_energy = (int32_t)(sum64 >> shift_norm);
+ } else {
+ if((word32_low & 0x80000000) != 0) {
+ shift_norm = 1;
+ residual_energy = (uint32_t)word32_low >> 1;
+ } else {
+ shift_norm = WebRtcSpl_NormW32(word32_low);
+ residual_energy = word32_low << shift_norm;
+ shift_norm = -shift_norm;
+ }
+ }
+
+ /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
+ * = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
+ */
+ *q_val_residual_energy = q_val_corr - shift_internal - shift_norm
+ + q_val_polynomial * 2;
+
+ return residual_energy;
+}
+
+void WebRtcIsacfix_GetLpcCoef(WebRtc_Word16 *inLoQ0,
+ WebRtc_Word16 *inHiQ0,
+ MaskFiltstr_enc *maskdata,
+ WebRtc_Word16 snrQ10,
+ const WebRtc_Word16 *pitchGains_Q12,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *lo_coeffQ15,
+ WebRtc_Word16 *hi_coeffQ15)
+{
+ int k, n, ii;
+ int pos1, pos2;
+ int sh_lo, sh_hi, sh, ssh, shMem;
+ WebRtc_Word16 varscaleQ14;
+
+ WebRtc_Word16 tmpQQlo, tmpQQhi;
+ WebRtc_Word32 tmp32;
+ WebRtc_Word16 tmp16,tmp16b;
+
+ WebRtc_Word16 polyHI[ORDERHI+1];
+ WebRtc_Word16 rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
+
+
+ WebRtc_Word16 DataLoQ6[WINLEN], DataHiQ6[WINLEN];
+ WebRtc_Word32 corrloQQ[ORDERLO+2];
+ WebRtc_Word32 corrhiQQ[ORDERHI+1];
+ WebRtc_Word32 corrlo2QQ[ORDERLO+1];
+ WebRtc_Word16 scale;
+ WebRtc_Word16 QdomLO, QdomHI, newQdomHI, newQdomLO;
+
+ WebRtc_Word32 res_nrgQQ;
+ WebRtc_Word32 sqrt_nrg;
+
+ /* less-noise-at-low-frequencies factor */
+ WebRtc_Word16 aaQ14;
+
+ /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to
+ Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032
+ */
+ WebRtc_Word16 snrq;
+ int shft;
+
+ WebRtc_Word16 tmp16a;
+ WebRtc_Word32 tmp32a, tmp32b, tmp32c;
+
+ WebRtc_Word16 a_LOQ11[ORDERLO+1];
+ WebRtc_Word16 k_vecloQ15[ORDERLO];
+ WebRtc_Word16 a_HIQ12[ORDERHI+1];
+ WebRtc_Word16 k_vechiQ15[ORDERHI];
+
+ WebRtc_Word16 stab;
+
+ snrq=snrQ10;
+
+ /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/
+ tmp16 = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(snrq, 172, 10); // Q10
+ tmp16b = exp2_Q10_T(tmp16); // Q10
+ snrq = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(tmp16b, 285, 10); // Q10
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14);
+
+ /* less-noise-at-low-frequencies factor */
+ /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint:
+ With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14,
+ we get Q16*Q14>>16 = Q14
+ */
+ aaQ14 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(
+ (WEBRTC_SPL_MUL_16_16(22938, (8192 + WEBRTC_SPL_RSHIFT_W32(varscaleQ14, 1)))
+ + ((WebRtc_Word32)32768)), 16);
+
+ /* Calculate tmp = (1.0 + aa*aa); in Q12 */
+ tmp16 = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(aaQ14, aaQ14, 15); //Q14*Q14>>15 = Q13
+ tmpQQlo = 4096 + WEBRTC_SPL_RSHIFT_W16(tmp16, 1); // Q12 + Q13>>1 = Q12
+
+ /* Calculate tmp = (1.0+aa) * (1.0+aa); */
+ tmp16 = 8192 + WEBRTC_SPL_RSHIFT_W16(aaQ14, 1); // 1+a in Q13
+ tmpQQhi = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(tmp16, tmp16, 14); //Q13*Q13>>14 = Q12
+
+ /* replace data in buffer by new look-ahead data */
+ for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) {
+ maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1];
+ }
+
+ for (k = 0; k < SUBFRAMES; k++) {
+
+ /* Update input buffer and multiply signal with window */
+ for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+ maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2];
+ maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2];
+ DataLoQ6[pos1] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
+ maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
+ DataHiQ6[pos1] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
+ maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
+ }
+ pos2 = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16(k, UPDATE)/2);
+ for (n = 0; n < UPDATE/2; n++, pos1++) {
+ maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2];
+ maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++];
+ DataLoQ6[pos1] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
+ maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
+ DataHiQ6[pos1] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
+ maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
+ }
+
+ /* Get correlation coefficients */
+ /* The highest absolute value measured inside DataLo in the test set
+ For DataHi, corresponding value was 160.
+
+ This means that it should be possible to represent the input values
+ to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 =
+ 19648). Of course, Q0 will also work, but due to the low energy in
+ DataLo and DataHi, the outputted autocorrelation will be more accurate
+ and mimic the floating point code better, by being in an high as possible
+ Q-domain.
+ */
+
+ WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale);
+ QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ
+ sh_lo = WebRtcSpl_NormW32(corrloQQ[0]);
+ QdomLO += sh_lo;
+ for (ii=0; ii<ORDERLO+2; ii++) {
+ corrloQQ[ii] = WEBRTC_SPL_LSHIFT_W32(corrloQQ[ii], sh_lo);
+ }
+ /* It is investigated whether it was possible to use 16 bits for the
+ 32-bit vector corrloQQ, but it didn't work. */
+
+ WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale);
+
+ QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ
+ sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]);
+ QdomHI += sh_hi;
+ for (ii=0; ii<ORDERHI+1; ii++) {
+ corrhiQQ[ii] = WEBRTC_SPL_LSHIFT_W32(corrhiQQ[ii], sh_hi);
+ }
+
+ /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+
+ /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/
+ corrlo2QQ[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]), 1)- // Q(12+QdomLO-16)>>1 = Q(QdomLO-5)
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]), 2); // 2*Q(14+QdomLO-16)>>3 = Q(QdomLO-2)>>2 = Q(QdomLO-5)
+
+ /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/
+ for (n = 1; n <= ORDERLO; n++) {
+
+ tmp32 = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n-1], 1) + WEBRTC_SPL_RSHIFT_W32(corrloQQ[n+1], 1); // Q(QdomLO-1)
+ corrlo2QQ[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]), 1)- // Q(12+QdomLO-16)>>1 = Q(QdomLO-5)
+ WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32), 2); // Q(14+QdomLO-1-16)>>2 = Q(QdomLO-3)>>2 = Q(QdomLO-5)
+
+ }
+ QdomLO -= 5;
+
+ /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4)
+ }
+ QdomHI -= 4;
+
+ /* add white noise floor */
+ /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */
+ /* Calculate corrlo2[0] += 9.5367431640625e-7; and
+ corrhi[0] += 9.5367431640625e-7, where the constant is 1/2^20 */
+
+ tmp32 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32) 1, QdomLO-20);
+ corrlo2QQ[0] += tmp32;
+ tmp32 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32) 1, QdomHI-20);
+ corrhiQQ[0] += tmp32;
+
+ /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following
+ code segment, where we want to make sure we get a 1-bit margin */
+ for (n = 0; n <= ORDERLO; n++) {
+ corrlo2QQ[n] = WEBRTC_SPL_RSHIFT_W32(corrlo2QQ[n], 1); // Make sure we have a 1-bit margin
+ }
+ QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin
+
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhiQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], 1); // Make sure we have a 1-bit margin
+ }
+ QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin
+
+
+ newQdomLO = QdomLO;
+
+ for (n = 0; n <= ORDERLO; n++) {
+ WebRtc_Word32 tmp, tmpB, tmpCorr;
+ WebRtc_Word16 alpha=328; //0.01 in Q15
+ WebRtc_Word16 beta=324; //(1-0.01)*0.01=0.0099 in Q15
+ WebRtc_Word16 gamma=32440; //(1-0.01)=0.99 in Q15
+
+ if (maskdata->CorrBufLoQQ[n] != 0) {
+ shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]);
+ sh = QdomLO - maskdata->CorrBufLoQdom[n];
+ if (sh<=shMem) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+ } else if ((sh-shMem)<7){
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, (sh-shMem)), tmp); // Shift alpha the number of times required to get tmp in QdomLO
+ } else {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, 6), tmp); // Shift alpha as much as possible without overflow the number of times required to get tmp in QdomHI
+ tmpCorr = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n], sh-shMem-6);
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufLoQQ[n] = tmp;
+ newQdomLO = QdomLO-(sh-shMem-6);
+ maskdata->CorrBufLoQdom[n] = newQdomLO;
+ }
+ } else
+ tmp = 0;
+
+ tmp = tmp + corrlo2QQ[n];
+
+ maskdata->CorrBufLoQQ[n] = tmp;
+ maskdata->CorrBufLoQdom[n] = QdomLO;
+
+ tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+ tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]);
+ corrlo2QQ[n] = tmp + tmpB;
+ }
+ if( newQdomLO!=QdomLO) {
+ for (n = 0; n <= ORDERLO; n++) {
+ if (maskdata->CorrBufLoQdom[n] != newQdomLO)
+ corrloQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n], maskdata->CorrBufLoQdom[n]-newQdomLO);
+ }
+ QdomLO = newQdomLO;
+ }
+
+
+ newQdomHI = QdomHI;
+
+ for (n = 0; n <= ORDERHI; n++) {
+ WebRtc_Word32 tmp, tmpB, tmpCorr;
+ WebRtc_Word16 alpha=328; //0.01 in Q15
+ WebRtc_Word16 beta=324; //(1-0.01)*0.01=0.0099 in Q15
+ WebRtc_Word16 gamma=32440; //(1-0.01)=0.99 in Q1
+ if (maskdata->CorrBufHiQQ[n] != 0) {
+ shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]);
+ sh = QdomHI - maskdata->CorrBufHiQdom[n];
+ if (sh<=shMem) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+ tmpCorr = corrhiQQ[n];
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ } else if ((sh-shMem)<7) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, (sh-shMem)), tmp); // Shift alpha the number of times required to get tmp in QdomHI
+ tmpCorr = corrhiQQ[n];
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ } else {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, 6), tmp); // Shift alpha as much as possible without overflow the number of times required to get tmp in QdomHI
+ tmpCorr = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], sh-shMem-6);
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ newQdomHI = QdomHI-(sh-shMem-6);
+ maskdata->CorrBufHiQdom[n] = newQdomHI;
+ }
+ } else {
+ tmp = corrhiQQ[n];
+ tmpCorr = tmp;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ }
+
+ tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+ tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr);
+ corrhiQQ[n] = tmp + tmpB;
+ }
+
+ if( newQdomHI!=QdomHI) {
+ for (n = 0; n <= ORDERHI; n++) {
+ if (maskdata->CorrBufHiQdom[n] != newQdomHI)
+ corrhiQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], maskdata->CorrBufHiQdom[n]-newQdomHI);
+ }
+ QdomHI = newQdomHI;
+ }
+
+ stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO);
+
+ if (stab<0) { // If unstable use lower order
+ a_LOQ11[0]=2048;
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LOQ11[n]=0;
+ }
+
+ stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8);
+ }
+
+
+ WebRtcSpl_LevinsonDurbin(corrhiQQ, a_HIQ12, k_vechiQ15, ORDERHI);
+
+ /* bandwidth expansion */
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LOQ11[n] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(kPolyVecLo[n-1], a_LOQ11[n]);
+ }
+
+
+ polyHI[0] = a_HIQ12[0];
+ for (n = 1; n <= ORDERHI; n++) {
+ a_HIQ12[n] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(kPolyVecHi[n-1], a_HIQ12[n]);
+ polyHI[n] = a_HIQ12[n];
+ }
+
+ /* Normalize the corrlo2 vector */
+ sh = WebRtcSpl_NormW32(corrlo2QQ[0]);
+ for (n = 0; n <= ORDERLO; n++) {
+ corrlo2QQ[n] = WEBRTC_SPL_LSHIFT_W32(corrlo2QQ[n], sh);
+ }
+ QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */
+
+
+ /* residual energy */
+
+ sh_lo = 31;
+ res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO,
+ kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo);
+
+ /* Convert to reflection coefficients */
+ WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo);
+
+ if (sh_lo & 0x0001) {
+ res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
+ sh_lo-=1;
+ }
+
+
+ if( res_nrgQQ > 0 )
+ {
+ sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+ /* add hearing threshold and compute the gain */
+ /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+
+ //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17); // Q14
+ tmp32a=WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) varscaleQ14,1); // H_T_HQ19=65536 (16-17=-1) ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1); // sqrt_nrg is in Qssh
+ ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1); // sqrt_nrg is in Qssh
+ sh = ssh - 14;
+ tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+ tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator)
+ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0); //Q24 (numerator)
+
+ sh = WebRtcSpl_NormW32(tmp32c);
+ shft = 16 - sh;
+ tmp16a = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator)
+
+ tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+ sh = ssh-shft-7;
+ *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17
+ }
+ else
+ {
+ *gain_lo_hiQ17 = 100; //(WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 17); // Gains in Q17
+ }
+ gain_lo_hiQ17++;
+
+ /* copy coefficients to output array */
+ for (n = 0; n < ORDERLO; n++) {
+ *lo_coeffQ15 = (WebRtc_Word16) (rcQ15_lo[n]);
+ lo_coeffQ15++;
+ }
+ /* residual energy */
+ sh_hi = 31;
+ res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI,
+ kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi);
+
+ /* Convert to reflection coefficients */
+ WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi);
+
+ if (sh_hi & 0x0001) {
+ res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
+ sh_hi-=1;
+ }
+
+
+ if( res_nrgQQ > 0 )
+ {
+ sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+
+ /* add hearing threshold and compute the gain */
+ /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+ //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17); // Q14
+ tmp32a=WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) varscaleQ14,1); // H_T_HQ19=65536 (16-17=-1)
+
+ ssh= WEBRTC_SPL_RSHIFT_W32(sh_hi, 1); // sqrt_nrg is in Qssh
+ sh = ssh - 14;
+ tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+ tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator)
+ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0); //Q24 (numerator)
+
+ sh = WebRtcSpl_NormW32(tmp32c);
+ shft = 16 - sh;
+ tmp16a = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator)
+
+ tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+ sh = ssh-shft-7;
+ *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17
+ }
+ else
+ {
+ *gain_lo_hiQ17 = 100; //(WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 17); // Gains in Q17
+ }
+ gain_lo_hiQ17++;
+
+
+ /* copy coefficients to output array */
+ for (n = 0; n < ORDERHI; n++) {
+ *hi_coeffQ15 = rcQ15_hi[n];
+ hi_coeffQ15++;
+ }
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
new file mode 100644
index 0000000..e06a207
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
@@ -0,0 +1,69 @@
+/*
+ * 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_masking_model.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "structs.h"
+
+void WebRtcIsacfix_GetVars(const WebRtc_Word16 *input,
+ const WebRtc_Word16 *pitchGains_Q12,
+ WebRtc_UWord32 *oldEnergy,
+ WebRtc_Word16 *varscale);
+
+void WebRtcIsacfix_GetLpcCoef(WebRtc_Word16 *inLoQ0,
+ WebRtc_Word16 *inHiQ0,
+ MaskFiltstr_enc *maskdata,
+ WebRtc_Word16 snrQ10,
+ const WebRtc_Word16 *pitchGains_Q12,
+ WebRtc_Word32 *gain_lo_hiQ17,
+ WebRtc_Word16 *lo_coeffQ15,
+ WebRtc_Word16 *hi_coeffQ15);
+
+typedef int32_t (*CalculateResidualEnergy)(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+extern CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int32_t WebRtcIsacfix_CalculateResidualEnergyNeon(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S
new file mode 100644
index 0000000..20b60d0
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S
@@ -0,0 +1,177 @@
+@
+@ 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.
+@
+
+@ Contains a function for WebRtcIsacfix_CalculateResidualEnergyNeon() in
+@ iSAC codec, optimized for ARM Neon platform. Reference code in
+@ lpc_masking_model.c.
+
+.arch armv7-a
+.fpu neon
+.global WebRtcIsacfix_CalculateResidualEnergyNeon
+.align 2
+
+@ int32_t WebRtcIsacfix_CalculateResidualEnergyNeon(int lpc_order,
+@ int32_t q_val_corr,
+@ int q_val_polynomial,
+@ int16_t* a_polynomial,
+@ int32_t* corr_coeffs,
+@ int* q_val_residual_energy);
+
+WebRtcIsacfix_CalculateResidualEnergyNeon:
+.fnstart
+.save {r4-r11}
+ push {r4-r11}
+
+ sub r13, r13, #16
+ str r1, [r13, #8]
+ str r2, [r13, #12]
+
+ mov r4, #1
+ vmov.s64 q11, #0 @ Initialize shift_internal.
+ vmov.s64 q13, #0 @ Initialize sum64.
+ vmov.s64 q10, #0
+ vmov.u8 d20[0], r4 @ Set q10 to 1.
+
+ cmp r0, #0
+ blt POST_LOOP_I
+
+ add r9, r3, r0, asl #1 @ &a_polynomial[lpc_order]
+ mov r6, #0 @ Loop counter i.
+ ldr r11, [r13, #48]
+ sub r10, r0, #1
+ mov r7, r3 @ &a_polynomial[0]
+ str r9, [r13, #4]
+
+LOOP_I:
+ ldr r2, [r11], #4 @ corr_coeffs[i]
+ vmov.s64 q15, #0 @ Initialize the sum64_tmp.
+ vdup.s32 d25, r2
+
+ cmp r0, r6 @ Compare lpc_order to i.
+ movle r2, r6
+ ble POST_LOOP_J
+
+ mov r1, r6 @ j = i;
+ mov r12, r7 @ &a_polynomial[i]
+ mov r4, r3 @ &a_polynomial[j - i]
+
+LOOP_J:
+ ldr r8, [r12], #4
+ ldr r5, [r4], #4
+ vmov.u32 d0[0], r8
+ vmov.u32 d1[0], r5
+ vmull.s16 q0, d0, d1
+ vmull.s32 q0, d0, d25
+ cmp r6, #0 @ i == 0?
+ vshl.s64 q0, q11
+ beq SUM1
+ vshl.s64 q0, #1
+
+SUM1:
+ vqadd.s64 q14, q0, q15 @ Sum and test overflow.
+ add r1, r1, #2
+ bvc MOV1 @ Skip the shift if there's no overflow.
+ vshr.s64 q0, #1
+ vshr.s64 q15, #1
+ vadd.s64 q14, q0, q15
+ vsub.s64 q11, q10
+
+MOV1:
+ cmp r0, r1 @ Compare lpc_order to j.
+ vmov.s64 q15, q14
+ bgt LOOP_J
+
+ bic r1, r10, #1
+ add r2, r6, #2
+ add r2, r1, r2
+
+POST_LOOP_J:
+ vqadd.s64 q0, q13, q15 @ Sum and test overflow.
+ bvc MOV2 @ Skip the shift if there's no overflow.
+ vshr.s64 q13, #1
+ vshr.s64 q15, #1
+ vadd.s64 q0, q13, q15
+ vsub.s64 q11, q10
+
+MOV2:
+ vmov.s64 q13, q0 @ update sum64.
+ cmp r2, r0
+ bne CHECK_LOOP_CONDITION
+
+ @ Last sample in the inner loop.
+ ldr r4, [r13, #4]
+ ldrsh r8, [r4]
+ ldrsh r12, [r9]
+ mul r8, r8, r12
+ vmov.s32 d0[0], r8
+ vmull.s32 q0, d0, d25
+ cmp r6, #0 @ i == 0?
+ vshl.s64 q0, q11
+ beq SUM2
+ vshl.s64 q0, #1
+
+SUM2:
+ vqadd.s64 d1, d0, d26 @ Sum and test overflow.
+ bvc MOV3 @ Skip the shift if there's no overflow.
+ vshr.s64 q13, #1
+ vshr.s64 d0, #1
+ vadd.s64 d1, d0, d26
+ vsub.s64 q11, q10
+
+MOV3:
+ vmov.s64 d26, d1 @ update sum64.
+
+CHECK_LOOP_CONDITION:
+ add r6, r6, #1
+ sub r9, r9, #2
+ cmp r0, r6 @ Compare i to lpc_order.
+ sub r10, r10, #1
+ add r7, r7, #2
+ bge LOOP_I
+
+POST_LOOP_I:
+ mov r3, #0
+ vqadd.s64 d0, d26, d27 @ Sum and test overflow.
+ bvc GET_SHIFT_NORM @ Skip the shift if there's no overflow.
+ vshr.s64 q13, #1
+ vadd.s64 d0, d26, d27
+ vsub.s64 q11, q10
+
+GET_SHIFT_NORM:
+ vcls.s32 d1, d0 @ Count leading extra sign bits.
+ vmov.32 r2, d1[1] @ Store # of sign bits of only the 32 MSBs.
+ vmovl.s32 q1, d1
+ vshl.s64 d0, d3 @ d3 contains # of sign bits of the 32 MSBs.
+
+ vcls.s32 d1, d0 @ Count again the leading extra sign bits.
+ vmov.s32 r1, d1[1] @ Store # of sign bits of only the 32 MSBs.
+ vmovl.s32 q1, d1
+ vshl.s64 d0, d3 @ d3 contains # of sign bits of the 32 MSBs.
+
+ vmov.s32 r0, d0[1] @ residual_energy
+ vmov.s32 r3, d22[0] @ shift_internal
+
+ @ Calculate the value for q_val_residual_energy.
+ ldr r4, [r13, #8] @ q_val_corr
+ ldr r5, [r13, #12] @ q_val_polynomial
+ sub r12, r4, #32
+ add r12, r12, r5, asl #1
+ add r1, r12, r1 @ add 1st part of shift_internal.
+ add r12, r1, r2 @ add 2nd part of shift_internal.
+ ldr r2, [r13, #52]
+ add r3, r12, r3 @ value for q_val_residual_energy.
+ str r3, [r2, #0]
+
+ add r13, r13, #16
+ pop {r4-r11}
+ bx r14
+
+.fnend
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c b/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
new file mode 100644
index 0000000..90cc9af
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
@@ -0,0 +1,1280 @@
+/*
+ * 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_tables.c
+ *
+ * Coding tables for the KLT coefficients
+ *
+ */
+
+
+#include "settings.h"
+#include "lpc_tables.h"
+
+/* indices of KLT coefficients used */
+const WebRtc_UWord16 WebRtcIsacfix_kSelIndGain[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11};
+
+const WebRtc_UWord16 WebRtcIsacfix_kSelIndShape[108] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107
+};
+
+/* cdf array for model indicator */
+const WebRtc_UWord16 WebRtcIsacfix_kModelCdf[4] = {
+ 0, 15434, 37548, 65535
+};
+
+/* pointer to cdf array for model indicator */
+const WebRtc_UWord16 *WebRtcIsacfix_kModelCdfPtr[1] = {
+ WebRtcIsacfix_kModelCdf
+};
+
+/* initial cdf index for decoder of model indicator */
+const WebRtc_UWord16 WebRtcIsacfix_kModelInitIndex[1] = {
+ 1
+};
+
+/* offset to go from rounded value to quantization index */
+const WebRtc_Word16 WebRtcIsacfix_kQuantMinGain[12] ={
+ 3, 6, 4, 6, 6, 9, 5, 16, 11, 34, 32, 47
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kQuantMinShape[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 WebRtcIsacfix_kMaxIndGain[12] = {
+ 6, 12, 8, 14, 10, 19, 12, 31, 22, 56, 52, 138
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kMaxIndShape[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 WebRtcIsacfix_kOffsetGain[3][12] = {
+ { 0, 7, 20, 29, 44, 55, 75, 88, 120, 143, 200, 253},
+ { 0, 7, 19, 27, 42, 53, 73, 86, 117, 140, 197, 249},
+ { 0, 7, 20, 28, 44, 55, 75, 89, 121, 145, 202, 257}
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kOffsetShape[3][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
+ },
+ {
+ 0, 1, 2, 3, 4, 6, 7, 8, 9, 11,
+ 13, 16, 19, 22, 26, 29, 34, 39, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 55, 57, 60,
+ 63, 66, 70, 73, 78, 84, 91, 92, 93, 94,
+ 95, 96, 97, 99, 102, 105, 108, 111, 114, 118,
+ 123, 128, 134, 141, 151, 152, 153, 154, 156, 159,
+ 162, 165, 168, 171, 174, 177, 181, 186, 194, 200,
+ 208, 218, 233, 234, 235, 236, 239, 242, 245, 248,
+ 251, 254, 258, 263, 270, 277, 288, 297, 308, 324,
+ 349, 351, 354, 357, 361, 366, 372, 378, 383, 390,
+ 398, 407, 420, 431, 450, 472, 496, 524
+ },
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 11,
+ 14, 17, 20, 23, 26, 29, 34, 40, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 58, 61, 64,
+ 67, 70, 73, 77, 82, 88, 96, 97, 98, 99,
+ 101, 102, 104, 107, 110, 113, 116, 119, 122, 125,
+ 129, 134, 141, 150, 160, 161, 162, 163, 166, 168,
+ 171, 174, 177, 180, 183, 186, 190, 195, 201, 208,
+ 216, 226, 243, 244, 245, 248, 251, 254, 257, 260,
+ 263, 268, 273, 278, 284, 291, 299, 310, 323, 340,
+ 366, 368, 371, 374, 379, 383, 389, 394, 399, 406,
+ 414, 422, 433, 445, 461, 480, 505, 533
+ }
+};
+
+/* initial cdf index for KLT coefficients */
+const WebRtc_UWord16 WebRtcIsacfix_kInitIndexGain[3][12] = {
+ { 3, 6, 4, 7, 5, 10, 6, 16, 11, 28, 26, 69},
+ { 3, 6, 4, 7, 5, 10, 6, 15, 11, 28, 26, 69},
+ { 3, 6, 4, 8, 5, 10, 7, 16, 12, 28, 27, 70}
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kInitIndexShape[3][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
+ },
+ {
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 1, 1, 1, 2, 1, 2, 2, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 2, 1, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 3, 3, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 4, 3, 4,
+ 5, 7, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 2, 2, 3, 3, 5, 4, 5, 8, 12,
+ 1, 1, 1, 2, 2, 3, 3, 2, 3, 4,
+ 4, 6, 5, 9, 11, 12, 14, 25
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 2, 3, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 3, 4, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 3, 3, 4,
+ 5, 8, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 3, 3, 4, 5, 6, 8, 13,
+ 1, 1, 1, 2, 2, 3, 2, 2, 3, 4,
+ 4, 5, 6, 8, 9, 12, 14, 25
+ }
+};
+
+/* offsets for quantizer representation levels*/
+const WebRtc_UWord16 WebRtcIsacfix_kOfLevelsGain[3] = {
+ 0, 392, 779
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kOfLevelsShape[3] = {
+ 0, 578, 1152
+};
+
+/* quantizer representation levels */
+
+
+
+const WebRtc_Word32 WebRtcIsacfix_kLevelsGainQ17[1176] = {
+ -364547,-231664,-102123,-573,104807,238257,368823,-758583,-640135,-510291
+ ,-377662,-252785,-113177,2627,112906,248601,389461,522691,644517,763974
+ ,-538963,-368179,-245823,-106095,-890,104299,241111,350730,493190,-800763
+ ,-646230,-510239,-382115,-248623,-111829,-2983,113852,251105,388114,519757
+ ,644048,774712,896334,1057931,-770009,-635310,-503690,-375087,-248106,-108525
+ ,-105,108259,243472,377948,519271,-1160885,-1032044,-914636,-777593,-647891
+ ,-518408,-388028,-254321,-115293,-598,117849,251296,385367,515510,652727
+ ,777432,920363,1038625,1153637,1316836,-632287,-505430,-379430,-248458,-118013
+ ,-888,118762,250266,381650,513327,652169,766471,932113,-2107480,-1971030
+ ,-1827020,-1698263,-1558670,-1436314,-1305377,-1172252,-1047355,-914202,-779651,-651001
+ ,-520999,-390394,-255761,-123490,-1893,126839,256703,385493,518607,651760
+ ,782750,908693,1044131,1163865,1311066,1424177,1582628,1709823,1831740,1955391
+ ,-1423044,-1288917,-1181281,-1043222,-911770,-780354,-646799,-522664,-386721,-258266
+ ,-128060,-1101,128233,259996,390336,519590,649290,778701,908010,1040796
+ ,1161235,1306889,1441882,-4446002,-4301031,-4194304,-4080591,-3947740,-3808975,-3686530
+ ,-3567839,-3383251,-3287089,-3136577,-3017405,-2869860,-2751321,-2619984,-2482932,-2354790
+ ,-2223147,-2090669,-1964135,-1831208,-1706697,-1570817,-1446008,-1305386,-1175773,-1046066
+ ,-915356,-785120,-653614,-524331,-393767,-260442,-130187,-799,128841,261466
+ ,393616,520542,652117,784613,914159,1045399,1181072,1308971,1442502,1570346
+ ,1693912,1843986,1966014,2090474,2224869,2364593,2475934,2628403,2752512,2856640
+ ,-4192441,-4063232,-3917821,-3799195,-3666233,-3519199,-3411021,-3269192,-3135684,-3008826
+ ,-2880875,-2747342,-2620981,-2494872,-2354979,-2229718,-2098939,-1964971,-1835399,-1703452
+ ,-1572806,-1440482,-1311794,-1179338,-1046521,-919823,-785914,-655335,-523416,-395507
+ ,-264833,-132184,-2546,131698,256217,391372,522688,651248,789964,909618
+ ,1035305,1179145,1313824,1436934,1552353,1693722,1815508,1972826,2096328,2228224
+ ,2359296,2490368,2598848,-6160384,-6029312,-5881382,-5767168,-5636096,-5505024,-5373952
+ ,-5228418,-5110384,-4954923,-4880576,-4710990,-4587364,-4471340,-4333905,-4211513,-4051293
+ ,-3907927,-3800105,-3675961,-3538640,-3413663,-3271148,-3152105,-3019103,-2869647,-2744015
+ ,-2620639,-2479385,-2364211,-2227611,-2095427,-1974497,-1834168,-1703561,-1568961,-1439826
+ ,-1309192,-1174050,-1050191,-917836,-786015,-656943,-518934,-394831,-257708,-128041
+ ,1610,128991,264442,393977,521383,653849,788164,918641,1049122,1181971
+ ,1308934,1439505,1571808,1706305,1836318,1966235,2097269,2228990,2357005,2490292
+ ,2617400,2749680,2881234,3014880,3145637,3276467,3409099,3536637,3671493,3802918
+ ,3929740,4065036,4194143,4325999,4456126,4586857,4717194,4843923,4978676,5110913
+ ,5245281,5371394,5499780,5633779,5762611,5897682,6028688,6167546,6296465,6421682
+ ,6548882,6682074,6809432,6941956,7078143,7204509,7334296,7475137,7609896,7732044
+ ,7861604,8002039,8131670,8259222,8390299,8522399,8650037,8782348,8908402,9037815
+ ,9164594,9300338,9434679,9574500,9699702,9833934,9948152,10083972,10244937,10332822
+ ,10485760,10600122,10760754,10892964,11010048,11111004,11272192,11403264,11525091,11624984
+ ,11796480,11915146,-393216,-262144,-101702,-740,100568,262144,393216,-786432
+ ,-655360,-524288,-383907,-243301,-94956,-156,95547,269629,416691,524288
+ ,655360,-393216,-262144,-88448,-37,87318,262144,393216,524288,-917504
+ ,-786432,-655360,-495894,-373308,-267503,-93211,4119,91308,250895,393216
+ ,526138,655360,786432,917504,-786432,-655360,-524288,-393216,-262144,-83497
+ ,222,86893,240922,393216,524288,-1048576,-917504,-790472,-655360,-508639
+ ,-383609,-262016,-95550,-3775,96692,256797,364847,534906,655360,786432
+ ,889679,1048576,1179648,1310720,1441792,-655360,-524288,-377684,-248408,-93690
+ ,1261,95441,227519,393216,524288,655360,786432,917504,-2097152,-1966080
+ ,-1809470,-1703936,-1572864,-1441792,-1314289,-1195149,-1056205,-917504,-809951,-657769
+ ,-521072,-383788,-248747,-106350,-2944,105550,243408,388548,521064,628732
+ ,786432,885456,1064548,1179648,1310720,1441792,1572864,1703936,1835008,-1441792
+ ,-1310720,-1179648,-1037570,-888492,-767774,-646634,-519935,-373458,-248029,-111915
+ ,760,111232,247735,379432,507672,672699,786432,917504,1048576,1179648
+ ,1310720,1441792,-4456448,-4325376,-4194304,-4063232,-3932160,-3801088,-3670016,-3538944
+ ,-3407872,-3276800,-3145728,-3014656,-2883584,-2752512,-2647002,-2490368,-2359296,-2228224
+ ,-2097152,-1951753,-1835008,-1703936,-1594177,-1462001,-1289150,-1160774,-1025917,-924928
+ ,-782509,-641294,-516191,-386630,-251910,-118886,5210,121226,253949,386008
+ ,517973,649374,780064,917783,1052462,1183856,1290593,1419389,1556641,1699884
+ ,1835008,1988314,2090470,2228224,2359296,2490368,2621440,2752512,2883584,-3801088
+ ,-3643514,-3539937,-3409931,-3263294,-3145658,-3012952,-2879230,-2752359,-2622556,-2483471
+ ,-2357556,-2226500,-2093112,-1965892,-1833664,-1701035,-1567767,-1440320,-1310556,-1178339
+ ,-1049625,-916812,-786477,-655277,-525050,-393773,-264828,-130696,-480,132126
+ ,260116,394197,527846,652294,785563,917183,1049511,1175958,1308161,1438759
+ ,1572253,1698835,1828535,1967072,2089391,2212798,2348901,2461547,2621440,2752512
+ ,2883584,-7309870,-7203780,-7062699,-6939106,-6790819,-6672036,-6553600,-6422317,-6288422
+ ,-6164694,-6026456,-5901410,-5754168,-5621459,-5502710,-5369686,-5240454,-5120712,-4976140
+ ,-4847970,-4723070,-4589083,-4450923,-4324680,-4189892,-4065551,-3931803,-3800209,-3668539
+ ,-3539395,-3404801,-3277470,-3141389,-3016710,-2885724,-2752612,-2618541,-2486762,-2354153
+ ,-2225059,-2094984,-1968194,-1830895,-1699508,-1575743,-1444516,-1308683,-1179714,-1053088
+ ,-917981,-783707,-653900,-524980,-395409,-260309,-131948,-3452,132113,263241
+ ,392185,522597,654134,788288,919810,1045795,1179210,1314201,1444235,1574447
+ ,1705193,1834009,1967332,2098102,2229019,2359147,2489859,2619878,2754966,2879671
+ ,3014438,3146143,3276733,3405958,3542196,3667493,3798815,3932961,4062458,4187125
+ ,4322346,4454875,4587752,4716809,4848274,4975027,5111957,5242215,5373085,5501158
+ ,5640140,5762918,5895358,6024008,6157906,6290628,6422713,6546339,6675888,6815606
+ ,6955288,7077501,7211630,7337893,7473635,7607175,7728310,7866475,7999658,8127888
+ ,8241758,8386483,8522550,8641582,8771915,8922139,9038632,9179385,9313426,9437184
+ ,9568256,9699328,9830400,9952933,10120004,10223616,10354688,10474645,10616832,-393216
+ ,-262144,-85425,-121,82533,262144,393216,-786432,-655360,-524288,-379928
+ ,-222821,-95200,287,95541,227093,393216,493567,655360,786432,-393216
+ ,-262144,-86805,510,86722,262144,393216,524288,-1048576,-917504,-786432
+ ,-624456,-529951,-395071,-241627,-101168,81,99975,241605,393216,524288
+ ,655360,786432,917504,-786432,-655360,-524288,-393216,-230359,-95619,-137
+ ,94425,226222,393216,524288,-1179648,-1048576,-917504,-773841,-655360,-492258
+ ,-379715,-244707,-103621,-434,104523,242680,381575,523659,650565,786432
+ ,917504,1048576,1179648,1310720,-786432,-629344,-524288,-376757,-242858,-101932
+ ,-2715,107155,239212,366480,514943,655360,786432,917504,-2228224,-2097152
+ ,-1966080,-1835008,-1703936,-1572864,-1441792,-1284584,-1179648,-1048819,-934658,-777181
+ ,-626371,-515660,-377493,-248975,-113036,436,113584,248354,379718,512475
+ ,653932,796494,917504,1048576,1179648,1310720,1441792,1572864,1703936,1835008
+ ,-1572864,-1441792,-1297608,-1161159,-1032316,-917092,-779770,-647384,-515529,-384269
+ ,-250003,-119252,1053,118111,249512,380545,512039,648101,770656,907003
+ ,1021725,1178082,1310720,1441792,-4587520,-4456448,-4325376,-4194304,-4063232,-3932160
+ ,-3801088,-3670016,-3538944,-3407872,-3276800,-3145728,-2999335,-2883584,-2752512,-2621440
+ ,-2490368,-2359296,-2228224,-2112691,-1966080,-1848781,-1709830,-1566109,-1438427,-1303530
+ ,-1176124,-1040936,-913876,-784585,-652025,-518361,-385267,-256342,-127297,-2733
+ ,125422,257792,389363,519911,651106,783805,909407,1044143,1174156,1309267
+ ,1436173,1553771,1708958,1814083,1967036,2095386,2255169,2359296,2478303,2621440
+ ,2752512,-4456448,-4325376,-4194304,-4063232,-3932160,-3797524,-3670016,-3560250,-3413217
+ ,-3257719,-3166416,-2986626,-2878000,-2781144,-2625383,-2495465,-2346792,-2230930,-2077063
+ ,-1949225,-1819274,-1697261,-1568664,-1443074,-1304302,-1175289,-1043794,-913423,-785561
+ ,-652104,-522835,-392667,-260517,-130088,-2,129509,260990,391931,522470
+ ,655770,784902,917093,1046445,1176951,1303121,1441362,1565401,1702022,1822856
+ ,1952852,2090384,2214607,2338436,2457483,2621440,-8781824,-8650752,-8519680,-8388608
+ ,-8260828,-8126464,-8003337,-7859030,-7750057,-7602176,-7471104,-7340032,-7193045,-7090588
+ ,-6946816,-6843344,-6676635,-6557575,-6447804,-6277614,-6159736,-6035729,-5884723,-5739567
+ ,-5634818,-5489867,-5372864,-5243300,-5098939,-4988639,-4856258,-4728494,-4591717,-4447428
+ ,-4322409,-4192918,-4062638,-3934141,-3797545,-3673373,-3531587,-3407391,-3277404,-3147797
+ ,-3013578,-2886548,-2749811,-2616428,-2490949,-2361301,-2228482,-2096883,-1964343,-1831754
+ ,-1702201,-1572495,-1442012,-1309242,-1182451,-1048996,-916905,-786510,-657079,-524730
+ ,-393672,-261313,-128743,166,130678,261334,393287,524155,655570,786839
+ ,917353,1052167,1179013,1309360,1442634,1571153,1703961,1832027,1965014,2097912
+ ,2224861,2355341,2490455,2623051,2753484,2877015,3015783,3144157,3273705,3405255
+ ,3542006,3669580,3802417,3935413,4065088,4190896,4333521,4456355,4579781,4713832
+ ,4845707,4978625,5113278,5243817,5382318,5500592,5638135,5761179,5900822,6029270
+ ,6186398,6297816,6436435,6559163,6666389,6806548,6950461,7086078,7195777,7350973
+ ,7480132,7614852,7743514,7847288,8014762,8126464,8257536,8388608,8519680,8650752
+ ,8781824,8912896,9043968,9175040,9306112,9437184
+};
+
+
+
+const WebRtc_Word16 WebRtcIsacfix_kLevelsShapeQ10[1735] = {
+ 0, 0, -1, 0, 0, 1, 0, 1, 0, -821
+ , 1, -763, -1, 656, -620, 0, 633, -636, 4, 615
+ , -630, 1, 649, -1773, -670, 5, 678, 1810, -1876, -676
+ , 0, 691, 1843, -1806, -743, -1, 749, 1795, 2920, -2872
+ , -1761, -772, -3, 790, 1763, 2942, 0, 0, 0, 0
+ , -792, 2, 0, 0, 1, 0, -854, 0, -702, -1
+ , 662, -624, -5, 638, -611, -6, 638, -647, 0, 651
+ , -685, -4, 679, 2123, -1814, -693, 0, 664, 1791, -1735
+ , -737, 0, 771, 1854, 2873, -2867, -1842, -793, -1, 821
+ , 1826, 2805, 3922, 0, 0, 0, -1, -779, 1, 786
+ , 1, -708, 0, 789, -799, 1, 797, -663, 2, 646
+ , -600, 3, 609, -600, 1, 658, 1807, -627, -3, 612
+ , -625, 3, 632, -1732, -674, 1, 672, 2048, -1768, -715
+ , 0, 724, 1784, -3881, -3072, -1774, -719, -1, 730, 1811
+ , -2963, -1829, -806, -1, 816, 1795, 3050, -5389, -3784, -2942
+ , -1893, -865, -12, 867, 1885, 2945, 3928, -2, 1, 4
+ , 0, -694, 2, 665, -598, 5, 587, -599, -1, 661
+ , -656, -7, 611, -607, 5, 603, -618, -4, 620, -1794
+ , -645, -2, 654, -655, -1, 658, -1801, -700, 5, 707
+ , 1927, -1752, -745, -8, 752, 1843, -2838, -1781, -801, 11
+ , 796, 1811, 2942, 3866, -3849, -3026, -1848, -819, 2, 827
+ , 1825, 2963, -3873, -2904, -1869, -910, -6, 903, 1902, 2885
+ , 3978, 5286, -7168, -6081, -4989, -3968, -2963, -1970, -943, -2
+ , 953, 1951, 2968, 3974, 5009, 6032, -2, 3, -1024, 2
+ , 1024, -637, 1, 669, -613, -7, 630, -603, 4, 612
+ , -612, 0, 590, -645, -11, 627, -657, -2, 671, 1849
+ , -1853, -694, 2, 702, 1838, -3304, -1780, -736, -8, 732
+ , 1772, -1709, -755, -6, 760, 1780, -2994, -1780, -800, 8
+ , 819, 1830, 2816, -4096, -2822, -1881, -851, -4, 855, 1872
+ , 2840, 3899, -3908, -2904, -1878, -887, 6, 897, 1872, 2942
+ , 4008, -4992, -3881, -2933, -1915, -928, 1, 937, 1919, 2900
+ , 4009, 4881, -6848, -6157, -5065, -3981, -2983, -1972, -978, -1
+ , 968, 1979, 2988, 4008, 5007, 6108, 7003, 8051, 9027,-13272
+ ,-12012,-11228,-10213, -9261, -8084, -7133, -6075, -5052, -4050, -3036
+ , -2014, -996, -4, 1007, 2031, 3038, 4049, 5074, 6134, 7069
+ , 8094, 9069, 10212, 11049, 12104, 51, -1024, -13, 1024, -609
+ , -107, 613, -2048, -687, -95, 667, 2048, -3072, -1724, -785
+ , -34, 732, 1819, -2048, -703, -26, 681, 2048, -2048, -686
+ , -9, 665, 2048, -2048, -702, 37, 748, 1723, -4096, -2786
+ , -1844, -837, 37, 811, 1742, 3072, -4096, -2783, -1848, -881
+ , 39, 898, 1843, 2792, 3764, -5120, -4096, -2923, -1833, -852
+ , -14, 862, 1824, 2834, 4096, -6144, -5120, -3914, -2842, -1870
+ , -886, -27, 888, 1929, 2931, 4051, -7168, -6144, -5120, -3866
+ , -2933, -1915, -927, 64, 933, 1902, 2929, 3912, 5063, 6144
+ ,-11264,-10240, -9216, -8192, -7086, -6144, -5039, -3972, -2943, -1929
+ , -941, 3, 938, 1942, 2959, 3933, 4905, 6088, 6983, 8192
+ , -9216, -8192, -7202, -6088, -4983, -4019, -2955, -1975, -966, 17
+ , 997, 1981, 2967, 3990, 4948, 6022, 6967, 8192,-13312,-12288
+ ,-11264,-10240, -9216, -8049, -6997, -6040, -5026, -4043, -3029, -2034
+ , -1015, -23, 984, 1997, 3010, 4038, 5002, 6015, 6946, 8061
+ , 9216, 10240,-12381,-11264,-10240, -9060, -8058, -7153, -6085, -5075
+ , -4051, -3042, -2037, -1017, -5, 1007, 2028, 3035, 4050, 5088
+ , 6111, 7160, 8156, 9215, 10095, 11229, 12202, 13016,-26624,-25600
+ ,-24582,-23671,-22674,-21400,-20355,-19508,-18315,-17269,-16361,-15299
+ ,-14363,-13294,-12262,-11237,-10203, -9227, -8165, -7156, -6116, -5122
+ , -4076, -3056, -2043, -1020, -8, 1027, 2047, 3065, 4110, 5130
+ , 6125, 7168, 8195, 9206, 10230, 11227, 12256, 13304, 14281, 15316
+ , 16374, 17382, 18428, 19388, 20361, 21468, 22448, 23781, 0, 0
+ , -1, 0, -2, 1024, 0, 0, 0, -1, 1024, -1024
+ , 1, -1024, 4, 1024, -1024, 2, 1024, -1024, 2, 1024
+ , -2048, -1024, -4, 1024, -1024, 2, 1024, -2048, -1024, -3
+ , 1024, 2048, -2048, -1024, 4, 1024, 2048, -3072, -2048, -1024
+ , -1, 662, 2048, 0, 1, 0, 0, 1, -2, -2
+ , 0, 2, 1024, -1, 1024, -1024, 4, 1024, -1024, 1
+ , 1024, -1024, 1, 1024, -2048, -781, -4, 844, -807, -5
+ , 866, -2048, -726, -13, 777, 2048, -2048, -643, -4, 617
+ , 2048, 3072, -3072, -2048, -629, 1, 630, 2048, 3072, 0
+ , -1, 1, -2, 2, 1, -1024, 5, -1024, 6, 1024
+ , -1024, 4, 1024, -1024, 1, 1024, -1024, -9, 1024, -673
+ , -7, 655, -2048, -665, -15, 716, -2048, -647, 4, 640
+ , 2048, -2048, -615, -1, 635, 2048, -2048, -613, 10, 637
+ , 2048, 3072, -3072, -2048, -647, -3, 641, 2048, 3072, -5120
+ , -4096, -3072, -2048, -681, 6, 685, 2048, 3072, 4096, 1
+ , 1, 0, -1, 1024, -1024, -3, 1024, -1024, 6, 1024
+ , -1024, -1, 769, -733, 0, 1024, -876, -2, 653, -1024
+ , -4, 786, -596, -13, 595, -634, -2, 638, 2048, -2048
+ , -620, -5, 620, 2048, -4096, -3072, -2048, -639, 11, 655
+ , 2048, 3072, -3072, -2048, -659, 5, 663, 2048, -3072, -1823
+ , -687, 22, 695, 2048, 3072, 4096, -4096, -3072, -1848, -715
+ , -3, 727, 1816, 3072, 4096, 5120, -8192, -7168, -6144, -5120
+ , -4096, -2884, -1771, -756, -14, 775, 1844, 3072, 4096, 5120
+ , 6144, -1, 1, 0, -1024, 2, 815, -768, 2, 708
+ , -1024, -3, 693, -661, -7, 607, -643, -5, 609, -624
+ , 3, 631, -682, -3, 691, 2048, -2048, -640, 5, 650
+ , 2048, -3072, -2048, -701, 9, 704, 2048, 3072, -3072, -2048
+ , -670, 10, 674, 2048, 3072, -5120, -4096, -3072, -1749, -738
+ , 0, 733, 1811, 3072, 4096, 5120, -4096, -3072, -1873, -753
+ , 0, 756, 1874, 3072, 4096, -5120, -4096, -2900, -1838, -793
+ , -6, 793, 1868, 2837, 4096, 5120, -7168, -6144, -5120, -4096
+ , -2832, -1891, -828, 1, 828, 1901, 2823, 3912, 5120, 6144
+ , 7168, 8192,-13312,-12288,-11264,-10240, -9216, -8192, -7168, -6144
+ , -5120, -3976, -3004, -1911, -869, 7, 869, 1932, 3024, 3992
+ , 5009, 6144, 7168, 8192, 9216, 10240, 11264, -4, 1024, -629
+ , -22, 609, -623, 9, 640, -2048, -768, 1, 682, -2048
+ , -741, 49, 722, 2048, -3072, -1706, -808, -20, 768, 1750
+ , -1684, -727, -29, 788, 1840, 3033, -1758, -784, 0, 801
+ , 1702, -3072, -1813, -814, 38, 820, 1884, 2927, -4096, -3241
+ , -1839, -922, 25, 882, 1886, 2812, -4096, -2982, -1923, -894
+ , 84, 912, 1869, 2778, 4096, -4928, -3965, -2902, -1920, -883
+ , 3, 917, 1953, 2921, 3957, 4922, 6144, 7168, -5120, -3916
+ , -2897, -1949, -930, 31, 959, 1934, 2901, 3851, 5120, -9216
+ , -8192, -7046, -6029, -5030, -4034, -2980, -1969, -1013, -76, 963
+ , 1963, 2901, 3929, 4893, 6270, 7168, 8192, 9216,-12288,-11264
+ ,-10240, -9216, -8192, -6846, -6123, -5108, -4008, -3000, -1963, -954
+ , -6, 958, 1992, 3009, 4020, 5085, 6097, 7168, 8192, 9216
+ ,-11264,-10139, -9194, -8127, -7156, -6102, -5053, -4049, -3036, -2025
+ , -1009, -34, 974, 1984, 3034, 4028, 5138, 6000, 7057, 8166
+ , 9070, 10033, 11360, 12288,-13312,-12288,-10932,-10190, -9120, -8123
+ , -7128, -6103, -5074, -4081, -3053, -2029, -989, -4, 1010, 2028
+ , 3051, 4073, 5071, 6099, 7132, 8147, 9295, 10159, 11023, 12263
+ , 13312, 14336,-25600,-24576,-23552,-22529,-21504,-20480,-19456,-18637
+ ,-17425,-16165,-15316,-14327,-13606,-12135,-11182,-10107, -9153, -8144
+ , -7146, -6160, -5129, -4095, -3064, -2038, -1025, 1, 1031, 2072
+ , 3074, 4088, 5123, 6149, 7157, 8173, 9198, 10244, 11250, 12268
+ , 13263, 14289, 15351, 16370, 17402, 18413, 19474, 20337, 21386, 22521
+ , 23367, 24350, 0, 0, 0, 0, 0, 0, 0, 0
+ , -1024, 0, 1024, -1024, 0, 1024, -1024, 0, 1024, -1024
+ , 0, 1024, -1024, 0, 1024, -773, 0, 1024, -674, 0
+ , 645, -2048, -745, 0, 628, 2048, -2048, -712, 0, 681
+ , 2048, 3072, -3072, -2048, -673, 0, 682, 1964, 3257, 0
+ , 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024
+ , -1024, 0, 1024, -1024, 0, 1024, -705, 0, 623, -771
+ , 0, 1024, -786, 0, 688, -631, 0, 652, 2048, -2048
+ , -627, -1, 666, 2048, -3072, -1756, -694, 0, 674, 2048
+ , -3098, -1879, -720, 5, 694, 1886, 2958, 4096, 0, 0
+ , 0, 0, 1024, 0, 0, 1024, -769, 0, 1024, -1024
+ , 0, 1024, -1024, 0, 1024, -817, 0, 734, -786, 0
+ , 651, -638, 0, 637, -623, 0, 671, -652, 0, 619
+ , 2048, -2048, -670, -1, 663, 2048, -1908, -680, 1, 686
+ , 2048, 3072, 4096, -4096, -3072, -1833, -711, 0, 727, 1747
+ , 3072, 4096, -4096, -2971, -1826, -762, 2, 766, 1832, 2852
+ , 3928, 5079, 0, 0, 0, -1024, 0, 1024, -1024, 0
+ , -656, 0, 1024, -599, 0, 620, -1024, 0, 1024, -603
+ , 0, 622, -643, 0, 660, -599, 0, 611, -641, -1
+ , 651, 2048, -2048, -648, -2, 647, 1798, -3072, -2048, -672
+ , 2, 670, 2048, -3072, -1780, -694, -1, 706, 1751, 3072
+ , -3072, -1862, -757, 7, 739, 1798, 3072, 4096, -5120, -4096
+ , -3253, -1811, -787, 3, 782, 1887, 3123, 4096, -7252, -6144
+ , -5354, -4060, -2864, -1863, -820, -11, 847, 1903, 2970, 3851
+ , 4921, 5957, 7168, 8192, 9306, 0, 0, -1024, 0, 1024
+ , -726, 0, 706, -692, 0, 593, -598, 0, 616, -624
+ , 0, 616, -605, 0, 613, -2048, -652, 1, 635, 2048
+ , -2048, -647, -1, 660, 2048, -1811, -668, -2, 685, 2048
+ , -1796, -731, -2, 730, 1702, 3072, -3072, -1766, -747, -4
+ , 756, 1770, 3072, -4096, -3024, -1762, -783, 4, 771, 1781
+ , 3072, -5120, -4057, -2807, -1832, -822, 0, 816, 1804, 2851
+ , 3949, 5120, -6144, -4899, -3927, -2920, -1893, -874, -2, 868
+ , 1881, 2905, 3960, 4912, 6144, -9216, -8192, -7168, -6225, -4963
+ , -3943, -2956, -1890, -902, 0, 897, 1914, 2916, 3984, 4990
+ , 6050, 7168,-11264,-10217, -9114, -8132, -7035, -5988, -4984, -4000
+ , -2980, -1962, -927, 7, 931, 1956, 2981, 4031, 4972, 6213
+ , 7227, 8192, 9216, 10240, 11170, 12288, 13312, 14336, 0, 1024
+ , -557, 1, 571, -606, -4, 612, -1676, -707, 10, 673
+ , 2048, -2048, -727, 5, 686, -3072, -1772, -755, 12, 716
+ , 1877, -1856, -786, 2, 786, 1712, -1685, -818, -16, 863
+ , 1729, -3072, -1762, -857, 3, 866, 1838, 2841, -3862, -2816
+ , -1864, -925, -2, 923, 1897, 2779, -2782, -1838, -920, -28
+ , 931, 1951, 2835, 3804, -4815, -4001, -2940, -1934, -959, -22
+ , 975, 1957, 2904, 3971, 4835, -5148, -3892, -2944, -1953, -986
+ , -11, 989, 1968, 2939, 3949, 4947, 5902, -9216, -8192, -6915
+ , -6004, -4965, -4013, -3009, -1977, -987, -1, 982, 1972, 3000
+ , 3960, 4939, 5814, -8976, -7888, -7084, -5955, -5043, -4009, -2991
+ , -2002, -1000, -8, 993, 2011, 3023, 4026, 5028, 6023, 7052
+ , 8014, 9216,-11240,-10036, -9125, -8118, -7105, -6062, -5048, -4047
+ , -3044, -2025, -1009, -1, 1011, 2023, 3042, 4074, 5085, 6108
+ , 7119, 8142, 9152, 10114, 11141, 12250, 13307,-15360,-14099,-13284
+ ,-12291,-11223,-10221, -9152, -8147, -7128, -6104, -5077, -4072, -3062
+ , -2033, -1020, 7, 1018, 2038, 3059, 4081, 5084, 6109, 7102
+ , 8128, 9134, 10125, 11239, 12080,-23552,-22528,-21504,-20480,-19456
+ ,-18159,-17240,-16291,-15364,-14285,-13305,-12271,-11233,-10217, -9198
+ , -8175, -7157, -6134, -5122, -4089, -3071, -2047, -1018, 3, 1026
+ , 2041, 3077, 4090, 5108, 6131, 7150, 8172, 9175, 10196, 11272
+ , 12303, 13273, 14328, 15332, 16334, 17381, 18409, 19423, 20423, 21451
+ , 22679, 23391, 24568, 25600, 26589
+};
+
+/* cdf tables for quantizer indices */
+const WebRtc_UWord16 WebRtcIsacfix_kCdfGain[1212] = {
+ 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, 0, 2, 4, 6, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 222, 65321,
+ 65513, 65528, 65531, 65533, 65535, 0, 2, 4, 50, 65476,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 12,
+ 38, 544, 64936, 65509, 65523, 65525, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 1055, 64508, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 12, 123,
+ 3956, 62999, 65372, 65495, 65515, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 12, 53, 4707, 59445,
+ 65467, 65525, 65527, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 38, 40, 50, 67,
+ 96, 234, 929, 14345, 55750, 64866, 65389, 65462, 65514, 65517,
+ 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 15, 35, 91, 377, 1946,
+ 13618, 52565, 63714, 65184, 65465, 65520, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52,
+ 54, 82, 149, 362, 751, 1701, 4239, 12893, 38627, 55072,
+ 60875, 63071, 64158, 64702, 65096, 65283, 65412, 65473, 65494, 65505,
+ 65508, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 15, 23, 53, 143, 260, 418, 698,
+ 988, 1353, 1812, 2411, 3144, 4015, 5143, 6401, 7611, 8999,
+ 10653, 12512, 14636, 16865, 19404, 22154, 24798, 27521, 30326, 33102,
+ 35790, 38603, 41415, 43968, 46771, 49435, 52152, 54715, 57143, 59481,
+ 61178, 62507, 63603, 64489, 64997, 65257, 65427, 65473, 65503, 65520,
+ 65529, 65531, 65533, 65535, 0, 3, 6, 9, 26, 32,
+ 44, 46, 64, 94, 111, 164, 205, 254, 327, 409,
+ 506, 608, 733, 885, 1093, 1292, 1482, 1742, 1993, 2329,
+ 2615, 3029, 3374, 3798, 4257, 4870, 5405, 5992, 6618, 7225,
+ 7816, 8418, 9051, 9761, 10532, 11380, 12113, 13010, 13788, 14594,
+ 15455, 16361, 17182, 18088, 18997, 20046, 20951, 21968, 22947, 24124,
+ 25296, 26547, 27712, 28775, 29807, 30835, 31709, 32469, 33201, 34014,
+ 34876, 35773, 36696, 37620, 38558, 39547, 40406, 41277, 42367, 43290,
+ 44445, 45443, 46510, 47684, 48973, 50157, 51187, 52242, 53209, 54083,
+ 55006, 55871, 56618, 57293, 57965, 58556, 59222, 59722, 60180, 60554,
+ 60902, 61250, 61554, 61837, 62100, 62372, 62631, 62856, 63078, 63324,
+ 63557, 63768, 63961, 64089, 64235, 64352, 64501, 64633, 64770, 64887,
+ 65001, 65059, 65121, 65188, 65246, 65302, 65346, 65390, 65428, 65463,
+ 65477, 65506, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 109, 65332, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 25, 1817, 63874, 65511,
+ 65527, 65529, 65531, 65533, 65535, 0, 2, 4, 907, 65014,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 10,
+ 12, 132, 2743, 62708, 65430, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 35, 3743, 61666, 65485,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 23,
+ 109, 683, 6905, 58417, 64911, 65398, 65497, 65518, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 53, 510,
+ 10209, 55212, 64573, 65441, 65522, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 32, 90, 266, 1037, 3349, 14468, 50488, 62394, 64685,
+ 65341, 65480, 65514, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535, 0, 2, 4, 6, 9, 16, 37, 106,
+ 296, 748, 1868, 5733, 18897, 45553, 60165, 63949, 64926, 65314,
+ 65441, 65508, 65524, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 83, 175, 344, 667, 1293, 2337, 4357,
+ 8033, 14988, 28600, 43244, 52011, 57042, 59980, 61779, 63065, 63869,
+ 64390, 64753, 64988, 65164, 65326, 65422, 65462, 65492, 65506, 65522,
+ 65524, 65526, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 14, 16, 25, 39, 48, 55, 62, 65,
+ 85, 106, 139, 169, 194, 252, 323, 485, 688, 1074,
+ 1600, 2544, 3863, 5733, 8303, 11397, 15529, 20273, 25734, 31455,
+ 36853, 41891, 46410, 50306, 53702, 56503, 58673, 60479, 61880, 62989,
+ 63748, 64404, 64852, 65124, 65309, 65424, 65480, 65524, 65528, 65533,
+ 65535, 0, 2, 4, 6, 8, 10, 12, 14, 21,
+ 23, 25, 27, 29, 31, 39, 41, 43, 48, 60,
+ 72, 79, 106, 136, 166, 187, 224, 252, 323, 381,
+ 427, 478, 568, 660, 783, 912, 1046, 1175, 1365, 1567,
+ 1768, 2024, 2347, 2659, 3049, 3529, 4033, 4623, 5281, 5925,
+ 6726, 7526, 8417, 9468, 10783, 12141, 13571, 15222, 16916, 18659,
+ 20350, 22020, 23725, 25497, 27201, 29026, 30867, 32632, 34323, 36062,
+ 37829, 39466, 41144, 42654, 43981, 45343, 46579, 47759, 49013, 50171,
+ 51249, 52283, 53245, 54148, 54938, 55669, 56421, 57109, 57791, 58464,
+ 59092, 59674, 60105, 60653, 61083, 61407, 61757, 62095, 62388, 62649,
+ 62873, 63157, 63358, 63540, 63725, 63884, 64046, 64155, 64278, 64426,
+ 64548, 64654, 64806, 64906, 64994, 65077, 65137, 65215, 65277, 65324,
+ 65354, 65409, 65437, 65455, 65462, 65490, 65495, 65499, 65508, 65511,
+ 65513, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kCdfShape[2059] = {
+ 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, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65533, 65535, 0, 2, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 2, 4, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 4, 65531, 65533, 65535, 0, 2, 4, 65531,
+ 65533, 65535, 0, 2, 4, 6, 65524, 65533, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65533,
+ 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0,
+ 2, 65533, 65535, 0, 2, 4, 65532, 65535, 0, 6,
+ 65523, 65535, 0, 2, 15, 65530, 65533, 65535, 0, 2,
+ 35, 65493, 65531, 65533, 65535, 0, 2, 4, 158, 65382,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 2, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 9, 65512, 65535, 0, 2,
+ 12, 65529, 65535, 0, 2, 73, 65434, 65533, 65535, 0,
+ 2, 240, 65343, 65533, 65535, 0, 2, 476, 65017, 65531,
+ 65533, 65535, 0, 2, 4, 1046, 64686, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 1870, 63898, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65532, 65535, 0, 6, 65533, 65535, 0, 6, 65523, 65535,
+ 0, 2, 65532, 65535, 0, 137, 65439, 65535, 0, 576,
+ 64899, 65533, 65535, 0, 2, 289, 65299, 65533, 65535, 0,
+ 2, 4, 6, 880, 64134, 65531, 65533, 65535, 0, 2,
+ 4, 1853, 63347, 65533, 65535, 0, 2, 6, 2516, 61762,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 9, 3980, 61380,
+ 65503, 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 61, 6393, 59859, 65466, 65527, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2, 65532,
+ 65535, 0, 3, 65529, 65535, 0, 2, 65529, 65535, 0,
+ 61, 65453, 65535, 0, 234, 65313, 65535, 0, 503, 65138,
+ 65535, 0, 155, 65402, 65533, 65535, 0, 2, 1058, 64554,
+ 65533, 65535, 0, 2, 4, 3138, 62109, 65531, 65533, 65535,
+ 0, 2, 4, 2031, 63339, 65531, 65533, 65535, 0, 2,
+ 4, 6, 9, 4155, 60778, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 41, 6189, 59269, 65490, 65531, 65533, 65535,
+ 0, 2, 4, 6, 210, 8789, 57043, 65400, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 26, 453, 10086,
+ 55499, 64948, 65483, 65524, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 114, 1014, 11202, 52670, 64226, 65356, 65503, 65514, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 15,
+ 65301, 65535, 0, 152, 64807, 65535, 0, 2, 3328, 63308,
+ 65535, 0, 2, 4050, 59730, 65533, 65535, 0, 2, 164,
+ 10564, 61894, 65529, 65535, 0, 15, 6712, 59831, 65076, 65532,
+ 65535, 0, 32, 7712, 57449, 65459, 65535, 0, 2, 210,
+ 7849, 53110, 65021, 65523, 65535, 0, 2, 12, 1081, 13883,
+ 48262, 62870, 65477, 65535, 0, 2, 88, 847, 6145, 37852,
+ 62012, 65454, 65533, 65535, 0, 9, 47, 207, 1823, 14522,
+ 45521, 61069, 64891, 65481, 65528, 65531, 65533, 65535, 0, 2,
+ 9, 488, 2881, 12758, 38703, 58412, 64420, 65410, 65533, 65535,
+ 0, 2, 4, 6, 61, 333, 1891, 6486, 19720, 43188,
+ 57547, 62472, 64796, 65421, 65497, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 12, 29, 117, 447,
+ 1528, 6138, 21242, 43133, 56495, 62432, 64746, 65362, 65500, 65529,
+ 65531, 65533, 65535, 0, 2, 18, 105, 301, 760, 1490,
+ 3472, 7568, 15002, 26424, 40330, 53029, 60048, 62964, 64274, 64890,
+ 65337, 65445, 65489, 65513, 65527, 65530, 65533, 65535, 0, 2,
+ 4, 6, 41, 102, 409, 853, 2031, 4316, 7302, 11328,
+ 16869, 24825, 34926, 43481, 50877, 56126, 59874, 62103, 63281, 63857,
+ 64166, 64675, 65382, 65522, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 29, 38, 53,
+ 58, 96, 181, 503, 1183, 2849, 5590, 8600, 11379, 13942,
+ 16478, 19453, 22638, 26039, 29411, 32921, 37596, 41433, 44998, 48560,
+ 51979, 55106, 57666, 59892, 61485, 62616, 63484, 64018, 64375, 64685,
+ 64924, 65076, 65278, 65395, 65471, 65509, 65529, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 7,
+ 65519, 65535, 0, 2, 14, 65491, 65533, 65535, 0, 2,
+ 81, 65427, 65531, 65533, 65535, 0, 2, 4, 312, 65293,
+ 65528, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 5, 65523, 65535, 0, 2, 65533, 65535, 0,
+ 7, 65526, 65535, 0, 46, 65464, 65533, 65535, 0, 2,
+ 120, 65309, 65533, 65535, 0, 2, 5, 362, 65097, 65533,
+ 65535, 0, 2, 18, 1164, 64785, 65528, 65531, 65533, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0,
+ 65535, 0, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65530, 65535,
+ 0, 2, 65523, 65535, 0, 69, 65477, 65535, 0, 141,
+ 65459, 65535, 0, 194, 65325, 65533, 65535, 0, 2, 543,
+ 64912, 65533, 65535, 0, 5, 1270, 64301, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 12, 2055, 63538, 65508, 65531, 65533,
+ 65535, 0, 2, 7, 102, 3775, 61970, 65429, 65526, 65528,
+ 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65535, 0, 9, 65533, 65535, 0,
+ 25, 65512, 65535, 0, 2, 65533, 65535, 0, 44, 65480,
+ 65535, 0, 48, 65475, 65535, 0, 162, 65373, 65535, 0,
+ 637, 64806, 65533, 65535, 0, 2, 935, 64445, 65533, 65535,
+ 0, 2, 4, 1662, 64083, 65533, 65535, 0, 2, 12,
+ 3036, 62469, 65521, 65533, 65535, 0, 2, 120, 5405, 60468,
+ 65469, 65531, 65533, 65535, 0, 2, 4, 18, 254, 6663,
+ 58999, 65272, 65528, 65533, 65535, 0, 2, 4, 9, 12,
+ 67, 591, 8981, 56781, 64564, 65365, 65508, 65524, 65526, 65529,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 9, 65526, 65535, 0, 14, 65503, 65535, 0,
+ 127, 65390, 65535, 0, 517, 64990, 65535, 0, 178, 65330,
+ 65535, 0, 2, 1055, 64533, 65533, 65535, 0, 2, 1558,
+ 63942, 65533, 65535, 0, 2, 2205, 63173, 65533, 65535, 0,
+ 25, 4493, 60862, 65505, 65533, 65535, 0, 2, 48, 5890,
+ 59442, 65482, 65533, 65535, 0, 2, 4, 127, 7532, 58191,
+ 65394, 65533, 65535, 0, 2, 5, 32, 550, 10388, 54924,
+ 65046, 65510, 65531, 65533, 65535, 0, 2, 4, 30, 150,
+ 1685, 14340, 51375, 63619, 65288, 65503, 65528, 65533, 65535, 0,
+ 2, 4, 6, 8, 28, 97, 473, 2692, 15407, 50020,
+ 62880, 65064, 65445, 65508, 65531, 65533, 65535, 0, 2, 4,
+ 12, 32, 79, 150, 372, 907, 2184, 5868, 18207, 45431,
+ 59856, 64031, 65096, 65401, 65481, 65507, 65521, 65523, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 182, 65491,
+ 65535, 0, 877, 64286, 65535, 0, 9, 2708, 63612, 65533,
+ 65535, 0, 2, 6038, 59532, 65535, 0, 2, 92, 5500,
+ 60539, 65533, 65535, 0, 268, 8908, 56512, 65385, 65535, 0,
+ 129, 13110, 52742, 65036, 65535, 0, 2, 806, 14003, 51929,
+ 64732, 65523, 65535, 0, 7, 92, 2667, 18159, 47678, 62610,
+ 65355, 65535, 0, 32, 1836, 19676, 48237, 61677, 64960, 65526,
+ 65535, 0, 21, 159, 967, 5668, 22782, 44709, 58317, 64020,
+ 65406, 65528, 65535, 0, 7, 162, 1838, 8328, 23929, 43014,
+ 56394, 63374, 65216, 65484, 65521, 65535, 0, 2, 4, 6,
+ 28, 268, 1120, 3613, 10688, 24185, 40989, 54917, 61684, 64510,
+ 65403, 65530, 65535, 0, 2, 16, 44, 139, 492, 1739,
+ 5313, 13558, 26766, 41566, 52446, 58937, 62815, 64480, 65201, 65454,
+ 65524, 65533, 65535, 0, 7, 25, 76, 263, 612, 1466,
+ 3325, 6832, 12366, 20152, 29466, 39255, 47360, 53506, 57740, 60726,
+ 62845, 64131, 64882, 65260, 65459, 65521, 65528, 65530, 65535, 0,
+ 2, 4, 14, 48, 136, 312, 653, 1240, 2369, 4327,
+ 7028, 10759, 15449, 21235, 28027, 35386, 42938, 49562, 54990, 59119,
+ 62086, 63916, 64863, 65249, 65445, 65493, 65523, 65535, 0, 2,
+ 4, 6, 8, 10, 12, 21, 83, 208, 409, 723,
+ 1152, 1868, 2951, 4463, 6460, 8979, 11831, 15195, 18863, 22657,
+ 26762, 30881, 34963, 39098, 43054, 47069, 50620, 53871, 56821, 59386,
+ 61340, 62670, 63512, 64023, 64429, 64750, 64944, 65126, 65279, 65366,
+ 65413, 65445, 65473, 65505, 65510, 65521, 65528, 65530, 65535
+};
+
+/* pointers to cdf tables for quantizer indices */
+const WebRtc_UWord16 *WebRtcIsacfix_kCdfGainPtr[3][12] = {
+ { WebRtcIsacfix_kCdfGain +0 +0, WebRtcIsacfix_kCdfGain +0 +8, WebRtcIsacfix_kCdfGain +0 +22,
+ WebRtcIsacfix_kCdfGain +0 +32, WebRtcIsacfix_kCdfGain +0 +48, WebRtcIsacfix_kCdfGain +0 +60,
+ WebRtcIsacfix_kCdfGain +0 +81, WebRtcIsacfix_kCdfGain +0 +95, WebRtcIsacfix_kCdfGain +0 +128,
+ WebRtcIsacfix_kCdfGain +0 +152, WebRtcIsacfix_kCdfGain +0 +210, WebRtcIsacfix_kCdfGain +0 +264
+ },
+ { WebRtcIsacfix_kCdfGain +404 +0, WebRtcIsacfix_kCdfGain +404 +8, WebRtcIsacfix_kCdfGain +404 +21,
+ WebRtcIsacfix_kCdfGain +404 +30, WebRtcIsacfix_kCdfGain +404 +46, WebRtcIsacfix_kCdfGain +404 +58,
+ WebRtcIsacfix_kCdfGain +404 +79, WebRtcIsacfix_kCdfGain +404 +93, WebRtcIsacfix_kCdfGain +404 +125,
+ WebRtcIsacfix_kCdfGain +404 +149, WebRtcIsacfix_kCdfGain +404 +207, WebRtcIsacfix_kCdfGain +404 +260
+ },
+ { WebRtcIsacfix_kCdfGain +803 +0, WebRtcIsacfix_kCdfGain +803 +8, WebRtcIsacfix_kCdfGain +803 +22,
+ WebRtcIsacfix_kCdfGain +803 +31, WebRtcIsacfix_kCdfGain +803 +48, WebRtcIsacfix_kCdfGain +803 +60,
+ WebRtcIsacfix_kCdfGain +803 +81, WebRtcIsacfix_kCdfGain +803 +96, WebRtcIsacfix_kCdfGain +803 +129,
+ WebRtcIsacfix_kCdfGain +803 +154, WebRtcIsacfix_kCdfGain +803 +212, WebRtcIsacfix_kCdfGain +803 +268
+ }
+};
+
+const WebRtc_UWord16 *WebRtcIsacfix_kCdfShapePtr[3][108] = {
+ { WebRtcIsacfix_kCdfShape +0 +0, WebRtcIsacfix_kCdfShape +0 +2, WebRtcIsacfix_kCdfShape +0 +4,
+ WebRtcIsacfix_kCdfShape +0 +6, WebRtcIsacfix_kCdfShape +0 +8, WebRtcIsacfix_kCdfShape +0 +10,
+ WebRtcIsacfix_kCdfShape +0 +12, WebRtcIsacfix_kCdfShape +0 +14, WebRtcIsacfix_kCdfShape +0 +16,
+ WebRtcIsacfix_kCdfShape +0 +18, WebRtcIsacfix_kCdfShape +0 +21, WebRtcIsacfix_kCdfShape +0 +25,
+ WebRtcIsacfix_kCdfShape +0 +29, WebRtcIsacfix_kCdfShape +0 +33, WebRtcIsacfix_kCdfShape +0 +37,
+ WebRtcIsacfix_kCdfShape +0 +43, WebRtcIsacfix_kCdfShape +0 +49, WebRtcIsacfix_kCdfShape +0 +56,
+ WebRtcIsacfix_kCdfShape +0 +64, WebRtcIsacfix_kCdfShape +0 +66, WebRtcIsacfix_kCdfShape +0 +68,
+ WebRtcIsacfix_kCdfShape +0 +70, WebRtcIsacfix_kCdfShape +0 +72, WebRtcIsacfix_kCdfShape +0 +75,
+ WebRtcIsacfix_kCdfShape +0 +77, WebRtcIsacfix_kCdfShape +0 +79, WebRtcIsacfix_kCdfShape +0 +81,
+ WebRtcIsacfix_kCdfShape +0 +83, WebRtcIsacfix_kCdfShape +0 +86, WebRtcIsacfix_kCdfShape +0 +90,
+ WebRtcIsacfix_kCdfShape +0 +94, WebRtcIsacfix_kCdfShape +0 +98, WebRtcIsacfix_kCdfShape +0 +102,
+ WebRtcIsacfix_kCdfShape +0 +107, WebRtcIsacfix_kCdfShape +0 +113, WebRtcIsacfix_kCdfShape +0 +120,
+ WebRtcIsacfix_kCdfShape +0 +129, WebRtcIsacfix_kCdfShape +0 +131, WebRtcIsacfix_kCdfShape +0 +133,
+ WebRtcIsacfix_kCdfShape +0 +135, WebRtcIsacfix_kCdfShape +0 +137, WebRtcIsacfix_kCdfShape +0 +141,
+ WebRtcIsacfix_kCdfShape +0 +143, WebRtcIsacfix_kCdfShape +0 +147, WebRtcIsacfix_kCdfShape +0 +151,
+ WebRtcIsacfix_kCdfShape +0 +155, WebRtcIsacfix_kCdfShape +0 +159, WebRtcIsacfix_kCdfShape +0 +164,
+ WebRtcIsacfix_kCdfShape +0 +168, WebRtcIsacfix_kCdfShape +0 +172, WebRtcIsacfix_kCdfShape +0 +178,
+ WebRtcIsacfix_kCdfShape +0 +184, WebRtcIsacfix_kCdfShape +0 +192, WebRtcIsacfix_kCdfShape +0 +200,
+ WebRtcIsacfix_kCdfShape +0 +211, WebRtcIsacfix_kCdfShape +0 +213, WebRtcIsacfix_kCdfShape +0 +215,
+ WebRtcIsacfix_kCdfShape +0 +217, WebRtcIsacfix_kCdfShape +0 +219, WebRtcIsacfix_kCdfShape +0 +223,
+ WebRtcIsacfix_kCdfShape +0 +227, WebRtcIsacfix_kCdfShape +0 +231, WebRtcIsacfix_kCdfShape +0 +235,
+ WebRtcIsacfix_kCdfShape +0 +239, WebRtcIsacfix_kCdfShape +0 +243, WebRtcIsacfix_kCdfShape +0 +248,
+ WebRtcIsacfix_kCdfShape +0 +252, WebRtcIsacfix_kCdfShape +0 +258, WebRtcIsacfix_kCdfShape +0 +264,
+ WebRtcIsacfix_kCdfShape +0 +273, WebRtcIsacfix_kCdfShape +0 +282, WebRtcIsacfix_kCdfShape +0 +293,
+ WebRtcIsacfix_kCdfShape +0 +308, WebRtcIsacfix_kCdfShape +0 +310, WebRtcIsacfix_kCdfShape +0 +312,
+ WebRtcIsacfix_kCdfShape +0 +316, WebRtcIsacfix_kCdfShape +0 +320, WebRtcIsacfix_kCdfShape +0 +324,
+ WebRtcIsacfix_kCdfShape +0 +328, WebRtcIsacfix_kCdfShape +0 +332, WebRtcIsacfix_kCdfShape +0 +336,
+ WebRtcIsacfix_kCdfShape +0 +341, WebRtcIsacfix_kCdfShape +0 +347, WebRtcIsacfix_kCdfShape +0 +354,
+ WebRtcIsacfix_kCdfShape +0 +360, WebRtcIsacfix_kCdfShape +0 +368, WebRtcIsacfix_kCdfShape +0 +378,
+ WebRtcIsacfix_kCdfShape +0 +388, WebRtcIsacfix_kCdfShape +0 +400, WebRtcIsacfix_kCdfShape +0 +418,
+ WebRtcIsacfix_kCdfShape +0 +445, WebRtcIsacfix_kCdfShape +0 +447, WebRtcIsacfix_kCdfShape +0 +451,
+ WebRtcIsacfix_kCdfShape +0 +455, WebRtcIsacfix_kCdfShape +0 +461, WebRtcIsacfix_kCdfShape +0 +468,
+ WebRtcIsacfix_kCdfShape +0 +474, WebRtcIsacfix_kCdfShape +0 +480, WebRtcIsacfix_kCdfShape +0 +486,
+ WebRtcIsacfix_kCdfShape +0 +495, WebRtcIsacfix_kCdfShape +0 +505, WebRtcIsacfix_kCdfShape +0 +516,
+ WebRtcIsacfix_kCdfShape +0 +528, WebRtcIsacfix_kCdfShape +0 +543, WebRtcIsacfix_kCdfShape +0 +564,
+ WebRtcIsacfix_kCdfShape +0 +583, WebRtcIsacfix_kCdfShape +0 +608, WebRtcIsacfix_kCdfShape +0 +635
+ },
+ { WebRtcIsacfix_kCdfShape +686 +0, WebRtcIsacfix_kCdfShape +686 +2, WebRtcIsacfix_kCdfShape +686 +4,
+ WebRtcIsacfix_kCdfShape +686 +6, WebRtcIsacfix_kCdfShape +686 +8, WebRtcIsacfix_kCdfShape +686 +11,
+ WebRtcIsacfix_kCdfShape +686 +13, WebRtcIsacfix_kCdfShape +686 +15, WebRtcIsacfix_kCdfShape +686 +17,
+ WebRtcIsacfix_kCdfShape +686 +20, WebRtcIsacfix_kCdfShape +686 +23, WebRtcIsacfix_kCdfShape +686 +27,
+ WebRtcIsacfix_kCdfShape +686 +31, WebRtcIsacfix_kCdfShape +686 +35, WebRtcIsacfix_kCdfShape +686 +40,
+ WebRtcIsacfix_kCdfShape +686 +44, WebRtcIsacfix_kCdfShape +686 +50, WebRtcIsacfix_kCdfShape +686 +56,
+ WebRtcIsacfix_kCdfShape +686 +63, WebRtcIsacfix_kCdfShape +686 +65, WebRtcIsacfix_kCdfShape +686 +67,
+ WebRtcIsacfix_kCdfShape +686 +69, WebRtcIsacfix_kCdfShape +686 +71, WebRtcIsacfix_kCdfShape +686 +73,
+ WebRtcIsacfix_kCdfShape +686 +75, WebRtcIsacfix_kCdfShape +686 +77, WebRtcIsacfix_kCdfShape +686 +79,
+ WebRtcIsacfix_kCdfShape +686 +82, WebRtcIsacfix_kCdfShape +686 +85, WebRtcIsacfix_kCdfShape +686 +89,
+ WebRtcIsacfix_kCdfShape +686 +93, WebRtcIsacfix_kCdfShape +686 +97, WebRtcIsacfix_kCdfShape +686 +102,
+ WebRtcIsacfix_kCdfShape +686 +106, WebRtcIsacfix_kCdfShape +686 +112, WebRtcIsacfix_kCdfShape +686 +119,
+ WebRtcIsacfix_kCdfShape +686 +127, WebRtcIsacfix_kCdfShape +686 +129, WebRtcIsacfix_kCdfShape +686 +131,
+ WebRtcIsacfix_kCdfShape +686 +133, WebRtcIsacfix_kCdfShape +686 +135, WebRtcIsacfix_kCdfShape +686 +137,
+ WebRtcIsacfix_kCdfShape +686 +139, WebRtcIsacfix_kCdfShape +686 +142, WebRtcIsacfix_kCdfShape +686 +146,
+ WebRtcIsacfix_kCdfShape +686 +150, WebRtcIsacfix_kCdfShape +686 +154, WebRtcIsacfix_kCdfShape +686 +158,
+ WebRtcIsacfix_kCdfShape +686 +162, WebRtcIsacfix_kCdfShape +686 +167, WebRtcIsacfix_kCdfShape +686 +173,
+ WebRtcIsacfix_kCdfShape +686 +179, WebRtcIsacfix_kCdfShape +686 +186, WebRtcIsacfix_kCdfShape +686 +194,
+ WebRtcIsacfix_kCdfShape +686 +205, WebRtcIsacfix_kCdfShape +686 +207, WebRtcIsacfix_kCdfShape +686 +209,
+ WebRtcIsacfix_kCdfShape +686 +211, WebRtcIsacfix_kCdfShape +686 +214, WebRtcIsacfix_kCdfShape +686 +218,
+ WebRtcIsacfix_kCdfShape +686 +222, WebRtcIsacfix_kCdfShape +686 +226, WebRtcIsacfix_kCdfShape +686 +230,
+ WebRtcIsacfix_kCdfShape +686 +234, WebRtcIsacfix_kCdfShape +686 +238, WebRtcIsacfix_kCdfShape +686 +242,
+ WebRtcIsacfix_kCdfShape +686 +247, WebRtcIsacfix_kCdfShape +686 +253, WebRtcIsacfix_kCdfShape +686 +262,
+ WebRtcIsacfix_kCdfShape +686 +269, WebRtcIsacfix_kCdfShape +686 +278, WebRtcIsacfix_kCdfShape +686 +289,
+ WebRtcIsacfix_kCdfShape +686 +305, WebRtcIsacfix_kCdfShape +686 +307, WebRtcIsacfix_kCdfShape +686 +309,
+ WebRtcIsacfix_kCdfShape +686 +311, WebRtcIsacfix_kCdfShape +686 +315, WebRtcIsacfix_kCdfShape +686 +319,
+ WebRtcIsacfix_kCdfShape +686 +323, WebRtcIsacfix_kCdfShape +686 +327, WebRtcIsacfix_kCdfShape +686 +331,
+ WebRtcIsacfix_kCdfShape +686 +335, WebRtcIsacfix_kCdfShape +686 +340, WebRtcIsacfix_kCdfShape +686 +346,
+ WebRtcIsacfix_kCdfShape +686 +354, WebRtcIsacfix_kCdfShape +686 +362, WebRtcIsacfix_kCdfShape +686 +374,
+ WebRtcIsacfix_kCdfShape +686 +384, WebRtcIsacfix_kCdfShape +686 +396, WebRtcIsacfix_kCdfShape +686 +413,
+ WebRtcIsacfix_kCdfShape +686 +439, WebRtcIsacfix_kCdfShape +686 +442, WebRtcIsacfix_kCdfShape +686 +446,
+ WebRtcIsacfix_kCdfShape +686 +450, WebRtcIsacfix_kCdfShape +686 +455, WebRtcIsacfix_kCdfShape +686 +461,
+ WebRtcIsacfix_kCdfShape +686 +468, WebRtcIsacfix_kCdfShape +686 +475, WebRtcIsacfix_kCdfShape +686 +481,
+ WebRtcIsacfix_kCdfShape +686 +489, WebRtcIsacfix_kCdfShape +686 +498, WebRtcIsacfix_kCdfShape +686 +508,
+ WebRtcIsacfix_kCdfShape +686 +522, WebRtcIsacfix_kCdfShape +686 +534, WebRtcIsacfix_kCdfShape +686 +554,
+ WebRtcIsacfix_kCdfShape +686 +577, WebRtcIsacfix_kCdfShape +686 +602, WebRtcIsacfix_kCdfShape +686 +631
+ },
+ { WebRtcIsacfix_kCdfShape +1368 +0, WebRtcIsacfix_kCdfShape +1368 +2, WebRtcIsacfix_kCdfShape +1368 +4,
+ WebRtcIsacfix_kCdfShape +1368 +6, WebRtcIsacfix_kCdfShape +1368 +8, WebRtcIsacfix_kCdfShape +1368 +10,
+ WebRtcIsacfix_kCdfShape +1368 +12, WebRtcIsacfix_kCdfShape +1368 +14, WebRtcIsacfix_kCdfShape +1368 +16,
+ WebRtcIsacfix_kCdfShape +1368 +20, WebRtcIsacfix_kCdfShape +1368 +24, WebRtcIsacfix_kCdfShape +1368 +28,
+ WebRtcIsacfix_kCdfShape +1368 +32, WebRtcIsacfix_kCdfShape +1368 +36, WebRtcIsacfix_kCdfShape +1368 +40,
+ WebRtcIsacfix_kCdfShape +1368 +44, WebRtcIsacfix_kCdfShape +1368 +50, WebRtcIsacfix_kCdfShape +1368 +57,
+ WebRtcIsacfix_kCdfShape +1368 +65, WebRtcIsacfix_kCdfShape +1368 +67, WebRtcIsacfix_kCdfShape +1368 +69,
+ WebRtcIsacfix_kCdfShape +1368 +71, WebRtcIsacfix_kCdfShape +1368 +73, WebRtcIsacfix_kCdfShape +1368 +75,
+ WebRtcIsacfix_kCdfShape +1368 +77, WebRtcIsacfix_kCdfShape +1368 +79, WebRtcIsacfix_kCdfShape +1368 +81,
+ WebRtcIsacfix_kCdfShape +1368 +85, WebRtcIsacfix_kCdfShape +1368 +89, WebRtcIsacfix_kCdfShape +1368 +93,
+ WebRtcIsacfix_kCdfShape +1368 +97, WebRtcIsacfix_kCdfShape +1368 +101, WebRtcIsacfix_kCdfShape +1368 +105,
+ WebRtcIsacfix_kCdfShape +1368 +110, WebRtcIsacfix_kCdfShape +1368 +116, WebRtcIsacfix_kCdfShape +1368 +123,
+ WebRtcIsacfix_kCdfShape +1368 +132, WebRtcIsacfix_kCdfShape +1368 +134, WebRtcIsacfix_kCdfShape +1368 +136,
+ WebRtcIsacfix_kCdfShape +1368 +138, WebRtcIsacfix_kCdfShape +1368 +141, WebRtcIsacfix_kCdfShape +1368 +143,
+ WebRtcIsacfix_kCdfShape +1368 +146, WebRtcIsacfix_kCdfShape +1368 +150, WebRtcIsacfix_kCdfShape +1368 +154,
+ WebRtcIsacfix_kCdfShape +1368 +158, WebRtcIsacfix_kCdfShape +1368 +162, WebRtcIsacfix_kCdfShape +1368 +166,
+ WebRtcIsacfix_kCdfShape +1368 +170, WebRtcIsacfix_kCdfShape +1368 +174, WebRtcIsacfix_kCdfShape +1368 +179,
+ WebRtcIsacfix_kCdfShape +1368 +185, WebRtcIsacfix_kCdfShape +1368 +193, WebRtcIsacfix_kCdfShape +1368 +203,
+ WebRtcIsacfix_kCdfShape +1368 +214, WebRtcIsacfix_kCdfShape +1368 +216, WebRtcIsacfix_kCdfShape +1368 +218,
+ WebRtcIsacfix_kCdfShape +1368 +220, WebRtcIsacfix_kCdfShape +1368 +224, WebRtcIsacfix_kCdfShape +1368 +227,
+ WebRtcIsacfix_kCdfShape +1368 +231, WebRtcIsacfix_kCdfShape +1368 +235, WebRtcIsacfix_kCdfShape +1368 +239,
+ WebRtcIsacfix_kCdfShape +1368 +243, WebRtcIsacfix_kCdfShape +1368 +247, WebRtcIsacfix_kCdfShape +1368 +251,
+ WebRtcIsacfix_kCdfShape +1368 +256, WebRtcIsacfix_kCdfShape +1368 +262, WebRtcIsacfix_kCdfShape +1368 +269,
+ WebRtcIsacfix_kCdfShape +1368 +277, WebRtcIsacfix_kCdfShape +1368 +286, WebRtcIsacfix_kCdfShape +1368 +297,
+ WebRtcIsacfix_kCdfShape +1368 +315, WebRtcIsacfix_kCdfShape +1368 +317, WebRtcIsacfix_kCdfShape +1368 +319,
+ WebRtcIsacfix_kCdfShape +1368 +323, WebRtcIsacfix_kCdfShape +1368 +327, WebRtcIsacfix_kCdfShape +1368 +331,
+ WebRtcIsacfix_kCdfShape +1368 +335, WebRtcIsacfix_kCdfShape +1368 +339, WebRtcIsacfix_kCdfShape +1368 +343,
+ WebRtcIsacfix_kCdfShape +1368 +349, WebRtcIsacfix_kCdfShape +1368 +355, WebRtcIsacfix_kCdfShape +1368 +361,
+ WebRtcIsacfix_kCdfShape +1368 +368, WebRtcIsacfix_kCdfShape +1368 +376, WebRtcIsacfix_kCdfShape +1368 +385,
+ WebRtcIsacfix_kCdfShape +1368 +397, WebRtcIsacfix_kCdfShape +1368 +411, WebRtcIsacfix_kCdfShape +1368 +429,
+ WebRtcIsacfix_kCdfShape +1368 +456, WebRtcIsacfix_kCdfShape +1368 +459, WebRtcIsacfix_kCdfShape +1368 +463,
+ WebRtcIsacfix_kCdfShape +1368 +467, WebRtcIsacfix_kCdfShape +1368 +473, WebRtcIsacfix_kCdfShape +1368 +478,
+ WebRtcIsacfix_kCdfShape +1368 +485, WebRtcIsacfix_kCdfShape +1368 +491, WebRtcIsacfix_kCdfShape +1368 +497,
+ WebRtcIsacfix_kCdfShape +1368 +505, WebRtcIsacfix_kCdfShape +1368 +514, WebRtcIsacfix_kCdfShape +1368 +523,
+ WebRtcIsacfix_kCdfShape +1368 +535, WebRtcIsacfix_kCdfShape +1368 +548, WebRtcIsacfix_kCdfShape +1368 +565,
+ WebRtcIsacfix_kCdfShape +1368 +585, WebRtcIsacfix_kCdfShape +1368 +611, WebRtcIsacfix_kCdfShape +1368 +640
+ }
+};
+
+/* code length for all coefficients using different models */
+
+const WebRtc_Word16 WebRtcIsacfix_kCodeLenGainQ11[392] = {
+ 25189, 16036, 8717, 358, 8757, 15706, 21456, 24397, 18502, 17559
+ , 13794, 11088, 7480, 873, 6603, 11636, 14627, 16805, 19132, 26624
+ , 26624, 19408, 13751, 7280, 583, 7591, 15178, 23773, 28672, 25189
+ , 19045, 16442, 13412, 10397, 5893, 1338, 6376, 9992, 12074, 13853
+ , 15781, 19821, 22819, 28672, 28672, 25189, 19858, 15781, 11262, 5477
+ , 1298, 5632, 11814, 17234, 22020, 28672, 19677, 18125, 16587, 14521
+ , 13032, 11196, 9249, 5411, 2495, 4994, 7975, 10234, 12308, 13892
+ , 15148, 17944, 21725, 23917, 25189, 19539, 16293, 11531, 7808, 4475
+ , 2739, 4872, 8089, 11314, 14992, 18105, 23257, 26624, 25189, 23257
+ , 23257, 20982, 18697, 18023, 16338, 16036, 14539, 13695, 13146, 11763
+ , 10754, 9074, 7260, 5584, 4430, 5553, 6848, 8344, 10141, 11636
+ , 12535, 13416, 14342, 15477, 17296, 19282, 22349, 23773, 28672, 28672
+ , 26624, 23773, 21456, 18023, 15118, 13362, 11212, 9293, 8043, 6985
+ , 5908, 5721, 5853, 6518, 7316, 8360, 9716, 11289, 12912, 14652
+ , 16969, 19858, 23773, 26624, 28013, 30720, 30720, 28672, 25426, 23141
+ , 25426, 23773, 20720, 19408, 18697, 19282, 16859, 16338, 16026, 15377
+ , 15021, 14319, 14251, 13937, 13260, 13017, 12332, 11703, 11430, 10359
+ , 10128, 9405, 8757, 8223, 7974, 7859, 7646, 7673, 7997, 8580
+ , 8880, 9061, 9866, 10397, 11358, 12200, 13244, 14157, 15021, 16026
+ , 16490, 18697, 18479, 20011, 19677, 20720, 24576, 26276, 30720, 30720
+ , 28672, 30720, 24068, 25189, 22437, 20345, 18479, 16396, 16026, 14928
+ , 13877, 13450, 12696, 12766, 11626, 11098, 10159, 9998, 9437, 9275
+ , 8783, 8552, 8629, 8488, 8522, 8454, 8571, 8775, 8915, 9427
+ , 9483, 9851, 10260, 10933, 11131, 11974, 12560, 13833, 15080, 16304
+ , 17491, 19017, 18697, 19408, 22020, 25189, 25426, 22819, 26276, 30720
+ , 30720, 30720, 30720, 30720, 30720, 28672, 30720, 30720, 30720, 30720
+ , 28013, 25426, 24397, 23773, 25189, 26624, 25189, 22437, 21725, 20011
+ , 20527, 20720, 20771, 22020, 22020, 19858, 19408, 19972, 17866, 17360
+ , 17791, 17219, 16805, 16927, 16067, 16162, 15661, 15178, 15021, 15209
+ , 14845, 14570, 14490, 14490, 13733, 13617, 13794, 13577, 13312, 12824
+ , 13032, 12683, 12189, 12469, 12109, 11940, 11636, 11617, 11932, 12294
+ , 11578, 11775, 12039, 11654, 11560, 11439, 11909, 11421, 12029, 11513
+ , 11773, 11899, 11560, 11805, 11476, 11664, 11963, 11647, 11754, 11963
+ , 11703, 12211, 11932, 12074, 12469, 12535, 12560, 12912, 12783, 12866
+ , 12884, 13378, 13957, 13775, 13635, 14019, 14545, 15240, 15520, 15554
+ , 15697, 16490, 16396, 17281, 16599, 16969, 17963, 16859, 16983, 16805
+ , 17099, 18210, 17219, 17646, 17700, 17646, 18297, 17425, 18479, 17791
+ , 17718, 19282, 18672, 20173, 20982, 21725, 21456, 23773, 23257, 25189
+ , 30720, 30720, 25189, 26624, 30720, 30720, 30720, 30720, 28672, 26276
+ , 30720, 30720
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kCodeLenShapeQ11[577] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 28672
+ , 0, 26624, 1, 23773, 22819, 4, 20982, 18598, 10, 19282
+ , 16587, 22, 16442, 26624, 13126, 60, 14245, 26624, 26624, 12736
+ , 79, 12912, 25189, 22819, 9563, 249, 9474, 22349, 28672, 23257
+ , 17944, 7980, 434, 8181, 16431, 26624, 0, 0, 0, 0
+ , 28672, 0, 0, 0, 0, 0, 28672, 0, 22437, 3
+ , 22437, 20982, 5, 20982, 16442, 22, 16752, 13814, 49, 14646
+ , 11645, 116, 11734, 26624, 28672, 10613, 158, 11010, 24397, 19539
+ , 8046, 453, 7709, 19017, 28672, 23257, 15110, 6770, 758, 6523
+ , 14108, 24397, 28672, 0, 0, 0, 0, 28672, 0, 28672
+ , 0, 26624, 1, 28672, 28672, 1, 26624, 24397, 2, 23257
+ , 21725, 4, 20982, 17158, 18, 17281, 28672, 15178, 35, 15209
+ , 12343, 92, 12320, 26624, 10344, 189, 10217, 30720, 22020, 9033
+ , 322, 8549, 23773, 28672, 30720, 20622, 7666, 473, 7806, 20527
+ , 24397, 14135, 5995, 960, 6018, 14872, 23773, 26624, 20928, 16293
+ , 10636, 4926, 1588, 5256, 11088, 18043, 25189, 0, 0, 0
+ , 0, 24397, 1, 25189, 20720, 5, 21456, 21209, 3, 25189
+ , 20982, 5, 21456, 15818, 30, 15410, 13794, 60, 13416, 28672
+ , 11162, 142, 11025, 9337, 231, 10094, 23773, 8338, 405, 7930
+ , 26624, 19677, 6787, 613, 7318, 19161, 28672, 16442, 6319, 932
+ , 5748, 15312, 25189, 28672, 28672, 28672, 13998, 5513, 1263, 5146
+ , 14024, 24397, 22819, 15818, 9460, 4447, 2122, 4681, 9970, 15945
+ , 22349, 28672, 30720, 22622, 19017, 14872, 10689, 7405, 4473, 2983
+ , 4783, 7894, 11186, 14964, 18210, 24397, 0, 0, 30720, 0
+ , 30720, 21456, 3, 23773, 14964, 39, 14757, 14179, 53, 13751
+ , 14928, 36, 15272, 12430, 79, 13228, 9135, 285, 9077, 28672
+ , 28672, 8377, 403, 7919, 26624, 28672, 23257, 7068, 560, 7473
+ , 20345, 19677, 6770, 720, 6464, 18697, 25189, 16249, 5779, 1087
+ , 5494, 15209, 22819, 30720, 20622, 12601, 5240, 1419, 5091, 12095
+ , 19408, 26624, 22819, 16805, 10683, 4812, 2056, 4293, 9836, 16026
+ , 24397, 25189, 18409, 13833, 8681, 4503, 2653, 4220, 8329, 13853
+ , 19132, 26624, 25189, 20771, 17219, 12630, 9520, 6733, 4565, 3657
+ , 4817, 7069, 10058, 13212, 16805, 21209, 26624, 26276, 28672, 28672
+ , 26276, 23257, 20173, 19282, 16538, 15051, 12811, 10754, 9267, 7547
+ , 6270, 5407, 5214, 6057, 7054, 8226, 9488, 10806, 12793, 14442
+ , 16442, 19677, 22099, 26276, 28672, 0, 30720, 0, 30720, 11920
+ , 56, 20720, 30720, 6766, 355, 13130, 30720, 30720, 22180, 5589
+ , 736, 7902, 26624, 30720, 7634, 354, 9721, 30720, 30720, 9027
+ , 246, 10117, 30720, 30720, 9630, 453, 6709, 23257, 30720, 25683
+ , 14228, 6127, 1271, 4615, 15178, 30720, 30720, 23504, 12382, 5739
+ , 2015, 3492, 10560, 22020, 26624, 30720, 30720, 23257, 13192, 4873
+ , 1527, 5001, 12445, 22020, 30720, 30720, 30720, 30720, 19344, 10761
+ , 4051, 1927, 5281, 10594, 17866, 28672, 30720, 30720, 30720, 21869
+ , 15554, 10060, 5979, 2710, 3085, 7889, 14646, 21725, 28672, 30720
+ , 30720, 30720, 30720, 30720, 30720, 30720, 22719, 17425, 13212, 8083
+ , 4439, 2820, 4305, 8136, 12988, 17425, 21151, 28672, 28672, 30720
+ , 30720, 30720, 28672, 20527, 19282, 14412, 10513, 7407, 5079, 3744
+ , 4115, 6308, 9621, 13599, 17040, 22349, 28672, 30720, 30720, 30720
+ , 30720, 30720, 30720, 29522, 19282, 14545, 11485, 9093, 6760, 5262
+ , 4672, 4970, 6005, 7852, 9732, 12343, 14672, 19161, 22819, 25189
+ , 30720, 30720, 28672, 30720, 30720, 20720, 18125, 14388, 12007, 9825
+ , 8092, 7064, 6069, 5903, 5932, 6359, 7169, 8310, 9324, 10711
+ , 11867, 13096, 14157, 16338, 17040, 19161, 21725, 23773, 30720, 30720
+ , 26276, 25426, 24397, 28672, 28672, 23257, 22020, 22349, 18297, 17646
+ , 16983, 16431, 16162, 15021, 15178, 13751, 12142, 10895, 10193, 9632
+ , 9086, 8896, 8823, 8735, 8591, 8754, 8649, 8361, 8329, 8522
+ , 8373, 8739, 8993, 9657, 10454, 11279, 11899, 12614, 14024, 14273
+ , 15477, 15240, 16649, 17866, 18697, 21151, 22099
+};
+
+/* left KLT transforms */
+const WebRtc_Word16 WebRtcIsacfix_kT1GainQ15[3][4] = {
+ { -26130, 19773, 19773, 26130 },
+ { -26664, 19046, 19046, 26664 },
+ { -23538, 22797, 22797, 23538 }
+};
+
+
+
+const WebRtc_Word16 WebRtcIsacfix_kT1ShapeQ15[3][324] = {
+ { 52,16,168,7,439,-138,-89,306,671,882,
+ 157,1301,291,1598,-3571,-1943,-1119,32404,96,-12,
+ 379,-64,-307,345,-836,539,1045,2541,-2865,-992,
+ 1683,-4717,5808,7427,30599,2319,183,-73,451,481,
+ 933,-198,781,-397,1244,-777,3690,-2414,149,-1356,
+ -2593,-31140,8289,-1737,-202,-14,-214,360,501,450,
+ -245,-7,797,3638,-2804,3042,-337,22137,-22103,2264,
+ 6838,-3381,305,172,263,-195,-355,351,179,513,
+ 2234,3343,5509,7531,19075,-17740,-16836,2244,-629,-1505,
+ -153,108,124,-324,2694,-124,1492,-850,5347,4285,
+ 7439,-10229,-22822,-12467,-12891,3645,822,-232,131,13,
+ 374,565,536,4681,1294,-1935,1926,-5734,-10643,26462,
+ -12480,-5589,-1038,-2468,964,-704,-247,-106,186,-558,
+ -4050,3760,2972,2141,-7393,6294,26740,11991,-3251,5461,
+ 5341,1574,2208,-51,-552,-297,-753,-154,2068,-5371,
+ 3578,4106,28043,-10533,8041,2353,2389,4609,3410,1906,
+ 351,-249,18,-15,1117,539,2870,9084,17585,-24528,
+ -366,-6490,2009,-3170,2942,1116,-232,1672,1065,606,
+ -399,-388,-518,38,3728,28948,-11936,4543,4104,-4441,
+ 1545,-4044,1485,622,-68,186,-473,135,-280,125,
+ -546,-1813,6989,6606,23711,19376,-2636,2870,-4553,-1687,
+ 878,-375,205,-208,-409,-108,-200,-45,-1670,-337,
+ 8213,-5524,-2334,5240,-12939,-26205,5937,-1582,-592,-959,
+ -5374,2449,3400,559,349,-492,668,12379,-27684,3419,
+ 5117,4415,-297,-8270,-1252,-3490,-1272,-1199,-3159,191,
+ 630,488,-797,-3071,12912,-27783,-10249,1047,647,619,
+ 111,-3722,-915,-1055,-502,5,-1384,-306,221,68,
+ 5219,13173,-26474,-11663,-5626,927,806,-1127,236,-589,
+ -522,-230,-312,-315,-428,-573,426,192,-11830,-26883,
+ -14121,-2785,-1429,-109,410,-832,-302,539,-459,104,
+ 1,-530,-202,-289,153,116,30082,-12944,-671,20,
+ 649,98,103,215,234,0,280,-51,-169,298,
+ 31,230,-73,-51
+ },
+ { -154,-7,-192,61,-739,-389,-947,-162,-60,94,
+ 511,-716,1520,-1428,4168,-2214,1816,32270,-123,-77,
+ -199,-99,-42,-588,203,-240,-930,-35,1580,234,
+ 3206,-5507,-1495,-10946,30000,-2667,-136,-176,-240,-175,
+ -204,-661,-1796,-1039,-1271,498,3143,734,2663,2699,
+ -8127,29333,10495,2356,-72,113,-91,118,-2840,-723,
+ -1733,-1158,-389,-2116,-3054,-3,-5179,8071,29546,6308,
+ 5657,-3178,-186,-294,-473,-635,1213,-983,-1437,-1715,
+ -1094,1280,-92,-9573,948,29576,-7060,-5921,2954,1349,
+ -337,-108,-1099,962,418,-413,-1149,-334,1241,3975,
+ -6825,26725,-14377,7051,-4772,-1707,2335,2008,-150,570,
+ 1371,42,-1649,-619,2039,3369,-1225,1583,-2755,-15207,
+ -27504,-4855,-4304,1495,2733,1324,15,-448,403,353,
+ 3016,-1242,2338,2673,2064,-7496,-30447,-3686,5833,-1301,
+ -2455,2122,1519,608,43,-653,773,-3072,912,-1537,
+ 4505,10284,30237,1549,3200,-691,205,1702,658,1014,
+ 1499,148,79,-322,-1162,-4639,-813,7536,3204,29109,
+ -10747,-26,1611,2286,2114,2561,1022,372,348,207,
+ 1062,-1088,-443,-9849,2381,5671,29097,-7612,-2927,3853,
+ 194,1155,275,1438,1438,1312,581,888,-784,906,
+ 112,-11103,25104,14438,-9311,-3068,1210,368,370,-940,
+ -2434,-1148,1925,392,657,258,-526,1475,-2281,-4265,
+ -1880,1534,2185,-1472,959,-30934,6306,3114,-4109,1768,
+ -2612,-703,45,644,2185,2033,5670,7211,19114,-22427,
+ 6432,5150,-4090,-2694,3860,1245,-596,293,1829,369,
+ -319,229,-3256,2170,-6374,-26216,-4570,-16053,-5766,-262,
+ -2006,2873,-1477,147,378,-1544,-344,-544,-985,-481,
+ 4210,4542,30757,-7291,-4863,1529,-2079,-628,-603,-783,
+ -408,1646,697,808,-620,-292,181,158,-13313,-29173,
+ 5984,-1262,859,-1776,-558,-24,-883,-1421,739,210,
+ -531,-285,131,-160,-246,-56,29345,-13706,-2859,-2966,
+ -300,-970,-2382,-268,-103,-636,-12,-62,-691,-253,
+ -147,-127,27,66
+ },
+ { 55,-212,-198,489,-274,81,682,399,328,-934,
+ -389,-37,1357,-3632,5276,6581,-9493,-29921,29,-45,
+ 2,190,172,-15,311,-130,-1085,-25,324,-684,
+ 3223,-6580,4485,-5280,-29521,9933,82,-320,-530,229,
+ -705,-533,-414,848,-1842,-4473,1390,-857,6717,-6692,
+ 4648,29397,576,8339,-68,-85,238,-330,264,-1012,
+ -381,-203,-3384,-3329,3906,6810,3790,-6250,28312,-8078,
+ 8089,1565,160,-569,-612,-613,-1063,-1928,-1125,3421,
+ -7481,-7484,4942,-6984,4330,-25591,-10574,-6982,5682,-1781,
+ -308,89,178,-1715,-420,-3530,-5776,1219,-8617,-7137,
+ 7015,4981,24875,12657,-5408,-3356,-785,-1972,326,-858,
+ -506,-3382,-986,-6258,-2259,4015,-8374,-10482,3127,23826,
+ -14126,-514,-5417,2178,-2912,-17,-587,80,67,-5881,
+ -1702,-5351,-4481,398,-10156,-225,20727,-15460,-11603,7752,
+ 3660,1714,-2001,-359,499,-527,-1225,-7820,-1297,-6326,
+ -8526,7900,-18328,13311,-17488,-2926,-196,-17,2281,873,
+ 480,-160,-624,471,780,-8729,1707,-14262,-20647,1721,
+ 18590,-2206,-1214,-1066,312,-2602,783,-412,-113,49,
+ -119,1305,-2371,-15132,-1833,-18252,20295,-8316,2227,341,
+ -2074,-702,3082,-262,-465,-198,430,30,-70,-788,
+ 2342,-25132,-4863,19783,-484,2137,2811,-1906,799,1586,
+ 962,-734,-191,-30,-129,-93,-1126,1729,5860,-2030,
+ 8953,603,-3338,-10869,-1144,22070,12130,10513,3191,-6881,
+ -3514,2090,711,-666,1843,-5997,-5681,2921,-17641,-2801,
+ 4969,18590,7169,12214,8587,4405,3008,-1074,-371,-77,
+ 253,331,-5611,5014,13152,-1985,18483,-1696,8043,20463,
+ 2381,-393,1688,-1205,618,1220,457,248,-83,176,
+ 7920,-13676,-22139,-3038,17402,2036,844,3258,994,719,
+ 2087,-44,426,494,12,-91,46,5,-14204,22912,
+ -18156,-361,442,2298,-829,2229,386,1433,1335,1323,
+ 55,-592,-139,49,-12,-57,27783,17134,350,-282,
+ 552,158,142,2488,465,329,1087,118,143,10,
+ 56,65,-15,-31
+ }
+};
+
+/* right KLT transforms */
+const WebRtc_Word16 WebRtcIsacfix_kT2GainQ15[3][36] = {
+ { 4775, -14892, 20313, -17104, 10533, -3613, -6782, 16044, -8889,
+ -11019, 21330, -10720, 13193, -15678, -11101, 14461, 12250, -13096,
+ -16951, 2167, 16066, 15569, -702, -16754, -19195, -12823, -4321,
+ 5128, 13348, 17825, 13232, 13404, 13494, 13490, 13383, 13261
+ },
+ { -3725, 11408, -18493, 20031, -13097, 3865, 9344, -19294, 10740,
+ 8856, -18432, 8982, 13975, -14444, -11930, 11774, 14285, -13594,
+ -16323, -4, 16340, 15609, 359, -17220, -18401, -13471, -4643,
+ 5225, 13375, 18053, 13124, 13463, 13621, 13583, 13393, 13072
+ },
+ { -3513, 11402, -17883, 19504, -14399, 4885, 8702, -19513, 12046,
+ 8533, -18110, 8447, 12778, -14838, -12444, 13177, 14107, -12759,
+ -17268, 914, 15822, 15661, 838, -16686, -18907, -12936, -4820,
+ 4175, 12398, 18830, 12913, 13215, 13433, 13572, 13601, 13518
+ }
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kT2ShapeQ15[3][36] = {
+ { 4400, -11512, 17205, -19470, 14770, -5345, 9784, -19222, 11228,
+ 6842, -18371, 9909, 14191, -13496, -11563, 14015, 11827, -14839,
+ -15439, 948, 17802, 14827, -2053, -17132, 18723, 14516, 4135,
+ -6822, -13869, -16016, 12975, 13341, 13563, 13603, 13478, 13296
+ },
+ { 5420, -14215, 19060, -18073, 11709, -3911, 9645, -18335, 7717,
+ 10842, -19283, 9777, 14898, -12555, -13661, 11668, 13520, -13733,
+ -15936, -1358, 15671, 16728, 328, -17100, 17527, 13973, 5587,
+ -5194, -14165, -17677, 12970, 13446, 13693, 13660, 13462, 13015
+ },
+ { 4386, -12426, 18019, -18895, 13894, -5034, 9713, -19270, 10283,
+ 8692, -18439, 9317, 13992, -13454, -13241, 12850, 13366, -13336,
+ -16334, -498, 15976, 16213, -114, -16987, 18191, 13659, 4958,
+ -5116, -13444, -18021, 12911, 13424, 13718, 13674, 13464, 13054
+ }
+};
+
+/* means of log gains and LAR coefficients*/
+const WebRtc_Word16 WebRtcIsacfix_kMeansGainQ8[3][12] = {
+ { -1758, -1370, -1758, -1373, -1757, -1375,
+ -1758, -1374, -1758, -1373, -1755, -1370
+ },
+ { -1569, -1224, -1569, -1225, -1569, -1227,
+ -1569, -1226, -1567, -1225, -1565, -1224
+ },
+ { -1452, -957, -1447, -951, -1438, -944,
+ -1431, -938, -1419, -931, -1406, -926
+ }
+};
+
+
+const WebRtc_Word32 WebRtcIsacfix_kMeansShapeQ17[3][108] = {
+ { -119581, 34418, -44193, 11112, -4428, 18906, 9222, 8068, 1953, 5425,
+ 1871, 1689, 109933, 33751, 10471, -2566, 1090, 2320, -119219, 33728,
+ -43759, 11450, -4870, 19117, 9174, 8037, 1972, 5331, 1872, 1843,
+ 109899, 34301, 10629, -2316, 1272, 2562, -118608, 32318, -44012, 11591,
+ -4914, 18932, 9456, 8088, 1900, 5419, 1723, 1853, 109963, 35059,
+ 10745, -2335, 1161, 2520, -119174, 32107, -44462, 11635, -4694, 18611,
+ 9757, 8108, 1969, 5486, 1673, 1777, 109636, 34907, 10643, -2406,
+ 1034, 2420, -118597, 32320, -44590, 10854, -4569, 18821, 9701, 7866,
+ 2003, 5577, 1732, 1626, 109913, 34448, 10714, -2752, 990, 2228,
+ -118138, 32996, -44352, 10334, -3772, 18488, 9464, 7865, 2208, 5540,
+ 1745, 1664, 109880, 33381, 10640, -2779, 980, 2054
+ },
+ { -146328, 46370, 1047, 26431, 10035, 13933, 6415, 14359, -2368, 6661,
+ 2269, 1764, 96623, 7802, 4163, 10742, 1643, 2954, -146871, 46561, 1127,
+ 26225, 10113, 14096, 6771, 14323, -2037, 6788, 2297, 1761, 96324, 8382,
+ 4309, 10450, 1695, 3016, -146502, 46475, 1580, 26118, 10487, 14179, 6622,
+ 14439, -2034, 6757, 2342, 1761, 95869, 8966, 4347, 10358, 1999, 2855,
+ -146958, 47717, 826, 25952, 10263, 14061, 5266, 13681, -2417, 6582, 2047,
+ 1608, 96257, 9107, 4452, 10301, 1792, 2676, -146992, 47123, 446, 25822,
+ 10405, 14292, 5140, 13804, -2403, 6496, 1834, 1735, 97489, 9253, 4414,
+ 10684, 1549, 2721, -145811, 46182, 901, 26482, 10241, 14524, 6075, 14514,
+ -2147, 6691, 2196, 1899, 97011, 8178, 4102, 10758, 1638, 2869
+ },
+ { -166617, 46969, -43908, 17726, 6330, 25615, 6913, 5450, -2301, 1984,
+ 507, 2883, 149998, 28709, 19333, 16703, 11093, 8965, -168254, 46604,
+ -44315, 17862, 6474, 25746, 7018, 5373, -2343, 1930, 513, 2819, 150391,
+ 28627, 19194, 16678, 10998, 8929, -169093, 46084, -44767, 17427, 6401,
+ 25674, 7147, 5472, -2336, 1820, 491, 2802, 149860, 28430, 19064, 16524,
+ 10898, 8875, -170205, 46189, -44877, 17403, 6190, 25209, 7035, 5673, -2173,
+ 1894, 574, 2756, 148830, 28230, 18819, 16418, 10789, 8811, -171263, 45045,
+ -44834, 16858, 6103, 24726, 7014, 5713, -2103, 1877, 518, 2729, 147073,
+ 27744, 18629, 16277, 10690, 8703, -171720, 44153, -45062, 15951, 5872,
+ 24429, 7044, 5585, -2082, 1807, 519, 2769, 144791, 27402, 18490, 16126,
+ 10548, 8635
+ }
+};
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h b/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
new file mode 100644
index 0000000..4f2e0e7
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
@@ -0,0 +1,98 @@
+/*
+ * 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_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+
+#include "typedefs.h"
+
+
+/* indices of KLT coefficients used */
+extern const WebRtc_UWord16 WebRtcIsacfix_kSelIndGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kSelIndShape[108];
+
+/* cdf array for model indicator */
+extern const WebRtc_UWord16 WebRtcIsacfix_kModelCdf[KLT_NUM_MODELS+1];
+
+/* pointer to cdf array for model indicator */
+extern const WebRtc_UWord16 *WebRtcIsacfix_kModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const WebRtc_UWord16 WebRtcIsacfix_kModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const WebRtc_Word16 WebRtcIsacfix_kQuantMinGain[12];
+
+extern const WebRtc_Word16 WebRtcIsacfix_kQuantMinShape[108];
+
+/* maximum quantization index */
+extern const WebRtc_UWord16 WebRtcIsacfix_kMaxIndGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kMaxIndShape[108];
+
+/* index offset */
+extern const WebRtc_UWord16 WebRtcIsacfix_kOffsetGain[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kOffsetShape[KLT_NUM_MODELS][108];
+
+/* initial cdf index for KLT coefficients */
+extern const WebRtc_UWord16 WebRtcIsacfix_kInitIndexGain[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kInitIndexShape[KLT_NUM_MODELS][108];
+
+/* offsets for quantizer representation levels */
+extern const WebRtc_UWord16 WebRtcIsacfix_kOfLevelsGain[3];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kOfLevelsShape[3];
+
+/* quantizer representation levels */
+extern const WebRtc_Word32 WebRtcIsacfix_kLevelsGainQ17[1176];
+
+extern const WebRtc_Word16 WebRtcIsacfix_kLevelsShapeQ10[1735];
+
+/* cdf tables for quantizer indices */
+extern const WebRtc_UWord16 WebRtcIsacfix_kCdfGain[1212];
+
+extern const WebRtc_UWord16 WebRtcIsacfix_kCdfShape[2059];
+
+/* pointers to cdf tables for quantizer indices */
+extern const WebRtc_UWord16 *WebRtcIsacfix_kCdfGainPtr[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 *WebRtcIsacfix_kCdfShapePtr[KLT_NUM_MODELS][108];
+
+/* code length for all coefficients using different models */
+extern const WebRtc_Word16 WebRtcIsacfix_kCodeLenGainQ11[392];
+
+extern const WebRtc_Word16 WebRtcIsacfix_kCodeLenShapeQ11[577];
+
+/* left KLT transforms */
+extern const WebRtc_Word16 WebRtcIsacfix_kT1GainQ15[KLT_NUM_MODELS][4];
+
+extern const WebRtc_Word16 WebRtcIsacfix_kT1ShapeQ15[KLT_NUM_MODELS][324];
+
+/* right KLT transforms */
+extern const WebRtc_Word16 WebRtcIsacfix_kT2GainQ15[KLT_NUM_MODELS][36];
+
+extern const WebRtc_Word16 WebRtcIsacfix_kT2ShapeQ15[KLT_NUM_MODELS][36];
+
+/* means of log gains and LAR coefficients */
+extern const WebRtc_Word16 WebRtcIsacfix_kMeansGainQ8[KLT_NUM_MODELS][12];
+
+extern const WebRtc_Word32 WebRtcIsacfix_kMeansShapeQ17[3][108];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c b/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
new file mode 100644
index 0000000..6af02d8
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
@@ -0,0 +1,551 @@
+/*
+ * 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.c
+ *
+ * Pitch filter functions
+ *
+ */
+
+#ifdef WEBRTC_ARCH_ARM_NEON
+#include <arm_neon.h>
+#endif
+
+#include "pitch_estimator.h"
+#include "signal_processing_library.h"
+#include "system_wrappers/interface/compile_assert.h"
+
+/* log2[0.2, 0.5, 0.98] in Q8 */
+static const WebRtc_Word16 kLogLagWinQ8[3] = {
+ -594, -256, -7
+};
+
+/* [1 -0.75 0.25] in Q12 */
+static const WebRtc_Word16 kACoefQ12[3] = {
+ 4096, -3072, 1024
+};
+
+
+
+static __inline WebRtc_Word32 Log2Q8( WebRtc_UWord32 x ) {
+
+ WebRtc_Word32 zeros, lg2;
+ WebRtc_Word16 frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)(WEBRTC_SPL_LSHIFT_W32(x, zeros))&0x7FFFFFFF), 23);
+ /* log2(magn(i)) */
+
+ lg2= (WEBRTC_SPL_LSHIFT_W32((31-zeros), 8)+frac);
+ return lg2;
+
+}
+
+static __inline WebRtc_Word16 Exp2Q10(WebRtc_Word16 x) { // Both in and out in Q10
+
+ WebRtc_Word16 tmp16_1, tmp16_2;
+
+ tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
+ tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
+ if(tmp16_1>0)
+ return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
+ else
+ return (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
+
+}
+
+
+
+/* 1D parabolic interpolation . All input and output values are in Q8 */
+static __inline void Intrp1DQ8(WebRtc_Word32 *x, WebRtc_Word32 *fx, WebRtc_Word32 *y, WebRtc_Word32 *fy) {
+
+ WebRtc_Word16 sign1=1, sign2=1;
+ WebRtc_Word32 r32, q32, t32, nom32, den32;
+ WebRtc_Word16 t16, tmp16, tmp16_1;
+
+ if ((fx[0]>0) && (fx[2]>0)) {
+ r32=fx[1]-fx[2];
+ q32=fx[0]-fx[1];
+ nom32=q32+r32;
+ den32=WEBRTC_SPL_MUL_32_16((q32-r32), 2);
+ if (nom32<0)
+ sign1=-1;
+ if (den32<0)
+ sign2=-1;
+
+ /* t = (q32+r32)/(2*(q32-r32)) = (fx[0]-fx[1] + fx[1]-fx[2])/(2 * fx[0]-fx[1] - (fx[1]-fx[2]))*/
+ /* (Signs are removed because WebRtcSpl_DivResultInQ31 can't handle negative numbers) */
+ t32=WebRtcSpl_DivResultInQ31(WEBRTC_SPL_MUL_32_16(nom32, sign1),WEBRTC_SPL_MUL_32_16(den32, sign2)); /* t in Q31, without signs */
+
+ t16=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(t32, 23); /* Q8 */
+ t16=t16*sign1*sign2; /* t in Q8 with signs */
+
+ *y = x[0]+t16; /* Q8 */
+ // *y = x[1]+t16; /* Q8 */
+
+ /* The following code calculates fy in three steps */
+ /* fy = 0.5 * t * (t-1) * fx[0] + (1-t*t) * fx[1] + 0.5 * t * (t+1) * fx[2]; */
+
+ /* Part I: 0.5 * t * (t-1) * fx[0] */
+ tmp16_1=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(t16,t16); /* Q8*Q8=Q16 */
+ tmp16_1 = WEBRTC_SPL_RSHIFT_W16(tmp16_1,2); /* Q16>>2 = Q14 */
+ t16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(t16, 64); /* Q8<<6 = Q14 */
+ tmp16 = tmp16_1-t16;
+ *fy = WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[0]); /* (Q14 * Q8 >>15)/2 = Q8 */
+
+ /* Part II: (1-t*t) * fx[1] */
+ tmp16 = 16384-tmp16_1; /* 1 in Q14 - Q14 */
+ *fy += WEBRTC_SPL_MUL_16_32_RSFT14(tmp16, fx[1]);/* Q14 * Q8 >> 14 = Q8 */
+
+ /* Part III: 0.5 * t * (t+1) * fx[2] */
+ tmp16 = tmp16_1+t16;
+ *fy += WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[2]);/* (Q14 * Q8 >>15)/2 = Q8 */
+ } else {
+ *y = x[0];
+ *fy= fx[1];
+ }
+}
+
+
+static void FindFour32(WebRtc_Word32 *in, WebRtc_Word16 length, WebRtc_Word16 *bestind)
+{
+ WebRtc_Word32 best[4]= {-100, -100, -100, -100};
+ WebRtc_Word16 k;
+
+ for (k=0; k<length; k++) {
+ if (in[k] > best[3]) {
+ if (in[k] > best[2]) {
+ if (in[k] > best[1]) {
+ if (in[k] > best[0]) { // The Best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = best[1];
+ bestind[2] = bestind[1];
+ best[1] = best[0];
+ bestind[1] = bestind[0];
+ best[0] = in[k];
+ bestind[0] = k;
+ } else { // 2nd best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = best[1];
+ bestind[2] = bestind[1];
+ best[1] = in[k];
+ bestind[1] = k;
+ }
+ } else { // 3rd best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = in[k];
+ bestind[2] = k;
+ }
+ } else { // 4th best
+ best[3] = in[k];
+ bestind[3] = k;
+ }
+ }
+ }
+}
+
+
+
+
+
+static void PCorr2Q32(const WebRtc_Word16 *in, WebRtc_Word32 *logcorQ8)
+{
+ WebRtc_Word16 scaling,n,k;
+ WebRtc_Word32 ysum32,csum32, lys, lcs;
+ WebRtc_Word32 oneQ8;
+
+
+ const WebRtc_Word16 *x, *inptr;
+
+ oneQ8 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, 8); // 1.00 in Q8
+
+ x = in + PITCH_MAX_LAG/2 + 2;
+ scaling = WebRtcSpl_GetScalingSquare ((WebRtc_Word16 *) in, PITCH_CORR_LEN2, PITCH_CORR_LEN2);
+ ysum32 = 1;
+ csum32 = 0;
+ x = in + PITCH_MAX_LAG/2 + 2;
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ ysum32 += WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16) in[n],(WebRtc_Word16) in[n], scaling); // Q0
+ csum32 += WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) x[n],(WebRtc_Word16) in[n], scaling); // Q0
+ }
+
+ logcorQ8 += PITCH_LAG_SPAN2 - 1;
+
+ lys=Log2Q8((WebRtc_UWord32) ysum32); // Q8
+ lys=WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
+
+ if (csum32>0) {
+
+ lcs=Log2Q8((WebRtc_UWord32) csum32); // 2log(csum) in Q8
+
+ if (lcs>(lys + oneQ8) ){ // csum/sqrt(ysum) > 2 in Q8
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+
+ } else {
+ *logcorQ8 = 0;
+ }
+
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ inptr = &in[k];
+ ysum32 -= WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16) in[k-1],(WebRtc_Word16) in[k-1], scaling);
+ ysum32 += WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16) in[PITCH_CORR_LEN2 + k - 1],(WebRtc_Word16) in[PITCH_CORR_LEN2 + k - 1], scaling);
+
+#ifdef WEBRTC_ARCH_ARM_NEON
+ {
+ int32_t vbuff[4];
+ int32x4_t int_32x4_sum = vmovq_n_s32(0);
+ // Can't shift a Neon register to right with a non-constant shift value.
+ int32x4_t int_32x4_scale = vdupq_n_s32(-scaling);
+ // Assert a codition used in loop unrolling at compile-time.
+ COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0);
+
+ for (n = 0; n < PITCH_CORR_LEN2; n += 4) {
+ int16x4_t int_16x4_x = vld1_s16(&x[n]);
+ int16x4_t int_16x4_in = vld1_s16(&inptr[n]);
+ int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in);
+ int_32x4 = vshlq_s32(int_32x4, int_32x4_scale);
+ int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4);
+ }
+
+ // Use vector store to avoid long stall from data trasferring
+ // from vector to general register.
+ vst1q_s32(vbuff, int_32x4_sum);
+ csum32 = vbuff[0] + vbuff[1];
+ csum32 += vbuff[2];
+ csum32 += vbuff[3];
+ }
+#else
+ csum32 = 0;
+ if(scaling == 0) {
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ csum32 += x[n] * inptr[n];
+ }
+ } else {
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ csum32 += (x[n] * inptr[n]) >> scaling;
+ }
+ }
+#endif
+
+ logcorQ8--;
+
+ lys=Log2Q8((WebRtc_UWord32)ysum32); // Q8
+ lys=WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
+
+ if (csum32>0) {
+
+ lcs=Log2Q8((WebRtc_UWord32) csum32); // 2log(csum) in Q8
+
+ if (lcs>(lys + oneQ8) ){ // csum/sqrt(ysum) > 2
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+
+ } else {
+ *logcorQ8 = 0;
+ }
+ }
+}
+
+
+
+void WebRtcIsacfix_InitialPitch(const WebRtc_Word16 *in, /* Q0 */
+ PitchAnalysisStruct *State,
+ WebRtc_Word16 *lagsQ7 /* Q7 */
+ )
+{
+ WebRtc_Word16 buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+ WebRtc_Word32 *crrvecQ8_1,*crrvecQ8_2;
+ WebRtc_Word32 cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2];
+ int k;
+ WebRtc_Word16 peaks_indq;
+ WebRtc_Word16 peakiq[PITCH_LAG_SPAN2];
+ WebRtc_Word32 corr;
+ WebRtc_Word32 corr32, corr_max32, corr_max_o32;
+ WebRtc_Word16 npkq;
+ WebRtc_Word16 best4q[4]={0,0,0,0};
+ WebRtc_Word32 xq[3],yq[1],fyq[1];
+ WebRtc_Word32 *fxq;
+ WebRtc_Word32 best_lag1q, best_lag2q;
+ WebRtc_Word32 tmp32a,tmp32b,lag32,ratq;
+ WebRtc_Word16 start;
+ WebRtc_Word16 oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16;
+ WebRtc_Word32 tmp32c,tmp32d, tmp32e;
+ WebRtc_Word16 old_lagQ;
+ WebRtc_Word32 old_lagQ8;
+ WebRtc_Word32 lagsQ8[4];
+
+ old_lagQ = State->PFstr_wght.oldlagQ7; // Q7
+ old_lagQ8= WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)old_lagQ,1); //Q8
+
+ oldgQ12= State->PFstr_wght.oldgainQ12;
+
+ crrvecQ8_1=&cv1q[1];
+ crrvecQ8_2=&cv2q[1];
+
+
+ /* copy old values from state buffer */
+ memcpy(buf_dec16, State->dec_buffer16, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2)));
+
+ /* decimation; put result after the old values */
+ WebRtcIsacfix_DecimateAllpass32(in, State->decimator_state32, PITCH_FRAME_LEN,
+ &buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+ /* low-pass filtering */
+ start= PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2;
+ WebRtcSpl_FilterARFastQ12(&buf_dec16[start],&buf_dec16[start],(WebRtc_Word16*)kACoefQ12,3, PITCH_FRAME_LEN/2);
+
+ /* copy end part back into state buffer */
+ for (k = 0; k < (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2); k++)
+ State->dec_buffer16[k] = buf_dec16[k+PITCH_FRAME_LEN/2];
+
+
+ /* compute correlation for first and second half of the frame */
+ PCorr2Q32(buf_dec16, crrvecQ8_1);
+ PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2);
+
+
+ /* bias towards pitch lag of previous frame */
+ tmp32a = Log2Q8((WebRtc_UWord32) old_lagQ8) - 2304; // log2(0.5*oldlag) in Q8
+ tmp32b = WEBRTC_SPL_MUL_16_16_RSFT(oldgQ12,oldgQ12, 10); //Q12 & * 4.0;
+ gain_bias16 = (WebRtc_Word16) tmp32b; //Q12
+ if (gain_bias16 > 3276) gain_bias16 = 3276; // 0.8 in Q12
+
+
+ for (k = 0; k < PITCH_LAG_SPAN2; k++)
+ {
+ if (crrvecQ8_1[k]>0) {
+ tmp32b = Log2Q8((WebRtc_UWord32) (k + (PITCH_MIN_LAG/2-2)));
+ tmp16a = (WebRtc_Word16) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4
+ tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(tmp16a,tmp16a, 6); //Q10
+ tmp16b = (WebRtc_Word16) tmp32c; // Q10 & <8
+ tmp32d = WEBRTC_SPL_MUL_16_16_RSFT(tmp16b, 177 , 8); // mult with ln2 in Q8
+ tmp16c = (WebRtc_Word16) tmp32d; // Q10 & <4
+ tmp16d = Exp2Q10((WebRtc_Word16) -tmp16c); //Q10
+ tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(gain_bias16,tmp16d,13); // Q10 & * 0.5
+ bias16 = (WebRtc_Word16) (1024 + tmp32c); // Q10
+ tmp32b = Log2Q8((WebRtc_UWord32) bias16) - 2560; // Q10 in -> Q8 out with 10*2^8 offset
+ crrvecQ8_1[k] += tmp32b ; // -10*2^8 offset
+ }
+ }
+
+ /* taper correlation functions */
+ for (k = 0; k < 3; k++) {
+ crrvecQ8_1[k] += kLogLagWinQ8[k];
+ crrvecQ8_2[k] += kLogLagWinQ8[k];
+
+ crrvecQ8_1[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+ crrvecQ8_2[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+ }
+
+
+ /* Make zeropadded corr vectors */
+ cv1q[0]=0;
+ cv2q[0]=0;
+ cv1q[PITCH_LAG_SPAN2+1]=0;
+ cv2q[PITCH_LAG_SPAN2+1]=0;
+ corr_max32 = 0;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+
+
+ corr32=crrvecQ8_1[k-1];
+ if (corr32 > corr_max32)
+ corr_max32 = corr32;
+
+ corr32=crrvecQ8_2[k-1];
+ corr32 += -4; // Compensate for later (log2(0.99))
+
+ if (corr32 > corr_max32)
+ corr_max32 = corr32;
+
+ }
+
+ /* threshold value to qualify as a peak */
+ // corr_max32 += -726; // log(0.14)/log(2.0) in Q8
+ corr_max32 += -1000; // log(0.14)/log(2.0) in Q8
+ corr_max_o32 = corr_max32;
+
+
+ /* find peaks in corr1 */
+ peaks_indq = 0;
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ corr32=cv1q[k];
+ if (corr32>corr_max32) { // Disregard small peaks
+ if ((corr32>=cv1q[k-1]) && (corr32>cv1q[k+1])) { // Peak?
+ peakvq[peaks_indq] = corr32;
+ peakiq[peaks_indq++] = k;
+ }
+ }
+ }
+
+
+ /* find highest interpolated peak */
+ corr_max32=0;
+ best_lag1q =0;
+ if (peaks_indq > 0) {
+ FindFour32(peakvq, (WebRtc_Word16) peaks_indq, best4q);
+ npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+
+ for (k=0;k<npkq;k++) {
+
+ lag32 = peakiq[best4q[k]];
+ fxq = &cv1q[peakiq[best4q[k]]-1];
+ xq[0]= lag32;
+ xq[0] = WEBRTC_SPL_LSHIFT_W32(xq[0], 8);
+ Intrp1DQ8(xq, fxq, yq, fyq);
+
+ tmp32a= Log2Q8((WebRtc_UWord32) *yq) - 2048; // offset 8*2^8
+ /* Bias towards short lags */
+ /* log(pow(0.8, log(2.0 * *y )))/log(2.0) */
+ tmp32b= WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) tmp32a, -42, 8);
+ tmp32c= tmp32b + 256;
+ *fyq += tmp32c;
+ if (*fyq > corr_max32) {
+ corr_max32 = *fyq;
+ best_lag1q = *yq;
+ }
+ }
+ tmp32a = best_lag1q - OFFSET_Q8;
+ tmp32b = WEBRTC_SPL_LSHIFT_W32(tmp32a, 1);
+ lagsQ8[0] = tmp32b + PITCH_MIN_LAG_Q8;
+ lagsQ8[1] = lagsQ8[0];
+ } else {
+ lagsQ8[0] = old_lagQ8;
+ lagsQ8[1] = lagsQ8[0];
+ }
+
+ /* Bias towards constant pitch */
+ tmp32a = lagsQ8[0] - PITCH_MIN_LAG_Q8;
+ ratq = WEBRTC_SPL_RSHIFT_W32(tmp32a, 1) + OFFSET_Q8;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ tmp32a = WEBRTC_SPL_LSHIFT_W32(k, 7); // 0.5*k Q8
+ tmp32b = (WebRtc_Word32) (WEBRTC_SPL_LSHIFT_W32(tmp32a, 1)) - ratq; // Q8
+ tmp32c = WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) tmp32b, (WebRtc_Word16) tmp32b, 8); // Q8
+
+ tmp32b = (WebRtc_Word32) tmp32c + (WebRtc_Word32) WEBRTC_SPL_RSHIFT_W32(ratq, 1); // (k-r)^2 + 0.5 * r Q8
+ tmp32c = Log2Q8((WebRtc_UWord32) tmp32a) - 2048; // offset 8*2^8 , log2(0.5*k) Q8
+ tmp32d = Log2Q8((WebRtc_UWord32) tmp32b) - 2048; // offset 8*2^8 , log2(0.5*k) Q8
+ tmp32e = tmp32c -tmp32d;
+
+ cv2q[k] += WEBRTC_SPL_RSHIFT_W32(tmp32e, 1);
+
+ }
+
+ /* find peaks in corr2 */
+ corr_max32 = corr_max_o32;
+ peaks_indq = 0;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ corr=cv2q[k];
+ if (corr>corr_max32) { // Disregard small peaks
+ if ((corr>=cv2q[k-1]) && (corr>cv2q[k+1])) { // Peak?
+ peakvq[peaks_indq] = corr;
+ peakiq[peaks_indq++] = k;
+ }
+ }
+ }
+
+
+
+ /* find highest interpolated peak */
+ corr_max32 = 0;
+ best_lag2q =0;
+ if (peaks_indq > 0) {
+
+ FindFour32(peakvq, (WebRtc_Word16) peaks_indq, best4q);
+ npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+ for (k=0;k<npkq;k++) {
+
+ lag32 = peakiq[best4q[k]];
+ fxq = &cv2q[peakiq[best4q[k]]-1];
+
+ xq[0]= lag32;
+ xq[0] = WEBRTC_SPL_LSHIFT_W32(xq[0], 8);
+ Intrp1DQ8(xq, fxq, yq, fyq);
+
+ /* Bias towards short lags */
+ /* log(pow(0.8, log(2.0f * *y )))/log(2.0f) */
+ tmp32a= Log2Q8((WebRtc_UWord32) *yq) - 2048; // offset 8*2^8
+ tmp32b= WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16) tmp32a, -82, 8);
+ tmp32c= tmp32b + 256;
+ *fyq += tmp32c;
+ if (*fyq > corr_max32) {
+ corr_max32 = *fyq;
+ best_lag2q = *yq;
+ }
+ }
+
+ tmp32a = best_lag2q - OFFSET_Q8;
+ tmp32b = WEBRTC_SPL_LSHIFT_W32(tmp32a, 1);
+ lagsQ8[2] = tmp32b + PITCH_MIN_LAG_Q8;
+ lagsQ8[3] = lagsQ8[2];
+ } else {
+ lagsQ8[2] = lagsQ8[0];
+ lagsQ8[3] = lagsQ8[0];
+ }
+
+ lagsQ7[0]=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(lagsQ8[0], 1);
+ lagsQ7[1]=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(lagsQ8[1], 1);
+ lagsQ7[2]=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(lagsQ8[2], 1);
+ lagsQ7[3]=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(lagsQ8[3], 1);
+
+
+}
+
+
+
+void WebRtcIsacfix_PitchAnalysis(const WebRtc_Word16 *inn, /* PITCH_FRAME_LEN samples */
+ WebRtc_Word16 *outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ WebRtc_Word16 *PitchLags_Q7,
+ WebRtc_Word16 *PitchGains_Q12)
+{
+ WebRtc_Word16 inbufQ0[PITCH_FRAME_LEN + QLOOKAHEAD];
+ WebRtc_Word16 k;
+
+ /* inital pitch estimate */
+ WebRtcIsacfix_InitialPitch(inn, State, PitchLags_Q7);
+
+
+ /* Calculate gain */
+ WebRtcIsacfix_PitchFilterGains(inn, &(State->PFstr_wght), PitchLags_Q7, PitchGains_Q12);
+
+ /* concatenate previous input's end and current input */
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ inbufQ0[k] = State->inbuf[k];
+ }
+ for (k = 0; k < PITCH_FRAME_LEN; k++) {
+ inbufQ0[k+QLOOKAHEAD] = (WebRtc_Word16) inn[k];
+ }
+
+ /* lookahead pitch filtering for masking analysis */
+ WebRtcIsacfix_PitchFilter(inbufQ0, outQ0, &(State->PFstr), PitchLags_Q7,PitchGains_Q12, 2);
+
+
+ /* store last part of input */
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ State->inbuf[k] = inbufQ0[k + PITCH_FRAME_LEN];
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h b/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
new file mode 100644
index 0000000..6225256
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+
+#include "structs.h"
+
+void WebRtcIsacfix_PitchAnalysis(const WebRtc_Word16 *in, /* PITCH_FRAME_LEN samples */
+ WebRtc_Word16 *outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ WebRtc_Word16 *lagsQ7,
+ WebRtc_Word16 *PitchGains_Q12);
+
+void WebRtcIsacfix_InitialPitch(const WebRtc_Word16 *in,
+ PitchAnalysisStruct *State,
+ WebRtc_Word16 *qlags);
+
+void WebRtcIsacfix_PitchFilter(WebRtc_Word16 *indatFix,
+ WebRtc_Word16 *outdatQQ,
+ PitchFiltstr *pfp,
+ WebRtc_Word16 *lagsQ7,
+ WebRtc_Word16 *gainsQ12,
+ WebRtc_Word16 type);
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ WebRtc_Word16 gain,
+ int index,
+ WebRtc_Word16 sign,
+ WebRtc_Word16* inputState,
+ WebRtc_Word16* outputBuff2,
+ const WebRtc_Word16* coefficient,
+ WebRtc_Word16* inputBuf,
+ WebRtc_Word16* outputBuf,
+ int* index2);
+
+void WebRtcIsacfix_PitchFilterGains(const WebRtc_Word16 *indatQ0,
+ PitchFiltstr *pfp,
+ WebRtc_Word16 *lagsQ7,
+ WebRtc_Word16 *gainsQ12);
+
+void WebRtcIsacfix_DecimateAllpass32(const WebRtc_Word16 *in,
+ WebRtc_Word32 *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ WebRtc_Word16 N, /* number of input samples */
+ WebRtc_Word16 *out); /* array of size N/2 */
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
new file mode 100644
index 0000000..f30293e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+/*
+ * pitch_filter.c
+ *
+ * Pitch filter functions
+ *
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "system_wrappers/interface/compile_assert.h"
+
+// Number of segments in a pitch subframe.
+static const int kSegments = 5;
+
+// A division factor of 1/5 in Q15.
+static const WebRtc_Word16 kDivFactor = 6553;
+
+// Filter coefficicients in Q15.
+static const WebRtc_Word16 kDampFilter[PITCH_DAMPORDER] = {
+ -2294, 8192, 20972, 8192, -2294
+};
+
+// Interpolation coefficients; generated by design_pitch_filter.m.
+// Coefficients are stored in Q14.
+static const WebRtc_Word16 kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+ {-367, 1090, -2706, 9945, 10596, -3318, 1626, -781, 287},
+ {-325, 953, -2292, 7301, 12963, -3320, 1570, -743, 271},
+ {-240, 693, -1622, 4634, 14809, -2782, 1262, -587, 212},
+ {-125, 358, -817, 2144, 15982, -1668, 721, -329, 118},
+ { 0, 0, -1, 1, 16380, 1, -1, 0, 0},
+ { 118, -329, 721, -1668, 15982, 2144, -817, 358, -125},
+ { 212, -587, 1262, -2782, 14809, 4634, -1622, 693, -240},
+ { 271, -743, 1570, -3320, 12963, 7301, -2292, 953, -325}
+};
+
+// Function prototype for pitch filtering.
+// TODO(Turaj): Add descriptions of input and output parameters.
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ WebRtc_Word16 gain,
+ int index,
+ WebRtc_Word16 sign,
+ WebRtc_Word16* inputState,
+ WebRtc_Word16* outputBuf2,
+ const WebRtc_Word16* coefficient,
+ WebRtc_Word16* inputBuf,
+ WebRtc_Word16* outputBuf,
+ int* index2);
+
+static __inline WebRtc_Word32 CalcLrIntQ(WebRtc_Word32 fixVal,
+ WebRtc_Word16 qDomain) {
+ WebRtc_Word32 intgr;
+ WebRtc_Word32 roundVal;
+
+ roundVal = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, qDomain - 1);
+ intgr = WEBRTC_SPL_RSHIFT_W32(fixVal + roundVal, qDomain);
+
+ return intgr;
+}
+
+void WebRtcIsacfix_PitchFilter(WebRtc_Word16* indatQQ, // Q10 if type is 1 or 4,
+ // Q0 if type is 2.
+ WebRtc_Word16* outdatQQ,
+ PitchFiltstr* pfp,
+ WebRtc_Word16* lagsQ7,
+ WebRtc_Word16* gainsQ12,
+ WebRtc_Word16 type) {
+ int k, ind, cnt;
+ WebRtc_Word16 sign = 1;
+ WebRtc_Word16 inystateQQ[PITCH_DAMPORDER];
+ WebRtc_Word16 ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD];
+ const WebRtc_Word16 Gain = 21299; // 1.3 in Q14
+ WebRtc_Word16 oldLagQ7;
+ WebRtc_Word16 oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
+ int indW32 = 0, frcQQ = 0;
+ WebRtc_Word32 tmpW32;
+ const WebRtc_Word16* fracoeffQQ = NULL;
+
+ // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM().
+ COMPILE_ASSERT(PITCH_FRACORDER == 9);
+ COMPILE_ASSERT(PITCH_DAMPORDER == 5);
+
+ // Set up buffer and states.
+ memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+ memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ));
+
+ // Get old lag and gain value from memory.
+ oldLagQ7 = pfp->oldlagQ7;
+ oldGainQ12 = pfp->oldgainQ12;
+
+ if (type == 4) {
+ sign = -1;
+
+ // Make output more periodic.
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ gainsQ12[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ gainsQ12[k], Gain, 14);
+ }
+ }
+
+ // No interpolation if pitch lag step is big.
+ if ((WEBRTC_SPL_MUL_16_16_RSFT(lagsQ7[0], 3, 1) < oldLagQ7) ||
+ (lagsQ7[0] > WEBRTC_SPL_MUL_16_16_RSFT(oldLagQ7, 3, 1))) {
+ oldLagQ7 = lagsQ7[0];
+ oldGainQ12 = gainsQ12[0];
+ }
+
+ ind = 0;
+
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ // Calculate interpolation steps.
+ lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+ lagdeltaQ7 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ lagdeltaQ7, kDivFactor, 15);
+ curLagQ7 = oldLagQ7;
+ gaindeltaQ12 = gainsQ12[k] - oldGainQ12;
+ gaindeltaQ12 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
+ gaindeltaQ12, kDivFactor, 15);
+
+ curGainQ12 = oldGainQ12;
+ oldLagQ7 = lagsQ7[k];
+ oldGainQ12 = gainsQ12[k];
+
+ // Each frame has 4 60-sample pitch subframes, and each subframe has 5
+ // 12-sample segments. Each segment need to be processed with
+ // newly-updated parameters, so we break the pitch filtering into
+ // two for-loops (5 x 12) below. It's also why kDivFactor = 0.2 (in Q15).
+ for (cnt = 0; cnt < kSegments; cnt++) {
+ // Update parameters for each segment.
+ curGainQ12 += gaindeltaQ12;
+ curLagQ7 += lagdeltaQ7;
+ indW32 = CalcLrIntQ(curLagQ7, 7);
+ tmpW32 = WEBRTC_SPL_LSHIFT_W32(indW32, 7);
+ tmpW32 -= curLagQ7;
+ frcQQ = WEBRTC_SPL_RSHIFT_W32(tmpW32, 4);
+ frcQQ += 4;
+
+ if (frcQQ == PITCH_FRACS) {
+ frcQQ = 0;
+ }
+ fracoeffQQ = kIntrpCoef[frcQQ];
+
+ // Pitch filtering.
+ WebRtcIsacfix_PitchFilterCore(PITCH_SUBFRAME_LEN / kSegments, curGainQ12,
+ indW32, sign, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+ }
+ }
+
+ // Export buffer and states.
+ memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+ memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ));
+
+ pfp->oldlagQ7 = oldLagQ7;
+ pfp->oldgainQ12 = oldGainQ12;
+
+ if (type == 2) {
+ // Filter look-ahead segment.
+ WebRtcIsacfix_PitchFilterCore(QLOOKAHEAD, curGainQ12, indW32, 1, inystateQQ,
+ ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+ }
+}
+
+
+void WebRtcIsacfix_PitchFilterGains(const WebRtc_Word16* indatQ0,
+ PitchFiltstr* pfp,
+ WebRtc_Word16* lagsQ7,
+ WebRtc_Word16* gainsQ12) {
+ int k, n, m, ind, pos, pos3QQ;
+
+ WebRtc_Word16 ubufQQ[PITCH_INTBUFFSIZE];
+ WebRtc_Word16 oldLagQ7, lagdeltaQ7, curLagQ7;
+ const WebRtc_Word16* fracoeffQQ = NULL;
+ WebRtc_Word16 scale;
+ WebRtc_Word16 cnt = 0, frcQQ, indW16 = 0, tmpW16;
+ WebRtc_Word32 tmpW32, tmp2W32, csum1QQ, esumxQQ;
+
+ // Set up buffer and states.
+ memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+ oldLagQ7 = pfp->oldlagQ7;
+
+ // No interpolation if pitch lag step is big.
+ if ((WEBRTC_SPL_MUL_16_16_RSFT(lagsQ7[0], 3, 1) < oldLagQ7) ||
+ (lagsQ7[0] > WEBRTC_SPL_MUL_16_16_RSFT(oldLagQ7, 3, 1))) {
+ oldLagQ7 = lagsQ7[0];
+ }
+
+ ind = 0;
+ pos = ind + PITCH_BUFFSIZE;
+ scale = 0;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+
+ // Calculate interpolation steps.
+ lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+ lagdeltaQ7 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ lagdeltaQ7, kDivFactor, 15);
+ curLagQ7 = oldLagQ7;
+ oldLagQ7 = lagsQ7[k];
+
+ csum1QQ = 1;
+ esumxQQ = 1;
+
+ // Same as function WebRtcIsacfix_PitchFilter(), we break the pitch
+ // filtering into two for-loops (5 x 12) below.
+ for (cnt = 0; cnt < kSegments; cnt++) {
+ // Update parameters for each segment.
+ curLagQ7 += lagdeltaQ7;
+ indW16 = (WebRtc_Word16)CalcLrIntQ(curLagQ7, 7);
+ tmpW16 = WEBRTC_SPL_LSHIFT_W16(indW16, 7);
+ tmpW16 -= curLagQ7;
+ frcQQ = WEBRTC_SPL_RSHIFT_W16(tmpW16, 4);
+ frcQQ += 4;
+
+ if (frcQQ == PITCH_FRACS) {
+ frcQQ = 0;
+ }
+ fracoeffQQ = kIntrpCoef[frcQQ];
+
+ pos3QQ = pos - (indW16 + 4);
+
+ for (n = 0; n < PITCH_SUBFRAME_LEN / kSegments; n++) {
+ // Filter to get fractional pitch.
+
+ tmpW32 = 0;
+ for (m = 0; m < PITCH_FRACORDER; m++) {
+ tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQ[pos3QQ + m], fracoeffQQ[m]);
+ }
+
+ // Subtract from input and update buffer.
+ ubufQQ[pos] = indatQ0[ind];
+
+ tmp2W32 = WEBRTC_SPL_MUL_16_32_RSFT14(indatQ0[ind], tmpW32);
+ tmpW32 += 8192;
+ tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 14);
+ tmpW32 = WEBRTC_SPL_MUL_16_16(tmpW16, tmpW16);
+
+ if ((tmp2W32 > 1073700000) || (csum1QQ > 1073700000) ||
+ (tmpW32 > 1073700000) || (esumxQQ > 1073700000)) { // 2^30
+ scale++;
+ csum1QQ = WEBRTC_SPL_RSHIFT_W32(csum1QQ, 1);
+ esumxQQ = WEBRTC_SPL_RSHIFT_W32(esumxQQ, 1);
+ }
+ tmp2W32 = WEBRTC_SPL_RSHIFT_W32(tmp2W32, scale);
+ csum1QQ += tmp2W32;
+ tmpW32 = WEBRTC_SPL_RSHIFT_W32(tmpW32, scale);
+ esumxQQ += tmpW32;
+
+ ind++;
+ pos++;
+ pos3QQ++;
+ }
+ }
+
+ if (csum1QQ < esumxQQ) {
+ tmp2W32 = WebRtcSpl_DivResultInQ31(csum1QQ, esumxQQ);
+
+ // Gain should be half the correlation.
+ tmpW32 = WEBRTC_SPL_RSHIFT_W32(tmp2W32, 20);
+ } else {
+ tmpW32 = 4096;
+ }
+ gainsQ12[k] = (WebRtc_Word16)WEBRTC_SPL_SAT(PITCH_MAX_GAIN_Q12, tmpW32, 0);
+ }
+
+ // Export buffer and states.
+ memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+ pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES - 1];
+ pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES - 1];
+
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
new file mode 100644
index 0000000..7ce3b6f
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
@@ -0,0 +1,147 @@
+@
+@ 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.
+@
+
+@ Contains the core loop routine for the pitch filter function in iSAC,
+@ optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in pitch_filter.c.
+
+#include "settings.h"
+
+.arch armv6
+.align 2
+.global WebRtcIsacfix_PitchFilterCore
+
+
+@ void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+@ WebRtc_Word16 gain,
+@ int index,
+@ WebRtc_Word16 sign,
+@ WebRtc_Word16* inputState,
+@ WebRtc_Word16* outputBuf2,
+@ const WebRtc_Word16* coefficient,
+@ WebRtc_Word16* inputBuf,
+@ WebRtc_Word16* outputBuf,
+@ int* index2) {
+
+WebRtcIsacfix_PitchFilterCore:
+.fnstart
+ push {r4-r11}
+ sub sp, #8
+
+ str r0, [sp] @ loopNumber
+ str r3, [sp, #4] @ sign
+ ldr r3, [sp, #44] @ outputBuf2
+ ldr r6, [sp, #60] @ index2
+ ldr r7, [r6] @ *index2
+ ldr r8, [sp, #52] @ inputBuf
+ ldr r12, [sp, #56] @ outputBuf
+
+ add r4, r7, r0
+ str r4, [r6] @ Store return value to index2.
+
+ mov r10, r7, asl #1
+ add r12, r10 @ &outputBuf[*index2]
+ add r8, r10 @ &inputBuf[*index2]
+
+ add r4, r7, #PITCH_BUFFSIZE @ *index2 + PITCH_BUFFSIZE
+ add r6, r3, r4, lsl #1 @ &outputBuf2[*index2 + PITCH_BUFFSIZE]
+ sub r4, r2 @ r2: index
+ sub r4, #2 @ *index2 + PITCH_BUFFSIZE - index - 2
+ add r3, r4, lsl #1 @ &ubufQQpos2[*index2]
+ ldr r9, [sp, #48] @ coefficient
+
+LOOP:
+@ Usage of registers in the loop:
+@ r0: loop counter
+@ r1: gain
+@ r2: tmpW32
+@ r3: &ubufQQpos2[]
+@ r6: &outputBuf2[]
+@ r8: &inputBuf[]
+@ r9: &coefficient[]
+@ r12: &outputBuf[]
+@ r4, r5, r7, r10, r11: scratch
+
+ @ Filter to get fractional pitch.
+ @ The pitch filter loop here is unrolled with 9 multipications.
+ pld [r3]
+ ldr r10, [r3], #4 @ ubufQQpos2[*index2 + 0, *index2 + 1]
+ ldr r4, [r9], #4 @ coefficient[0, 1]
+ ldr r11, [r3], #4
+ ldr r5, [r9], #4
+ smuad r2, r10, r4
+ smlad r2, r11, r5, r2
+
+ ldr r10, [r3], #4
+ ldr r4, [r9], #4
+ ldr r11, [r3], #4
+ ldr r5, [r9], #4
+ smlad r2, r10, r4, r2
+ ldrh r10, [r3], #-14 @ r3 back to &ubufQQpos2[*index2].
+ ldrh r4, [r9], #-16 @ r9 back to &coefficient[0].
+ smlad r2, r11, r5, r2
+ smlabb r2, r10, r4, r2
+
+ @ Saturate to avoid overflow in tmpW16.
+ asr r2, #1
+ add r4, r2, #0x1000
+ ssat r7, #16, r4, asr #13
+
+ @ Shift low pass filter state, and excute the low pass filter.
+ @ The memmove() and the low pass filter loop are unrolled and mixed.
+ smulbb r5, r1, r7
+ add r7, r5, #0x800
+ asr r7, #12 @ Get the value for inputState[0].
+ ldr r11, [sp, #40] @ inputState
+ pld [r11]
+ adr r10, kDampFilter
+ ldrsh r4, [r10], #2 @ kDampFilter[0]
+ mul r2, r7, r4
+ ldr r4, [r11] @ inputState[0, 1], before shift.
+ strh r7, [r11] @ inputState[0], after shift.
+ ldr r5, [r11, #4] @ inputState[2, 3], before shift.
+ ldr r7, [r10], #4 @ kDampFilter[1, 2]
+ ldr r10, [r10] @ kDampFilter[3, 4]
+ str r4, [r11, #2] @ inputState[1, 2], after shift.
+ str r5, [r11, #6] @ inputState[3, 4], after shift.
+ smlad r2, r4, r7, r2
+ smlad r2, r5, r10, r2
+
+ @ Saturate to avoid overflow.
+ @ First shift the sample to the range of [0xC0000000, 0x3FFFFFFF],
+ @ to avoid overflow in the next saturation step.
+ asr r2, #1
+ add r10, r2, #0x2000
+ ssat r10, #16, r10, asr #14
+
+ @ Subtract from input and update buffer.
+ ldr r11, [sp, #4] @ sign
+ ldrsh r4, [r8]
+ ldrsh r7, [r8], #2 @ inputBuf[*index2]
+ smulbb r5, r11, r10
+ subs r0, #1
+ sub r4, r5
+ ssat r2, #16, r4
+ strh r2, [r12], #2 @ outputBuf[*index2]
+
+ add r2, r7
+ ssat r2, #16, r2
+ strh r2, [r6], #2 @ outputBuff2[*index2 + PITCH_BUFFSIZE]
+ bgt LOOP
+
+ add sp, #8
+ pop {r4-r11}
+ bx lr
+.fnend
+
+.align 2
+kDampFilter:
+ .short -2294, 8192, 20972, 8192, -2294
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
new file mode 100644
index 0000000..29b4b6a
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
@@ -0,0 +1,74 @@
+/*
+ * 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 "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+/* Filter coefficicients in Q15. */
+static const WebRtc_Word16 kDampFilter[PITCH_DAMPORDER] = {
+ -2294, 8192, 20972, 8192, -2294
+};
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ WebRtc_Word16 gain,
+ int index,
+ WebRtc_Word16 sign,
+ WebRtc_Word16* inputState,
+ WebRtc_Word16* outputBuf2,
+ const WebRtc_Word16* coefficient,
+ WebRtc_Word16* inputBuf,
+ WebRtc_Word16* outputBuf,
+ int* index2) {
+ int i = 0, j = 0; /* Loop counters. */
+ WebRtc_Word16* ubufQQpos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)];
+ WebRtc_Word16 tmpW16 = 0;
+
+ for (i = 0; i < loopNumber; i++) {
+ WebRtc_Word32 tmpW32 = 0;
+
+ /* Filter to get fractional pitch. */
+ for (j = 0; j < PITCH_FRACORDER; j++) {
+ tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQpos2[*index2 + j], coefficient[j]);
+ }
+
+ /* Saturate to avoid overflow in tmpW16. */
+ tmpW32 = WEBRTC_SPL_SAT(536862719, tmpW32, -536879104);
+ tmpW32 += 8192;
+ tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 14);
+
+ /* Shift low pass filter state. */
+ memmove(&inputState[1], &inputState[0],
+ (PITCH_DAMPORDER - 1) * sizeof(WebRtc_Word16));
+ inputState[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ gain, tmpW16, 12);
+
+ /* Low pass filter. */
+ tmpW32 = 0;
+ /* TODO(kma): Define a static inline function WebRtcSpl_DotProduct()
+ in spl_inl.h to replace this and other similar loops. */
+ for (j = 0; j < PITCH_DAMPORDER; j++) {
+ tmpW32 += WEBRTC_SPL_MUL_16_16(inputState[j], kDampFilter[j]);
+ }
+
+ /* Saturate to avoid overflow in tmpW16. */
+ tmpW32 = WEBRTC_SPL_SAT(1073725439, tmpW32, -1073758208);
+ tmpW32 += 16384;
+ tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 15);
+
+ /* Subtract from input and update buffer. */
+ tmpW32 = inputBuf[*index2] - WEBRTC_SPL_MUL_16_16(sign, tmpW16);
+ outputBuf[*index2] = WebRtcSpl_SatW32ToW16(tmpW32);
+ tmpW32 = inputBuf[*index2] + outputBuf[*index2];
+ outputBuf2[*index2 + PITCH_BUFFSIZE] = WebRtcSpl_SatW32ToW16(tmpW32);
+
+ (*index2)++;
+ }
+}
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c b/src/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
new file mode 100644
index 0000000..50ea658
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
@@ -0,0 +1,149 @@
+/*
+ * 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.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "pitch_gain_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* cdf for quantized pitch filter gains */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchGainCdf[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 WebRtcIsacfix_kLowerlimiGain[3] = {
+ -7, -2, -1
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kUpperlimitGain[3] = {
+ 0, 3, 1
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kMultsGain[2] = {
+ 18, 3
+};
+
+/* size of cdf table */
+const WebRtc_UWord16 WebRtcIsacfix_kCdfTableSizeGain[1] = {
+ 256
+};
+
+/* mean values of pitch filter gains in FIXED point Q12 */
+const WebRtc_Word16 WebRtcIsacfix_kPitchGain1[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 WebRtcIsacfix_kPitchGain2[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 WebRtcIsacfix_kPitchGain3[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 WebRtcIsacfix_kPitchGain4[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
+};
+
+
+
+/* transform matrix in Q12*/
+const WebRtc_Word16 WebRtcIsacfix_kTransform[4][4] = {
+ { -2048, -2048, -2048, -2048 },
+ { 2748, 916, -916, -2748 },
+ { 2048, -2048, -2048, 2048 },
+ { 916, -2748, 2748, -916 }
+};
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h b/src/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
new file mode 100644
index 0000000..788e553
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/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_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include "typedefs.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsacfix_kLowerlimiGain[3];
+extern const WebRtc_Word16 WebRtcIsacfix_kUpperlimitGain[3];
+extern const WebRtc_UWord16 WebRtcIsacfix_kMultsGain[2];
+
+/* mean values of pitch filter gains in Q12*/
+extern const WebRtc_Word16 WebRtcIsacfix_kPitchGain1[144];
+extern const WebRtc_Word16 WebRtcIsacfix_kPitchGain2[144];
+extern const WebRtc_Word16 WebRtcIsacfix_kPitchGain3[144];
+extern const WebRtc_Word16 WebRtcIsacfix_kPitchGain4[144];
+
+/* size of cdf table */
+extern const WebRtc_UWord16 WebRtcIsacfix_kCdfTableSizeGain[1];
+
+/* transform matrix */
+extern const WebRtc_Word16 WebRtcIsacfix_kTransform[4][4];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c b/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
new file mode 100644
index 0000000..81700e4
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
@@ -0,0 +1,306 @@
+/*
+ * 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.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "settings.h"
+#include "pitch_lag_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Lo[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 WebRtcIsacfix_kPitchLagCdf2Lo[20] = {
+ 0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
+ 42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf3Lo[2] = {
+ 0, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Lo[10] = {
+ 0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535
+};
+
+const WebRtc_UWord16 *WebRtcIsacfix_kPitchLagPtrLo[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Lo,
+ WebRtcIsacfix_kPitchLagCdf2Lo,
+ WebRtcIsacfix_kPitchLagCdf3Lo,
+ WebRtcIsacfix_kPitchLagCdf4Lo
+};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeLo[1] = {
+ 128
+};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsacfix_kLowerLimitLo[4] = {
+ -140, -9, 0, -4
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kUpperLimitLo[4] = {
+ -20, 9, 0, 4
+};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsacfix_kInitIndLo[3] = {
+ 10, 1, 5
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Lo[19] = {
+ -17627, -16207, -14409, -12319, -10253, -8200, -6054, -3986, -1948, -19,
+ 1937, 3974, 6064, 8155, 10229, 12270, 14296, 16127, 17520
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Lo[9] = {
+ -7949, -6063, -4036, -1941, 38, 1977, 4060, 6059
+};
+
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Mid[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 WebRtcIsacfix_kPitchLagCdf2Mid[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 WebRtcIsacfix_kPitchLagCdf3Mid[2] = {
+ 0, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Mid[20] = {
+ 0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
+ 44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535
+};
+
+const WebRtc_UWord16 *WebRtcIsacfix_kPitchLagPtrMid[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Mid,
+ WebRtcIsacfix_kPitchLagCdf2Mid,
+ WebRtcIsacfix_kPitchLagCdf3Mid,
+ WebRtcIsacfix_kPitchLagCdf4Mid
+};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeMid[1] = {
+ 256
+};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsacfix_kLowerLimitMid[4] = {
+ -280, -17, 0, -9
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kUpperLimitMid[4] = {
+ -40, 17, 0, 9
+};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsacfix_kInitIndMid[3] = {
+ 18, 1, 10
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Mid[35] = {
+ -17297, -16250, -15416, -14343, -13341, -12363, -11270,
+ -10355, -9122, -8217, -7172, -6083, -5102, -4004, -3060,
+ -1982, -952, -18, 935, 1976, 3040, 4032,
+ 5082, 6065, 7257, 8202, 9264, 10225, 11242,
+ 12234, 13337, 14336, 15374, 16187, 17347
+};
+
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Mid[19] = {
+ -8811, -8081, -7203, -6003, -5057, -4025, -2983, -1964,
+ -891, 29, 921, 1920, 2988, 4064, 5187, 6079, 7173, 8074, 8849
+};
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Hi[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 WebRtcIsacfix_kPitchLagCdf2Hi[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 WebRtcIsacfix_kPitchLagCdf3Hi[2] = {
+ 0, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Hi[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 *WebRtcIsacfix_kPitchLagPtrHi[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Hi,
+ WebRtcIsacfix_kPitchLagCdf2Hi,
+ WebRtcIsacfix_kPitchLagCdf3Hi,
+ WebRtcIsacfix_kPitchLagCdf4Hi
+};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeHi[1] = {
+ 512
+};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsacfix_kLowerLimitHi[4] = {
+ -552, -34, 0, -16
+};
+
+const WebRtc_Word16 WebRtcIsacfix_kUpperLimitHi[4] = {
+ -80, 32, 0, 17
+};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsacfix_kInitIndHi[3] = {
+ 34, 1, 18
+};
+
+/* mean values of pitch filter lags */
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Hi[67] = {
+ -17482, -16896, -16220, -15929, -15329, -14848, -14336, -13807, -13312, -12800, -12218, -11720,
+ -11307, -10649, -10396, -9742, -9148, -8668, -8297, -7718, -7155, -6656, -6231, -5600, -5129,
+ -4610, -4110, -3521, -3040, -2525, -2016, -1506, -995, -477, -5, 469, 991, 1510, 2025, 2526, 3079,
+ 3555, 4124, 4601, 5131, 5613, 6194, 6671, 7140, 7645, 8207, 8601, 9132, 9728, 10359, 10752, 11302,
+ 11776, 12288, 12687, 13204, 13759, 14295, 14810, 15360, 15764, 16350
+};
+
+
+const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Hi[34] = {
+ -8175, -7659, -7205, -6684, -6215, -5651, -5180, -4566, -4087, -3536, -3096,
+ -2532, -1990, -1482, -959, -440, 11, 451, 954, 1492, 2020, 2562, 3059,
+ 3577, 4113, 4618, 5134, 5724, 6060, 6758, 7015, 7716, 8066, 8741
+};
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h b/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
new file mode 100644
index 0000000..9517c29
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
@@ -0,0 +1,103 @@
+/*
+ * 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_FIX_SOURCE_PITCH_LAG_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
+
+
+#include "typedefs.h"
+
+
+/********************* Pitch Filter Lag Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Lo[127];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf2Lo[20];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf3Lo[2];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Lo[10];
+
+extern const WebRtc_UWord16 *WebRtcIsacfix_kPitchLagPtrLo[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeLo[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsacfix_kLowerLimitLo[4];
+extern const WebRtc_Word16 WebRtcIsacfix_kUpperLimitLo[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsacfix_kInitIndLo[3];
+
+/* mean values of pitch filter lags */
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Lo[19];
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Lo[9];
+
+
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Mid[255];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf2Mid[36];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf3Mid[2];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Mid[20];
+
+extern const WebRtc_UWord16 *WebRtcIsacfix_kPitchLagPtrMid[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeMid[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsacfix_kLowerLimitMid[4];
+extern const WebRtc_Word16 WebRtcIsacfix_kUpperLimitMid[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsacfix_kInitIndMid[3];
+
+/* mean values of pitch filter lags */
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Mid[35];
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Mid[19];
+
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf1Hi[511];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf2Hi[68];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf3Hi[2];
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagCdf4Hi[35];
+
+extern const WebRtc_UWord16 *WebRtcIsacfix_kPitchLagPtrHi[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsacfix_kPitchLagSizeHi[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsacfix_kLowerLimitHi[4];
+extern const WebRtc_Word16 WebRtcIsacfix_kUpperLimitHi[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsacfix_kInitIndHi[3];
+
+/* mean values of pitch filter lags */
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag2Hi[67];
+extern const WebRtc_Word16 WebRtcIsacfix_kMeanLag4Hi[34];
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/settings.h b/src/modules/audio_coding/codecs/isac/fix/source/settings.h
new file mode 100644
index 0000000..da88ba2
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/settings.h
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+
+
+/* sampling frequency (Hz) */
+#define FS 16000
+/* 1.5 times Sampling frequency */
+#define FS_1_HALF (WebRtc_UWord32) 24000
+/* Three times Sampling frequency */
+#define FS3 (WebRtc_UWord32) 48000
+/* Eight times Sampling frequency */
+#define FS8 (WebRtc_UWord32) 128000
+
+/* number of samples per frame (either 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder (30ms) */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms 160 /* ((10*FS)/1000) */
+/* Number of samples per 1 ms */
+#define SAMPLES_PER_MSEC 16
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN 40 /* (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
+#define MAX_ORDER 13
+#define LEVINSON_MAX_ORDER 12
+
+/* 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 KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_SHAPE_ORDER 18 /* (ORDERLO + ORDERHI) */
+
+#define KLT_ORDER_GAIN 12 /* (2 * SUBFRAMES) */
+#define KLT_ORDER_SHAPE 108 /* (LPC_SHAPE_ORDER * SUBFRAMES) */
+
+
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* for decimator */
+#define ALLPASSSECTIONS 2
+/* 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
+
+
+
+#define DPMIN_Q10 -10240 /* -10.00 in Q10 */
+#define DPMAX_Q10 10240 /* 10.00 in Q10 */
+#define MINBITS_Q10 10240 /* 10.0 in Q10 */
+
+
+/* array size for byte stream in number of Word16. */
+#define STREAM_MAXW16 300 /* The old maximum size still needed for the decoding */
+#define STREAM_MAXW16_30MS 100 /* 100 Word16 = 200 bytes = 53.4 kbit/s @ 30 ms.framelength */
+#define STREAM_MAXW16_60MS 200 /* 200 Word16 = 400 bytes = 53.4 kbit/s @ 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
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 1
+
+/* Bandwidth estimator */
+
+#define MIN_ISAC_BW 10000 /* Minimum bandwidth in bits per sec */
+#define MAX_ISAC_BW 32000 /* Maxmum bandwidth in bits per sec */
+#define MIN_ISAC_MD 5 /* Minimum Max Delay in ?? */
+#define MAX_ISAC_MD 25 /* Maxmum Max Delay in ?? */
+#define DELAY_CORRECTION_MAX 717
+#define DELAY_CORRECTION_MED 819
+#define Thld_30_60 18000
+#define Thld_60_30 27000
+
+/* assumed header size; we don't know the exact number (header compression may be used) */
+#define HEADER_SIZE 35 /* bytes */
+#define INIT_FRAME_LEN 60
+#define INIT_BN_EST 20000
+#define INIT_BN_EST_Q7 2560000 /* 20 kbps in Q7 */
+#define INIT_REC_BN_EST_Q5 789312 /* INIT_BN_EST + INIT_HDR_RATE in Q5 */
+
+/* 8738 in Q18 is ~ 1/30 */
+/* #define INIT_HDR_RATE (((HEADER_SIZE * 8 * 1000) * 8738) >> NUM_BITS_TO_SHIFT (INIT_FRAME_LEN)) */
+#define INIT_HDR_RATE 4666
+/* 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 800
+/* 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 10240000 /* INIT_BN_EST in Q9 */
+
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN 240 /* (FRAMESAMPLES/2) 30 ms */
+#define PITCH_MAX_LAG 140 /* 57 Hz */
+#define PITCH_MIN_LAG 20 /* 400 Hz */
+#define PITCH_MIN_LAG_Q8 5120 /* 256 * PITCH_MIN_LAG */
+#define OFFSET_Q8 768 /* 256 * 3 */
+
+#define PITCH_MAX_GAIN_Q12 1843 /* 0.45 */
+#define PITCH_LAG_SPAN2 65 /* (PITCH_MAX_LAG/2-PITCH_MIN_LAG/2+5) */
+#define PITCH_CORR_LEN2 60 /* 15 ms */
+#define PITCH_CORR_STEP2 60 /* (PITCH_FRAME_LEN/4) */
+#define PITCH_SUBFRAMES 4
+#define PITCH_SUBFRAME_LEN 60 /* (PITCH_FRAME_LEN/PITCH_SUBFRAMES) */
+
+/* For pitch filter */
+#define PITCH_BUFFSIZE 190 /* (PITCH_MAX_LAG + 50) Extra 50 for fraction and LP filters */
+#define PITCH_INTBUFFSIZE 430 /* (PITCH_FRAME_LEN+PITCH_BUFFSIZE) */
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+
+/* PLC */
+#define DECAY_RATE 10 /* Q15, 20% of decay every lost frame apllied linearly sample by sample*/
+#define PLC_WAS_USED 1
+#define PLC_NOT_USED 3
+#define RECOVERY_OVERLAP 80
+#define RESAMP_RES 256
+#define RESAMP_RES_BIT 8
+
+
+
+/* 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
+/* 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
+/* 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
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c b/src/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000..81b932f
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
@@ -0,0 +1,193 @@
+/*
+ * 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.c
+ *
+ * This file contains tables with AR coefficients, Gain coefficients
+ * and cosine tables.
+ *
+ */
+
+#include "spectrum_ar_model_tables.h"
+#include "settings.h"
+
+/********************* AR Coefficient Tables ************************/
+
+/* cdf for quantized reflection coefficient 1 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc1Cdf[12] = {
+ 0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 2 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc2Cdf[12] = {
+ 0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 3 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc3Cdf[12] = {
+ 0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 4 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc4Cdf[12] = {
+ 0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 5 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc5Cdf[12] = {
+ 0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 6 */
+const WebRtc_UWord16 WebRtcIsacfix_kRc6Cdf[12] = {
+ 0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
+ 65533, 65535
+};
+
+/* representation levels for quantized reflection coefficient 1 */
+const WebRtc_Word16 WebRtcIsacfix_kRc1Levels[11] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const WebRtc_Word16 WebRtcIsacfix_kRc2Levels[11] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const WebRtc_Word16 WebRtcIsacfix_kRc3Levels[11] = {
+ -32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const WebRtc_Word16 WebRtcIsacfix_kRc4Levels[11] = {
+ -32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const WebRtc_Word16 WebRtcIsacfix_kRc5Levels[11] = {
+ -32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const WebRtc_Word16 WebRtcIsacfix_kRc6Levels[11] = {
+ -32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const WebRtc_Word16 WebRtcIsacfix_kRcBound[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 WebRtcIsacfix_kRcInitInd[6] = {
+ 5, 5, 5, 5, 5, 5
+};
+
+/* pointers to AR cdf tables */
+const WebRtc_UWord16 *WebRtcIsacfix_kRcCdfPtr[AR_ORDER] = {
+ WebRtcIsacfix_kRc1Cdf,
+ WebRtcIsacfix_kRc2Cdf,
+ WebRtcIsacfix_kRc3Cdf,
+ WebRtcIsacfix_kRc4Cdf,
+ WebRtcIsacfix_kRc5Cdf,
+ WebRtcIsacfix_kRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const WebRtc_Word16 *WebRtcIsacfix_kRcLevPtr[AR_ORDER] = {
+ WebRtcIsacfix_kRc1Levels,
+ WebRtcIsacfix_kRc2Levels,
+ WebRtcIsacfix_kRc3Levels,
+ WebRtcIsacfix_kRc4Levels,
+ WebRtcIsacfix_kRc5Levels,
+ WebRtcIsacfix_kRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+
+/* cdf for Gain coefficient */
+const WebRtc_UWord16 WebRtcIsacfix_kGainCdf[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 WebRtcIsacfix_kGain2Lev[18] = {
+ 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 WebRtcIsacfix_kGain2Bound[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 *WebRtcIsacfix_kGainPtr[1] = {
+ WebRtcIsacfix_kGainCdf
+};
+
+/* gain initial index for gain quantizer and cdf table search */
+const WebRtc_UWord16 WebRtcIsacfix_kGainInitInd[1] = {
+ 11
+};
+
+
+/************************* Cosine Tables ****************************/
+
+/* cosine table */
+const WebRtc_Word16 WebRtcIsacfix_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/fix/source/spectrum_ar_model_tables.h b/src/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000..b506d0e
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
@@ -0,0 +1,96 @@
+/*
+ * 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_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include "typedefs.h"
+#include "settings.h"
+
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc1Cdf[12];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc2Cdf[12];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc3Cdf[12];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc4Cdf[12];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc5Cdf[12];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRc6Cdf[12];
+
+/* representation levels for quantized reflection coefficient 1 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc1Levels[11];
+
+/* representation levels for quantized reflection coefficient 2 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc2Levels[11];
+
+/* representation levels for quantized reflection coefficient 3 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc3Levels[11];
+
+/* representation levels for quantized reflection coefficient 4 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc4Levels[11];
+
+/* representation levels for quantized reflection coefficient 5 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc5Levels[11];
+
+/* representation levels for quantized reflection coefficient 6 */
+extern const WebRtc_Word16 WebRtcIsacfix_kRc6Levels[11];
+
+/* quantization boundary levels for reflection coefficients */
+extern const WebRtc_Word16 WebRtcIsacfix_kRcBound[12];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsacfix_kRcInitInd[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const WebRtc_UWord16 *WebRtcIsacfix_kRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const WebRtc_Word16 *WebRtcIsacfix_kRcLevPtr[AR_ORDER];
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const WebRtc_UWord16 WebRtcIsacfix_kGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsacfix_kGain2Lev[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsacfix_kGain2Bound[19];
+
+/* pointer to Gain cdf table */
+extern const WebRtc_UWord16 *WebRtcIsacfix_kGainPtr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsacfix_kGainInitInd[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const WebRtc_Word16 WebRtcIsacfix_kCos[6][60];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/structs.h b/src/modules/audio_coding/codecs/isac/fix/source/structs.h
new file mode 100644
index 0000000..c038a43
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/structs.h
@@ -0,0 +1,382 @@
+/*
+ * 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.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "typedefs.h"
+
+/* Bitstream struct for decoder */
+typedef struct Bitstreamstruct_dec {
+
+ WebRtc_UWord16 *stream; /* Pointer to bytestream to decode */
+ WebRtc_UWord32 W_upper; /* Upper boundary of interval W */
+ WebRtc_UWord32 streamval;
+ WebRtc_UWord16 stream_index; /* Index to the current position in bytestream */
+ WebRtc_Word16 full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+
+} Bitstr_dec;
+
+/* Bitstream struct for encoder */
+typedef struct Bitstreamstruct_enc {
+
+ WebRtc_UWord16 stream[STREAM_MAXW16_60MS]; /* Vector for adding encoded bytestream */
+ WebRtc_UWord32 W_upper; /* Upper boundary of interval W */
+ WebRtc_UWord32 streamval;
+ WebRtc_UWord16 stream_index; /* Index to the current position in bytestream */
+ WebRtc_Word16 full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+
+} Bitstr_enc;
+
+
+typedef struct {
+
+ WebRtc_Word16 DataBufferLoQ0[WINLEN];
+ WebRtc_Word16 DataBufferHiQ0[WINLEN];
+
+ WebRtc_Word32 CorrBufLoQQ[ORDERLO+1];
+ WebRtc_Word32 CorrBufHiQQ[ORDERHI+1];
+
+ WebRtc_Word16 CorrBufLoQdom[ORDERLO+1];
+ WebRtc_Word16 CorrBufHiQdom[ORDERHI+1];
+
+ WebRtc_Word32 PreStateLoGQ15[ORDERLO+1];
+ WebRtc_Word32 PreStateHiGQ15[ORDERHI+1];
+
+ WebRtc_UWord32 OldEnergy;
+
+} MaskFiltstr_enc;
+
+
+
+typedef struct {
+
+ WebRtc_Word16 PostStateLoGQ0[ORDERLO+1];
+ WebRtc_Word16 PostStateHiGQ0[ORDERHI+1];
+
+ WebRtc_UWord32 OldEnergy;
+
+} MaskFiltstr_dec;
+
+
+
+
+
+
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+
+ WebRtc_Word32 INSTAT1_fix[2*(QORDER-1)];
+ WebRtc_Word32 INSTAT2_fix[2*(QORDER-1)];
+ WebRtc_Word16 INLABUF1_fix[QLOOKAHEAD];
+ WebRtc_Word16 INLABUF2_fix[QLOOKAHEAD];
+
+ /* High pass filter */
+ WebRtc_Word32 HPstates_fix[HPORDER];
+
+} PreFiltBankstr;
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+ WebRtc_Word32 STATE_0_LOWER_fix[2*POSTQORDER];
+ WebRtc_Word32 STATE_0_UPPER_fix[2*POSTQORDER];
+
+ /* High pass filter */
+
+ WebRtc_Word32 HPstates1_fix[HPORDER];
+ WebRtc_Word32 HPstates2_fix[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+
+
+ /* data buffer for pitch filter */
+ WebRtc_Word16 ubufQQ[PITCH_BUFFSIZE];
+
+ /* low pass state vector */
+ WebRtc_Word16 ystateQQ[PITCH_DAMPORDER];
+
+ /* old lag and gain */
+ WebRtc_Word16 oldlagQ7;
+ WebRtc_Word16 oldgainQ12;
+
+} PitchFiltstr;
+
+
+
+typedef struct {
+
+ //for inital estimator
+ WebRtc_Word16 dec_buffer16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2];
+ WebRtc_Word32 decimator_state32[2*ALLPASSSECTIONS+1];
+ WebRtc_Word16 inbuf[QLOOKAHEAD];
+
+ PitchFiltstr PFstr_wght;
+ PitchFiltstr PFstr;
+
+
+} PitchAnalysisStruct;
+
+
+typedef struct {
+ /* Parameters used in PLC to avoid re-computation */
+
+ /* --- residual signals --- */
+ WebRtc_Word16 prevPitchInvIn[FRAMESAMPLES/2];
+ WebRtc_Word16 prevPitchInvOut[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
+ WebRtc_Word32 prevHP[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
+
+
+ WebRtc_Word16 decayCoeffPriodic; /* how much to supress a sample */
+ WebRtc_Word16 decayCoeffNoise;
+ WebRtc_Word16 used; /* if PLC is used */
+
+
+ WebRtc_Word16 *lastPitchLP; // [FRAMESAMPLES/2]; saved 240;
+
+
+ /* --- LPC side info --- */
+ WebRtc_Word16 lofilt_coefQ15[ ORDERLO ];
+ WebRtc_Word16 hifilt_coefQ15[ ORDERHI ];
+ WebRtc_Word32 gain_lo_hiQ17[2];
+
+ /* --- LTP side info --- */
+ WebRtc_Word16 AvgPitchGain_Q12;
+ WebRtc_Word16 lastPitchGain_Q12;
+ WebRtc_Word16 lastPitchLag_Q7;
+
+ /* --- Add-overlap in recovery packet --- */
+ WebRtc_Word16 overlapLP[ RECOVERY_OVERLAP ]; // [FRAMESAMPLES/2]; saved 160
+
+ WebRtc_Word16 pitchCycles;
+ WebRtc_Word16 A;
+ WebRtc_Word16 B;
+ WebRtc_Word16 pitchIndex;
+ WebRtc_Word16 stretchLag;
+ WebRtc_Word16 *prevPitchLP; // [ FRAMESAMPLES/2 ]; saved 240
+ WebRtc_Word16 seed;
+
+ WebRtc_Word16 std;
+} PLCstr;
+
+
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+
+ WebRtc_Word16 prevFrameSizeMs; /* Previous frame size (in ms) */
+ WebRtc_UWord16 prevRtpNumber; /* Previous RTP timestamp from received packet */
+ /* (in samples relative beginning) */
+ WebRtc_UWord32 prevSendTime; /* Send time for previous packet, from RTP header */
+ WebRtc_UWord32 prevArrivalTime; /* Arrival time for previous packet (in ms using timeGetTime()) */
+ WebRtc_UWord16 prevRtpRate; /* rate of previous packet, derived from RTP timestamps (in bits/s) */
+ WebRtc_UWord32 lastUpdate; /* Time since the last update of the Bottle Neck estimate (in samples) */
+ WebRtc_UWord32 lastReduction; /* Time sinse the last reduction (in samples) */
+ WebRtc_Word32 countUpdates; /* How many times the estimate was update in the beginning */
+
+ /* The estimated bottle neck rate from there to here (in bits/s) */
+ WebRtc_UWord32 recBw;
+ WebRtc_UWord32 recBwInv;
+ WebRtc_UWord32 recBwAvg;
+ WebRtc_UWord32 recBwAvgQ;
+
+ WebRtc_UWord32 minBwInv;
+ WebRtc_UWord32 maxBwInv;
+
+ /* The estimated mean absolute jitter value, as seen on this side (in ms) */
+ WebRtc_Word32 recJitter;
+ WebRtc_Word32 recJitterShortTerm;
+ WebRtc_Word32 recJitterShortTermAbs;
+ WebRtc_Word32 recMaxDelay;
+ WebRtc_Word32 recMaxDelayAvgQ;
+
+
+ WebRtc_Word16 recHeaderRate; /* (assumed) bitrate for headers (bps) */
+
+ WebRtc_UWord32 sendBwAvg; /* The estimated bottle neck rate from here to there (in bits/s) */
+ WebRtc_Word32 sendMaxDelayAvg; /* The estimated mean absolute jitter value, as seen on the other siee (in ms) */
+
+
+ WebRtc_Word16 countRecPkts; /* number of packets received since last update */
+ WebRtc_Word16 highSpeedRec; /* flag for marking that a high speed network has been detected downstream */
+
+ /* number of consecutive pkts sent during which the bwe estimate has
+ remained at a value greater than the downstream threshold for determining highspeed network */
+ WebRtc_Word16 countHighSpeedRec;
+
+ /* flag indicating bwe should not adjust down immediately for very late pckts */
+ WebRtc_Word16 inWaitPeriod;
+
+ /* variable holding the time of the start of a window of time when
+ bwe should not adjust down immediately for very late pckts */
+ WebRtc_UWord32 startWaitPeriod;
+
+ /* number of consecutive pkts sent during which the bwe estimate has
+ remained at a value greater than the upstream threshold for determining highspeed network */
+ WebRtc_Word16 countHighSpeedSent;
+
+ /* flag indicated the desired number of packets over threshold rate have been sent and
+ bwe will assume the connection is over broadband network */
+ WebRtc_Word16 highSpeedSend;
+
+
+
+
+} BwEstimatorstr;
+
+
+typedef struct {
+
+ /* boolean, flags if previous packet exceeded B.N. */
+ WebRtc_Word16 PrevExceed;
+ /* ms */
+ WebRtc_Word16 ExceedAgo;
+ /* packets left to send in current burst */
+ WebRtc_Word16 BurstCounter;
+ /* packets */
+ WebRtc_Word16 InitCounter;
+ /* ms remaining in buffer when next packet will be sent */
+ WebRtc_Word16 StillBuffered;
+
+} RateModel;
+
+/* 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 */
+ WebRtc_Word16 pitchGain_index[2];
+
+ /* Pitch Lag */
+ WebRtc_Word32 meanGain[2];
+ WebRtc_Word16 pitchIndex[PITCH_SUBFRAMES*2];
+
+ /* LPC */
+ WebRtc_Word32 LPCcoeffs_g[12*2]; /* KLT_ORDER_GAIN = 12 */
+ WebRtc_Word16 LPCindex_s[108*2]; /* KLT_ORDER_SHAPE = 108 */
+ WebRtc_Word16 LPCindex_g[12*2]; /* KLT_ORDER_GAIN = 12 */
+
+ /* 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 {
+
+ Bitstr_enc bitstr_obj;
+ MaskFiltstr_enc maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PitchAnalysisStruct pitchanalysisstr_obj;
+ RateModel rate_data_obj;
+
+ WebRtc_Word16 buffer_index;
+ WebRtc_Word16 current_framesamples;
+
+ WebRtc_Word16 data_buffer_fix[FRAMESAMPLES]; // the size was MAX_FRAMESAMPLES
+
+ WebRtc_Word16 frame_nb;
+ WebRtc_Word16 BottleNeck;
+ WebRtc_Word16 MaxDelay;
+ WebRtc_Word16 new_framelength;
+ WebRtc_Word16 s2nr;
+ WebRtc_UWord16 MaxBits;
+
+ WebRtc_Word16 bitstr_seed;
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ PostFiltBankstr interpolatorstr_obj;
+#endif
+
+ ISAC_SaveEncData_t *SaveEnc_ptr;
+ WebRtc_Word16 payloadLimitBytes30; /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 payloadLimitBytes60; /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 maxPayloadBytes; /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ WebRtc_Word16 maxRateInBytes; /* Maximum allowed rate in bytes per 30 msec packet */
+ WebRtc_Word16 enforceFrameSize; /* If set iSAC will never change packet size */
+
+} ISACFIX_EncInst_t;
+
+
+typedef struct {
+
+ Bitstr_dec bitstr_obj;
+ MaskFiltstr_dec maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PLCstr plcstr_obj; /* TS; for packet loss concealment */
+
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ PreFiltBankstr decimatorstr_obj;
+#endif
+
+} ISACFIX_DecInst_t;
+
+
+
+typedef struct {
+
+ ISACFIX_EncInst_t ISACenc_obj;
+ ISACFIX_DecInst_t ISACdec_obj;
+ BwEstimatorstr bwestimator_obj;
+ WebRtc_Word16 CodingMode; /* 0 = adaptive; 1 = instantaneous */
+ WebRtc_Word16 errorcode;
+ WebRtc_Word16 initflag; /* 0 = nothing initiated; 1 = encoder or decoder */
+ /* not initiated; 2 = all initiated */
+} ISACFIX_SubStruct;
+
+
+typedef struct {
+ WebRtc_Word32 lpcGains[12]; /* 6 lower-band & 6 upper-band we may need to double it for 60*/
+ /* */
+ WebRtc_UWord32 W_upper; /* Upper boundary of interval W */
+ WebRtc_UWord32 streamval;
+ WebRtc_UWord16 stream_index; /* Index to the current position in bytestream */
+ WebRtc_Word16 full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+ WebRtc_UWord16 beforeLastWord;
+ WebRtc_UWord16 lastWord;
+} transcode_obj;
+
+
+//Bitstr_enc myBitStr;
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_ */
diff --git a/src/modules/audio_coding/codecs/isac/fix/source/transform.c b/src/modules/audio_coding/codecs/isac/fix/source/transform.c
new file mode 100644
index 0000000..56ef9f2
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/source/transform.c
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+/*
+ * WebRtcIsacfix_kTransform.c
+ *
+ * Transform functions
+ *
+ */
+
+#include "fft.h"
+#include "codec.h"
+#include "settings.h"
+
+
+/* Cosine table 1 in Q14 */
+static const WebRtc_Word16 kCosTab1[FRAMESAMPLES/2] = {
+ 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315, 16294, 16270,
+ 16244, 16214, 16182, 16147, 16110, 16069, 16026, 15980, 15931, 15880,
+ 15826, 15769, 15709, 15647, 15582, 15515, 15444, 15371, 15296, 15218,
+ 15137, 15053, 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295,
+ 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380, 13255, 13128,
+ 12998, 12867, 12733, 12597, 12458, 12318, 12176, 12031, 11885, 11736,
+ 11585, 11433, 11278, 11121, 10963, 10803, 10641, 10477, 10311, 10143,
+ 9974, 9803, 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377,
+ 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859, 6664, 6467,
+ 6270, 6071, 5872, 5671, 5469, 5266, 5063, 4859, 4653, 4447,
+ 4240, 4033, 3825, 3616, 3406, 3196, 2986, 2775, 2563, 2351,
+ 2139, 1926, 1713, 1499, 1285, 1072, 857, 643, 429, 214,
+ 0, -214, -429, -643, -857, -1072, -1285, -1499, -1713, -1926,
+ -2139, -2351, -2563, -2775, -2986, -3196, -3406, -3616, -3825, -4033,
+ -4240, -4447, -4653, -4859, -5063, -5266, -5469, -5671, -5872, -6071,
+ -6270, -6467, -6664, -6859, -7053, -7246, -7438, -7629, -7818, -8006,
+ -8192, -8377, -8561, -8743, -8923, -9102, -9280, -9456, -9630, -9803,
+ -9974, -10143, -10311, -10477, -10641, -10803, -10963, -11121, -11278, -11433,
+ -11585, -11736, -11885, -12031, -12176, -12318, -12458, -12597, -12733, -12867,
+ -12998, -13128, -13255, -13380, -13502, -13623, -13741, -13856, -13970, -14081,
+ -14189, -14295, -14399, -14500, -14598, -14694, -14788, -14879, -14968, -15053,
+ -15137, -15218, -15296, -15371, -15444, -15515, -15582, -15647, -15709, -15769,
+ -15826, -15880, -15931, -15980, -16026, -16069, -16110, -16147, -16182, -16214,
+ -16244, -16270, -16294, -16315, -16333, -16349, -16362, -16371, -16378, -16383
+};
+
+
+/* Sine table 1 in Q14 */
+static const WebRtc_Word16 kSinTab1[FRAMESAMPLES/2] = {
+ 0, 214, 429, 643, 857, 1072, 1285, 1499, 1713, 1926,
+ 2139, 2351, 2563, 2775, 2986, 3196, 3406, 3616, 3825, 4033,
+ 4240, 4447, 4653, 4859, 5063, 5266, 5469, 5671, 5872, 6071,
+ 6270, 6467, 6664, 6859, 7053, 7246, 7438, 7629, 7818, 8006,
+ 8192, 8377, 8561, 8743, 8923, 9102, 9280, 9456, 9630, 9803,
+ 9974, 10143, 10311, 10477, 10641, 10803, 10963, 11121, 11278, 11433,
+ 11585, 11736, 11885, 12031, 12176, 12318, 12458, 12597, 12733, 12867,
+ 12998, 13128, 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081,
+ 14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879, 14968, 15053,
+ 15137, 15218, 15296, 15371, 15444, 15515, 15582, 15647, 15709, 15769,
+ 15826, 15880, 15931, 15980, 16026, 16069, 16110, 16147, 16182, 16214,
+ 16244, 16270, 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383,
+ 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315, 16294, 16270,
+ 16244, 16214, 16182, 16147, 16110, 16069, 16026, 15980, 15931, 15880,
+ 15826, 15769, 15709, 15647, 15582, 15515, 15444, 15371, 15296, 15218,
+ 15137, 15053, 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295,
+ 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380, 13255, 13128,
+ 12998, 12867, 12733, 12597, 12458, 12318, 12176, 12031, 11885, 11736,
+ 11585, 11433, 11278, 11121, 10963, 10803, 10641, 10477, 10311, 10143,
+ 9974, 9803, 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377,
+ 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859, 6664, 6467,
+ 6270, 6071, 5872, 5671, 5469, 5266, 5063, 4859, 4653, 4447,
+ 4240, 4033, 3825, 3616, 3406, 3196, 2986, 2775, 2563, 2351,
+ 2139, 1926, 1713, 1499, 1285, 1072, 857, 643, 429, 214
+};
+
+
+/* Cosine table 2 in Q14 */
+static const WebRtc_Word16 kCosTab2[FRAMESAMPLES/4] = {
+ 107, -322, 536, -750, 965, -1179, 1392, -1606, 1819, -2032,
+ 2245, -2457, 2669, -2880, 3091, -3301, 3511, -3720, 3929, -4137,
+ 4344, -4550, 4756, -4961, 5165, -5368, 5570, -5771, 5971, -6171,
+ 6369, -6566, 6762, -6957, 7150, -7342, 7534, -7723, 7912, -8099,
+ 8285, -8469, 8652, -8833, 9013, -9191, 9368, -9543, 9717, -9889,
+ 10059, -10227, 10394, -10559, 10722, -10883, 11042, -11200, 11356, -11509,
+ 11661, -11810, 11958, -12104, 12247, -12389, 12528, -12665, 12800, -12933,
+ 13063, -13192, 13318, -13441, 13563, -13682, 13799, -13913, 14025, -14135,
+ 14242, -14347, 14449, -14549, 14647, -14741, 14834, -14924, 15011, -15095,
+ 15178, -15257, 15334, -15408, 15480, -15549, 15615, -15679, 15739, -15798,
+ 15853, -15906, 15956, -16003, 16048, -16090, 16129, -16165, 16199, -16229,
+ 16257, -16283, 16305, -16325, 16342, -16356, 16367, -16375, 16381, -16384
+};
+
+
+/* Sine table 2 in Q14 */
+static const WebRtc_Word16 kSinTab2[FRAMESAMPLES/4] = {
+ 16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305, 16283, -16257,
+ 16229, -16199, 16165, -16129, 16090, -16048, 16003, -15956, 15906, -15853,
+ 15798, -15739, 15679, -15615, 15549, -15480, 15408, -15334, 15257, -15178,
+ 15095, -15011, 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242,
+ 14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318, 13192, -13063,
+ 12933, -12800, 12665, -12528, 12389, -12247, 12104, -11958, 11810, -11661,
+ 11509, -11356, 11200, -11042, 10883, -10722, 10559, -10394, 10227, -10059,
+ 9889, -9717, 9543, -9368, 9191, -9013, 8833, -8652, 8469, -8285,
+ 8099, -7912, 7723, -7534, 7342, -7150, 6957, -6762, 6566, -6369,
+ 6171, -5971, 5771, -5570, 5368, -5165, 4961, -4756, 4550, -4344,
+ 4137, -3929, 3720, -3511, 3301, -3091, 2880, -2669, 2457, -2245,
+ 2032, -1819, 1606, -1392, 1179, -965, 750, -536, 322, -107
+};
+
+
+
+void WebRtcIsacfix_Time2Spec(WebRtc_Word16 *inre1Q9,
+ WebRtc_Word16 *inre2Q9,
+ WebRtc_Word16 *outreQ7,
+ WebRtc_Word16 *outimQ7)
+{
+
+ int k;
+ WebRtc_Word32 tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
+ WebRtc_Word16 tmp1rQ14, tmp1iQ14;
+ WebRtc_Word32 xrQ16, xiQ16, yrQ16, yiQ16;
+ WebRtc_Word32 v1Q16, v2Q16;
+ WebRtc_Word16 factQ19, sh;
+
+ /* Multiply with complex exponentials and combine into one complex vector */
+ factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921
+ for (k = 0; k < FRAMESAMPLES/2; k++) {
+ tmp1rQ14 = kCosTab1[k];
+ tmp1iQ14 = kSinTab1[k];
+ xrQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre1Q9[k]) + WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre2Q9[k]), 7);
+ xiQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre2Q9[k]) - WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre1Q9[k]), 7);
+ tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16
+ tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16
+ }
+
+
+ xrQ16 = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2);
+ yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2);
+ if (yrQ16>xrQ16) {
+ xrQ16 = yrQ16;
+ }
+
+ sh = WebRtcSpl_NormW32(xrQ16);
+ sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+ //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ inre1Q9[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmpreQ16[k], sh); //Q(16+sh)
+ inre2Q9[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmpimQ16[k], sh); //Q(16+sh)
+ }
+ } else {
+ WebRtc_Word32 round = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, -sh-1);
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ inre1Q9[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpreQ16[k]+round, -sh); //Q(16+sh)
+ inre2Q9[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpimQ16[k]+round, -sh); //Q(16+sh)
+ }
+ }
+
+ /* Get DFT */
+ WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inre1Q9[k], sh); //Q(16+sh) -> Q16
+ tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inre2Q9[k], sh); //Q(16+sh) -> Q16
+ }
+ } else {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ tmpreQ16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inre1Q9[k], -sh); //Q(16+sh) -> Q16
+ tmpimQ16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inre2Q9[k], -sh); //Q(16+sh) -> Q16
+ }
+ }
+
+
+ /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+ for (k = 0; k < FRAMESAMPLES/4; k++) {
+ xrQ16 = tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+ yiQ16 = -tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+ xiQ16 = tmpimQ16[k] - tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+ yrQ16 = tmpimQ16[k] + tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+ tmp1rQ14 = kCosTab2[k];
+ tmp1iQ14 = kSinTab2[k];
+ v1Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xiQ16);
+ v2Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xiQ16);
+ outreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(v1Q16, 9);
+ outimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(v2Q16, 9);
+ v1Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yiQ16);
+ v2Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yiQ16);
+ outreQ7[FRAMESAMPLES/2 - 1 - k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(v1Q16, 9); //CalcLrIntQ(v1Q16, 9);
+ outimQ7[FRAMESAMPLES/2 - 1 - k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(v2Q16, 9); //CalcLrIntQ(v2Q16, 9);
+
+ }
+}
+
+
+void WebRtcIsacfix_Spec2Time(WebRtc_Word16 *inreQ7, WebRtc_Word16 *inimQ7, WebRtc_Word32 *outre1Q16, WebRtc_Word32 *outre2Q16)
+{
+
+ int k;
+ WebRtc_Word16 tmp1rQ14, tmp1iQ14;
+ WebRtc_Word32 xrQ16, xiQ16, yrQ16, yiQ16;
+ WebRtc_Word32 tmpInRe, tmpInIm, tmpInRe2, tmpInIm2;
+ WebRtc_Word16 factQ11;
+ WebRtc_Word16 sh;
+
+ for (k = 0; k < FRAMESAMPLES/4; k++) {
+ /* Move zero in time to beginning of frames */
+ tmp1rQ14 = kCosTab2[k];
+ tmp1iQ14 = kSinTab2[k];
+
+ tmpInRe = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inreQ7[k], 9); // Q7 -> Q16
+ tmpInIm = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inimQ7[k], 9); // Q7 -> Q16
+ tmpInRe2 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inreQ7[FRAMESAMPLES/2 - 1 - k], 9); // Q7 -> Q16
+ tmpInIm2 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inimQ7[FRAMESAMPLES/2 - 1 - k], 9); // Q7 -> Q16
+
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe);
+ yrQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm2) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe2);
+ yiQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe2) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm2);
+
+ /* Combine into one vector, z = x + j * y */
+ outre1Q16[k] = xrQ16 - yiQ16;
+ outre1Q16[FRAMESAMPLES/2 - 1 - k] = xrQ16 + yiQ16;
+ outre2Q16[k] = xiQ16 + yrQ16;
+ outre2Q16[FRAMESAMPLES/2 - 1 - k] = -xiQ16 + yrQ16;
+ }
+
+ /* Get IDFT */
+ tmpInRe = WebRtcSpl_MaxAbsValueW32(outre1Q16, 240);
+ tmpInIm = WebRtcSpl_MaxAbsValueW32(outre2Q16, 240);
+ if (tmpInIm>tmpInRe) {
+ tmpInRe = tmpInIm;
+ }
+
+ sh = WebRtcSpl_NormW32(tmpInRe);
+ sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+ //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<240; k++) {
+ inreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(outre1Q16[k], sh); //Q(16+sh)
+ inimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(outre2Q16[k], sh); //Q(16+sh)
+ }
+ } else {
+ WebRtc_Word32 round = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, -sh-1);
+ for (k=0; k<240; k++) {
+ inreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(outre1Q16[k]+round, -sh); //Q(16+sh)
+ inimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(outre2Q16[k]+round, -sh); //Q(16+sh)
+ }
+ }
+
+ WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inreQ7[k], sh); //Q(16+sh) -> Q16
+ outre2Q16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inimQ7[k], sh); //Q(16+sh) -> Q16
+ }
+ } else {
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inreQ7[k], -sh); //Q(16+sh) -> Q16
+ outre2Q16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inimQ7[k], -sh); //Q(16+sh) -> Q16
+ }
+ }
+
+ /* Divide through by the normalizing constant: */
+ /* scale all values with 1/240, i.e. with 273 in Q16 */
+ /* 273/65536 ~= 0.0041656 */
+ /* 1/240 ~= 0.0041666 */
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre1Q16[k]);
+ outre2Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]);
+ }
+
+ /* Demodulate and separate */
+ factQ11 = 31727; // sqrt(240) in Q11 is round(15.49193338482967*2048) = 31727
+ for (k = 0; k < FRAMESAMPLES/2; k++) {
+ tmp1rQ14 = kCosTab1[k];
+ tmp1iQ14 = kSinTab1[k];
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre1Q16[k]) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre2Q16[k]);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre2Q16[k]) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre1Q16[k]);
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16);
+ outre2Q16[k] = xiQ16;
+ outre1Q16[k] = xrQ16;
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/ISACHist.cc b/src/modules/audio_coding/codecs/isac/fix/test/ISACHist.cc
new file mode 100644
index 0000000..753acd7
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/ISACHist.cc
@@ -0,0 +1,173 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+//#include "isac_codec.h"
+//#include "isac_structs.h"
+#include "isacfix.h"
+
+
+#define NUM_CODECS 1
+
+int main(int argc, char* argv[])
+{
+ FILE *inFileList;
+ FILE *audioFile;
+ FILE *outFile;
+ char audioFileName[501];
+ short audioBuff[960];
+ short encoded[600];
+ short startAudio;
+ short encodedLen;
+ ISACFIX_MainStruct *isac_struct;
+ unsigned long int hist[601];
+
+ // reset the histogram
+ for(short n=0; n < 601; n++)
+ {
+ hist[n] = 0;
+ }
+
+
+ inFileList = fopen(argv[1], "r");
+ if(inFileList == NULL)
+ {
+ printf("Could not open the input file.\n");
+ getchar();
+ exit(-1);
+ }
+ outFile = fopen(argv[2], "w");
+ if(outFile == NULL)
+ {
+ printf("Could not open the histogram file.\n");
+ getchar();
+ exit(-1);
+ }
+
+ short frameSizeMsec = 30;
+ if(argc > 3)
+ {
+ frameSizeMsec = atoi(argv[3]);
+ }
+
+ short audioOffset = 0;
+ if(argc > 4)
+ {
+ audioOffset = atoi(argv[4]);
+ }
+ int ok;
+ ok = WebRtcIsacfix_Create(&isac_struct);
+ // instantaneous mode
+ ok |= WebRtcIsacfix_EncoderInit(isac_struct, 1);
+ // is not used but initialize
+ ok |= WebRtcIsacfix_DecoderInit(isac_struct);
+ ok |= WebRtcIsacfix_Control(isac_struct, 32000, frameSizeMsec);
+
+ if(ok != 0)
+ {
+ printf("\nProblem in seting up iSAC\n");
+ exit(-1);
+ }
+
+ while( fgets(audioFileName, 500, inFileList) != NULL )
+ {
+ // remove trailing white-spaces and any Cntrl character
+ if(strlen(audioFileName) == 0)
+ {
+ continue;
+ }
+ short n = strlen(audioFileName) - 1;
+ while(isspace(audioFileName[n]) || iscntrl(audioFileName[n]))
+ {
+ audioFileName[n] = '\0';
+ n--;
+ if(n < 0)
+ {
+ break;
+ }
+ }
+
+ // remove leading spaces
+ if(strlen(audioFileName) == 0)
+ {
+ continue;
+ }
+ n = 0;
+ while((isspace(audioFileName[n]) || iscntrl(audioFileName[n])) &&
+ (audioFileName[n] != '\0'))
+ {
+ n++;
+ }
+ memmove(audioFileName, &audioFileName[n], 500 - n);
+ if(strlen(audioFileName) == 0)
+ {
+ continue;
+ }
+ audioFile = fopen(audioFileName, "rb");
+ if(audioFile == NULL)
+ {
+ printf("\nCannot open %s!!!!!\n", audioFileName);
+ exit(0);
+ }
+
+ if(audioOffset > 0)
+ {
+ fseek(audioFile, (audioOffset<<1), SEEK_SET);
+ }
+
+ while(fread(audioBuff, sizeof(short), (480*frameSizeMsec/30), audioFile) >= (480*frameSizeMsec/30))
+ {
+ startAudio = 0;
+ do
+ {
+ encodedLen = WebRtcIsacfix_Encode(isac_struct,
+ &audioBuff[startAudio], encoded);
+ startAudio += 160;
+ } while(encodedLen == 0);
+
+ if(encodedLen < 0)
+ {
+ printf("\nEncoding Error!!!\n");
+ exit(0);
+ }
+ hist[encodedLen]++;
+ }
+ fclose(audioFile);
+ }
+ fclose(inFileList);
+ unsigned long totalFrames = 0;
+ for(short n=0; n < 601; n++)
+ {
+ totalFrames += hist[n];
+ fprintf(outFile, "%10lu\n", hist[n]);
+ }
+ fclose(outFile);
+
+ short topTenCntr = 0;
+ printf("\nTotal number of Frames %lu\n\n", totalFrames);
+ printf("Payload Len # occurences\n");
+ printf("=========== ============\n");
+
+ for(short n = 600; (n >= 0) && (topTenCntr < 10); n--)
+ {
+ if(hist[n] > 0)
+ {
+ topTenCntr++;
+ printf(" %3d %3d\n", n, hist[n]);
+ }
+ }
+ WebRtcIsacfix_Free(isac_struct);
+ return 0;
+}
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/Isac_test.cc b/src/modules/audio_coding/codecs/isac/fix/test/Isac_test.cc
new file mode 100644
index 0000000..2791db4
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/Isac_test.cc
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+/******************************************************************
+ Stand Alone test application for ISACFIX and ISAC LC
+
+******************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedefs.h"
+
+#include "isacfix.h"
+ISACFIX_MainStruct *ISACfix_inst;
+
+#define FS 16000
+
+
+typedef struct {
+ WebRtc_UWord32 arrival_time; /* samples */
+ WebRtc_UWord32 sample_count; /* samples */
+ WebRtc_UWord16 rtp_number;
+} BottleNeckModel;
+
+void get_arrival_time(int current_framesamples, /* samples */
+ int packet_size, /* bytes */
+ int bottleneck, /* excluding headers; bits/s */
+ BottleNeckModel *BN_data)
+{
+ const int HeaderSize = 35;
+ int HeaderRate;
+
+ HeaderRate = HeaderSize * 8 * FS / current_framesamples; /* bits/s */
+
+ /* everything in samples */
+ BN_data->sample_count = BN_data->sample_count + current_framesamples;
+
+ BN_data->arrival_time += ((packet_size + HeaderSize) * 8 * FS) / (bottleneck + HeaderRate);
+
+ if (BN_data->arrival_time < BN_data->sample_count)
+ BN_data->arrival_time = BN_data->sample_count;
+
+ BN_data->rtp_number++;
+}
+
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+*/
+int main(int argc, char* argv[]){
+
+ /* Parameters */
+ FILE *pInFile, *pOutFile, *pChcFile;
+ WebRtc_Word8 inFile[40];
+ WebRtc_Word8 outFile[40];
+ WebRtc_Word8 chcFile[40];
+ WebRtc_Word8 codec[10];
+ WebRtc_Word16 bitrt, spType, size;
+ WebRtc_UWord16 frameLen;
+ WebRtc_Word16 sigOut[1000], sigIn[1000];
+ WebRtc_UWord16 bitStream[500]; /* double to 32 kbps for 60 ms */
+
+ WebRtc_Word16 chc, ok;
+ int noOfCalls, cdlen;
+ WebRtc_Word16 noOfLostFrames;
+ int err, errtype;
+
+ BottleNeckModel BN_data;
+
+ int totalbits =0;
+ int totalsmpls =0;
+
+ /*End Parameters*/
+
+
+ if ((argc==6)||(argc==7) ){
+
+ strcpy(codec,argv[5]);
+
+ if(argc==7){
+ if (!_stricmp("isac",codec)){
+ bitrt = atoi(argv[6]);
+ if ( (bitrt<10000)&&(bitrt>32000)){
+ printf("Error: Supported bit rate in the range 10000-32000 bps!\n");
+ exit(-1);
+ }
+
+ }else{
+ printf("Error: Codec not recognized. Check spelling!\n");
+ exit(-1);
+ }
+
+ } else {
+ printf("Error: Codec not recognized. Check spelling!\n");
+ exit(-1);
+ }
+ } else {
+ printf("Error: Wrong number of input parameter!\n\n");
+ exit(-1);
+ }
+
+ frameLen = atoi(argv[4]);
+ strcpy(chcFile,argv[3]);
+ strcpy(outFile,argv[2]);
+ strcpy(inFile,argv[1]);
+
+ /* Open file streams */
+ if( (pInFile = fopen(inFile,"rb")) == NULL ) {
+ printf( "Error: Did not find input file!\n" );
+ exit(-1);
+ }
+ strcat(outFile,"_");
+ strcat(outFile, argv[4]);
+ strcat(outFile,"_");
+ strcat(outFile, codec);
+
+ if (argc==7){
+ strcat(outFile,"_");
+ strcat(outFile, argv[6]);
+ }
+ if (_stricmp("none", chcFile)){
+ strcat(outFile,"_");
+ strcat(outFile, "plc");
+ }
+
+ strcat(outFile, ".otp");
+
+ if (_stricmp("none", chcFile)){
+ if( (pChcFile = fopen(chcFile,"rb")) == NULL ) {
+ printf( "Error: Did not find channel file!\n" );
+ exit(-1);
+ }
+ }
+ /******************************************************************/
+ if (!_stricmp("isac", codec)){ /* ISAC */
+ if ((frameLen!=480)&&(frameLen!=960)) {
+ printf("Error: ISAC only supports 480 and 960 samples per frame (not %d)\n", frameLen);
+ exit(-1);
+ }
+ if( (pOutFile = fopen(outFile,"wb")) == NULL ) {
+ printf( "Could not open output file!\n" );
+ exit(-1);
+ }
+ ok=WebRtcIsacfix_Create(&ISACfix_inst);
+ if (ok!=0) {
+ printf("Couldn't allocate memory for iSAC fix instance\n");
+ exit(-1);
+ }
+
+ BN_data.arrival_time = 0;
+ BN_data.sample_count = 0;
+ BN_data.rtp_number = 0;
+
+ WebRtcIsacfix_EncoderInit(ISACfix_inst,1);
+ WebRtcIsacfix_DecoderInit(ISACfix_inst);
+ err = WebRtcIsacfix_Control(ISACfix_inst, bitrt, (frameLen>>4));
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ exit(EXIT_FAILURE);
+ }
+ /* loop over frame */
+ while (fread(sigIn,sizeof(WebRtc_Word16),frameLen,pInFile) == frameLen) {
+
+ noOfCalls=0;
+ cdlen=0;
+ while (cdlen<=0) {
+ cdlen=WebRtcIsacfix_Encode(ISACfix_inst,&sigIn[noOfCalls*160],(WebRtc_Word16*)bitStream);
+ if(cdlen==-1){
+ errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
+ printf("\n\nError in encoder: %d.\n\n", errtype);
+ exit(-1);
+ }
+ noOfCalls++;
+ }
+
+
+ if(_stricmp("none", chcFile)){
+ if (fread(&chc,sizeof(WebRtc_Word16),1,pChcFile)!=1) /* packet may be lost */
+ break;
+ } else {
+ chc = 1; /* packets never lost */
+ }
+
+ /* simulate packet handling through NetEq and the modem */
+ get_arrival_time(frameLen, cdlen, bitrt, &BN_data);
+
+ if (chc){ /* decode */
+
+ err = WebRtcIsacfix_UpdateBwEstimate1(ISACfix_inst,
+ bitStream,
+ cdlen,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ exit(EXIT_FAILURE);
+ }
+ size = WebRtcIsacfix_Decode(ISACfix_inst, bitStream, cdlen, sigOut, &spType);
+ if(size<=0){
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ exit(-1);
+ }
+ } else { /* PLC */
+ if (frameLen == 480){
+ noOfLostFrames = 1;
+ } else{
+ noOfLostFrames = 2;
+ }
+ size = WebRtcIsacfix_DecodePlc(ISACfix_inst, sigOut, noOfLostFrames );
+ if(size<=0){
+ errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ exit(-1);
+ }
+ }
+
+ /* Write decoded speech to file */
+ fwrite(sigOut,sizeof(short),size,pOutFile);
+
+ totalbits += 8 * cdlen;
+ totalsmpls += size;
+
+ }
+ /******************************************************************/
+ }
+
+// printf("\n\ntotal bits = %d bits", totalbits);
+ printf("\nmeasured average bitrate = %0.3f kbits/s", (double)totalbits * 16 / totalsmpls);
+ printf("\n");
+
+
+ fclose(pInFile);
+ fclose(pOutFile);
+ if (_stricmp("none", chcFile)){
+ fclose(pChcFile);
+ }
+
+ if (!_stricmp("isac", codec)){
+ WebRtcIsacfix_Free(ISACfix_inst);
+ }
+
+ return 0;
+
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/ChannelFiles.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/ChannelFiles.txt
new file mode 100644
index 0000000..05f7410
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/ChannelFiles.txt
@@ -0,0 +1,3 @@
+bottlenecks.txt
+lowrates.txt
+tworates.txt
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFiles.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFiles.txt
new file mode 100644
index 0000000..f26b7af
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFiles.txt
@@ -0,0 +1,31 @@
+DTMF_16kHz_long.pcm
+DTMF_16kHz_short.pcm
+F00.INP
+F01.INP
+F02.INP
+F03.INP
+F04.INP
+F05.INP
+F06.INP
+longtest.pcm
+ltest_speech_clean.pcm
+ltest_music.pcm
+ltest_speech_noisy.pcm
+misc2.pcm
+purenb.pcm
+sawsweep_380_60.pcm
+sinesweep.pcm
+sinesweep_half.pcm
+speechmusic.pcm
+speechmusic_nb.pcm
+speechoffice0dB.pcm
+speech_and_misc_NB.pcm
+speech_and_misc_WB.pcm
+testM4.pcm
+testM4D_rev.pcm
+testM4D.pcm
+testfile.pcm
+tone_cisco.pcm
+tone_cisco_long.pcm
+wb_contspeech.pcm
+wb_speech_office25db.pcm
\ No newline at end of file
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFilesFew.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFilesFew.txt
new file mode 100644
index 0000000..08bbde3
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/InputFilesFew.txt
@@ -0,0 +1,6 @@
+DTMF_16kHz_short.pcm
+ltest_speech_noisy.pcm
+misc2.pcm
+sinesweep.pcm
+speechmusic.pcm
+tone_cisco.pcm
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/ListOfTestCases.xls b/src/modules/audio_coding/codecs/isac/fix/test/QA/ListOfTestCases.xls
new file mode 100644
index 0000000..f0889ef
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/ListOfTestCases.xls
Binary files differ
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSAC.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSAC.txt
new file mode 100644
index 0000000..96b87c0
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSAC.txt
@@ -0,0 +1,481 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+diff ../dataqa350/i30_1DTMF_16kHz_long.pcm ../dataqa351/i30_1DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_1DTMF_16kHz_long.pcm ../dataqa351/i60_1DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_2DTMF_16kHz_long.pcm ../dataqa351/i30_2DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_2DTMF_16kHz_long.pcm ../dataqa351/i60_2DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_3DTMF_16kHz_long.pcm ../dataqa351/i30_3DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_3DTMF_16kHz_long.pcm ../dataqa351/i60_3DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_4DTMF_16kHz_long.pcm ../dataqa351/i30_4DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_4DTMF_16kHz_long.pcm ../dataqa351/i60_4DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_5DTMF_16kHz_long.pcm ../dataqa351/i30_5DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_5DTMF_16kHz_long.pcm ../dataqa351/i60_5DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_6DTMF_16kHz_long.pcm ../dataqa351/i30_6DTMF_16kHz_long.pcm
+diff ../dataqa350/i60_6DTMF_16kHz_long.pcm ../dataqa351/i60_6DTMF_16kHz_long.pcm
+diff ../dataqa350/a1DTMF_16kHz_long.pcm ../dataqa351/a1DTMF_16kHz_long.pcm
+diff ../dataqa350/a2DTMF_16kHz_long.pcm ../dataqa351/a2DTMF_16kHz_long.pcm
+diff ../dataqa350/a3DTMF_16kHz_long.pcm ../dataqa351/a3DTMF_16kHz_long.pcm
+diff ../dataqa350/i30_7DTMF_16kHz_short.pcm ../dataqa351/i30_7DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_7DTMF_16kHz_short.pcm ../dataqa351/i60_7DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_8DTMF_16kHz_short.pcm ../dataqa351/i30_8DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_8DTMF_16kHz_short.pcm ../dataqa351/i60_8DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_9DTMF_16kHz_short.pcm ../dataqa351/i30_9DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_9DTMF_16kHz_short.pcm ../dataqa351/i60_9DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_10DTMF_16kHz_short.pcm ../dataqa351/i30_10DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_10DTMF_16kHz_short.pcm ../dataqa351/i60_10DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_11DTMF_16kHz_short.pcm ../dataqa351/i30_11DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_11DTMF_16kHz_short.pcm ../dataqa351/i60_11DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_12DTMF_16kHz_short.pcm ../dataqa351/i30_12DTMF_16kHz_short.pcm
+diff ../dataqa350/i60_12DTMF_16kHz_short.pcm ../dataqa351/i60_12DTMF_16kHz_short.pcm
+diff ../dataqa350/a4DTMF_16kHz_short.pcm ../dataqa351/a4DTMF_16kHz_short.pcm
+diff ../dataqa350/a5DTMF_16kHz_short.pcm ../dataqa351/a5DTMF_16kHz_short.pcm
+diff ../dataqa350/a6DTMF_16kHz_short.pcm ../dataqa351/a6DTMF_16kHz_short.pcm
+diff ../dataqa350/i30_13F00.INP ../dataqa350/i30_13F00.INP
+diff ../dataqa350/i60_13F00.INP ../dataqa350/i60_13F00.INP
+diff ../dataqa350/i30_14F00.INP ../dataqa350/i30_14F00.INP
+diff ../dataqa350/i60_14F00.INP ../dataqa350/i60_14F00.INP
+diff ../dataqa350/i30_15F00.INP ../dataqa350/i30_15F00.INP
+diff ../dataqa350/i60_15F00.INP ../dataqa350/i60_15F00.INP
+diff ../dataqa350/i30_16F00.INP ../dataqa350/i30_16F00.INP
+diff ../dataqa350/i60_16F00.INP ../dataqa350/i60_16F00.INP
+diff ../dataqa350/i30_17F00.INP ../dataqa350/i30_17F00.INP
+diff ../dataqa350/i60_17F00.INP ../dataqa350/i60_17F00.INP
+diff ../dataqa350/i30_18F00.INP ../dataqa350/i30_18F00.INP
+diff ../dataqa350/i60_18F00.INP ../dataqa350/i60_18F00.INP
+diff ../dataqa350/a7F00.INP ../dataqa350/a7F00.INP
+diff ../dataqa350/a8F00.INP ../dataqa350/a8F00.INP
+diff ../dataqa350/a9F00.INP ../dataqa350/a9F00.INP
+diff ../dataqa350/i30_19F01.INP ../dataqa350/i30_19F01.INP
+diff ../dataqa350/i60_19F01.INP ../dataqa350/i60_19F01.INP
+diff ../dataqa350/i30_20F01.INP ../dataqa350/i30_20F01.INP
+diff ../dataqa350/i60_20F01.INP ../dataqa350/i60_20F01.INP
+diff ../dataqa350/i30_21F01.INP ../dataqa350/i30_21F01.INP
+diff ../dataqa350/i60_21F01.INP ../dataqa350/i60_21F01.INP
+diff ../dataqa350/i30_22F01.INP ../dataqa350/i30_22F01.INP
+diff ../dataqa350/i60_22F01.INP ../dataqa350/i60_22F01.INP
+diff ../dataqa350/i30_23F01.INP ../dataqa350/i30_23F01.INP
+diff ../dataqa350/i60_23F01.INP ../dataqa350/i60_23F01.INP
+diff ../dataqa350/i30_24F01.INP ../dataqa350/i30_24F01.INP
+diff ../dataqa350/i60_24F01.INP ../dataqa350/i60_24F01.INP
+diff ../dataqa350/a10F01.INP ../dataqa350/a10F01.INP
+diff ../dataqa350/a11F01.INP ../dataqa350/a11F01.INP
+diff ../dataqa350/a12F01.INP ../dataqa350/a12F01.INP
+diff ../dataqa350/i30_25F02.INP ../dataqa350/i30_25F02.INP
+diff ../dataqa350/i60_25F02.INP ../dataqa350/i60_25F02.INP
+diff ../dataqa350/i30_26F02.INP ../dataqa350/i30_26F02.INP
+diff ../dataqa350/i60_26F02.INP ../dataqa350/i60_26F02.INP
+diff ../dataqa350/i30_27F02.INP ../dataqa350/i30_27F02.INP
+diff ../dataqa350/i60_27F02.INP ../dataqa350/i60_27F02.INP
+diff ../dataqa350/i30_28F02.INP ../dataqa350/i30_28F02.INP
+diff ../dataqa350/i60_28F02.INP ../dataqa350/i60_28F02.INP
+diff ../dataqa350/i30_29F02.INP ../dataqa350/i30_29F02.INP
+diff ../dataqa350/i60_29F02.INP ../dataqa350/i60_29F02.INP
+diff ../dataqa350/i30_30F02.INP ../dataqa350/i30_30F02.INP
+diff ../dataqa350/i60_30F02.INP ../dataqa350/i60_30F02.INP
+diff ../dataqa350/a13F02.INP ../dataqa350/a13F02.INP
+diff ../dataqa350/a14F02.INP ../dataqa350/a14F02.INP
+diff ../dataqa350/a15F02.INP ../dataqa350/a15F02.INP
+diff ../dataqa350/i30_31F03.INP ../dataqa350/i30_31F03.INP
+diff ../dataqa350/i60_31F03.INP ../dataqa350/i60_31F03.INP
+diff ../dataqa350/i30_32F03.INP ../dataqa350/i30_32F03.INP
+diff ../dataqa350/i60_32F03.INP ../dataqa350/i60_32F03.INP
+diff ../dataqa350/i30_33F03.INP ../dataqa350/i30_33F03.INP
+diff ../dataqa350/i60_33F03.INP ../dataqa350/i60_33F03.INP
+diff ../dataqa350/i30_34F03.INP ../dataqa350/i30_34F03.INP
+diff ../dataqa350/i60_34F03.INP ../dataqa350/i60_34F03.INP
+diff ../dataqa350/i30_35F03.INP ../dataqa350/i30_35F03.INP
+diff ../dataqa350/i60_35F03.INP ../dataqa350/i60_35F03.INP
+diff ../dataqa350/i30_36F03.INP ../dataqa350/i30_36F03.INP
+diff ../dataqa350/i60_36F03.INP ../dataqa350/i60_36F03.INP
+diff ../dataqa350/a16F03.INP ../dataqa350/a16F03.INP
+diff ../dataqa350/a17F03.INP ../dataqa350/a17F03.INP
+diff ../dataqa350/a18F03.INP ../dataqa350/a18F03.INP
+diff ../dataqa350/i30_37F04.INP ../dataqa350/i30_37F04.INP
+diff ../dataqa350/i60_37F04.INP ../dataqa350/i60_37F04.INP
+diff ../dataqa350/i30_38F04.INP ../dataqa350/i30_38F04.INP
+diff ../dataqa350/i60_38F04.INP ../dataqa350/i60_38F04.INP
+diff ../dataqa350/i30_39F04.INP ../dataqa350/i30_39F04.INP
+diff ../dataqa350/i60_39F04.INP ../dataqa350/i60_39F04.INP
+diff ../dataqa350/i30_40F04.INP ../dataqa350/i30_40F04.INP
+diff ../dataqa350/i60_40F04.INP ../dataqa350/i60_40F04.INP
+diff ../dataqa350/i30_41F04.INP ../dataqa350/i30_41F04.INP
+diff ../dataqa350/i60_41F04.INP ../dataqa350/i60_41F04.INP
+diff ../dataqa350/i30_42F04.INP ../dataqa350/i30_42F04.INP
+diff ../dataqa350/i60_42F04.INP ../dataqa350/i60_42F04.INP
+diff ../dataqa350/a19F04.INP ../dataqa350/a19F04.INP
+diff ../dataqa350/a20F04.INP ../dataqa350/a20F04.INP
+diff ../dataqa350/a21F04.INP ../dataqa350/a21F04.INP
+diff ../dataqa350/i30_43F05.INP ../dataqa350/i30_43F05.INP
+diff ../dataqa350/i60_43F05.INP ../dataqa350/i60_43F05.INP
+diff ../dataqa350/i30_44F05.INP ../dataqa350/i30_44F05.INP
+diff ../dataqa350/i60_44F05.INP ../dataqa350/i60_44F05.INP
+diff ../dataqa350/i30_45F05.INP ../dataqa350/i30_45F05.INP
+diff ../dataqa350/i60_45F05.INP ../dataqa350/i60_45F05.INP
+diff ../dataqa350/i30_46F05.INP ../dataqa350/i30_46F05.INP
+diff ../dataqa350/i60_46F05.INP ../dataqa350/i60_46F05.INP
+diff ../dataqa350/i30_47F05.INP ../dataqa350/i30_47F05.INP
+diff ../dataqa350/i60_47F05.INP ../dataqa350/i60_47F05.INP
+diff ../dataqa350/i30_48F05.INP ../dataqa350/i30_48F05.INP
+diff ../dataqa350/i60_48F05.INP ../dataqa350/i60_48F05.INP
+diff ../dataqa350/a22F05.INP ../dataqa350/a22F05.INP
+diff ../dataqa350/a23F05.INP ../dataqa350/a23F05.INP
+diff ../dataqa350/a24F05.INP ../dataqa350/a24F05.INP
+diff ../dataqa350/i30_49F06.INP ../dataqa350/i30_49F06.INP
+diff ../dataqa350/i60_49F06.INP ../dataqa350/i60_49F06.INP
+diff ../dataqa350/i30_50F06.INP ../dataqa350/i30_50F06.INP
+diff ../dataqa350/i60_50F06.INP ../dataqa350/i60_50F06.INP
+diff ../dataqa350/i30_51F06.INP ../dataqa350/i30_51F06.INP
+diff ../dataqa350/i60_51F06.INP ../dataqa350/i60_51F06.INP
+diff ../dataqa350/i30_52F06.INP ../dataqa350/i30_52F06.INP
+diff ../dataqa350/i60_52F06.INP ../dataqa350/i60_52F06.INP
+diff ../dataqa350/i30_53F06.INP ../dataqa350/i30_53F06.INP
+diff ../dataqa350/i60_53F06.INP ../dataqa350/i60_53F06.INP
+diff ../dataqa350/i30_54F06.INP ../dataqa350/i30_54F06.INP
+diff ../dataqa350/i60_54F06.INP ../dataqa350/i60_54F06.INP
+diff ../dataqa350/a25F06.INP ../dataqa350/a25F06.INP
+diff ../dataqa350/a26F06.INP ../dataqa350/a26F06.INP
+diff ../dataqa350/a27F06.INP ../dataqa350/a27F06.INP
+diff ../dataqa350/i30_55longtest.pcm ../dataqa351/i30_55longtest.pcm
+diff ../dataqa350/i60_55longtest.pcm ../dataqa351/i60_55longtest.pcm
+diff ../dataqa350/i30_56longtest.pcm ../dataqa351/i30_56longtest.pcm
+diff ../dataqa350/i60_56longtest.pcm ../dataqa351/i60_56longtest.pcm
+diff ../dataqa350/i30_57longtest.pcm ../dataqa351/i30_57longtest.pcm
+diff ../dataqa350/i60_57longtest.pcm ../dataqa351/i60_57longtest.pcm
+diff ../dataqa350/i30_58longtest.pcm ../dataqa351/i30_58longtest.pcm
+diff ../dataqa350/i60_58longtest.pcm ../dataqa351/i60_58longtest.pcm
+diff ../dataqa350/i30_59longtest.pcm ../dataqa351/i30_59longtest.pcm
+diff ../dataqa350/i60_59longtest.pcm ../dataqa351/i60_59longtest.pcm
+diff ../dataqa350/i30_60longtest.pcm ../dataqa351/i30_60longtest.pcm
+diff ../dataqa350/i60_60longtest.pcm ../dataqa351/i60_60longtest.pcm
+diff ../dataqa350/a28longtest.pcm ../dataqa351/a28longtest.pcm
+diff ../dataqa350/a29longtest.pcm ../dataqa351/a29longtest.pcm
+diff ../dataqa350/a30longtest.pcm ../dataqa351/a30longtest.pcm
+diff ../dataqa350/i30_61ltest_speech_clean.pcm ../dataqa351/i30_61ltest_speech_clean.pcm
+diff ../dataqa350/i60_61ltest_speech_clean.pcm ../dataqa351/i60_61ltest_speech_clean.pcm
+diff ../dataqa350/i30_62ltest_speech_clean.pcm ../dataqa351/i30_62ltest_speech_clean.pcm
+diff ../dataqa350/i60_62ltest_speech_clean.pcm ../dataqa351/i60_62ltest_speech_clean.pcm
+diff ../dataqa350/i30_63ltest_speech_clean.pcm ../dataqa351/i30_63ltest_speech_clean.pcm
+diff ../dataqa350/i60_63ltest_speech_clean.pcm ../dataqa351/i60_63ltest_speech_clean.pcm
+diff ../dataqa350/i30_64ltest_speech_clean.pcm ../dataqa351/i30_64ltest_speech_clean.pcm
+diff ../dataqa350/i60_64ltest_speech_clean.pcm ../dataqa351/i60_64ltest_speech_clean.pcm
+diff ../dataqa350/i30_65ltest_speech_clean.pcm ../dataqa351/i30_65ltest_speech_clean.pcm
+diff ../dataqa350/i60_65ltest_speech_clean.pcm ../dataqa351/i60_65ltest_speech_clean.pcm
+diff ../dataqa350/i30_66ltest_speech_clean.pcm ../dataqa351/i30_66ltest_speech_clean.pcm
+diff ../dataqa350/i60_66ltest_speech_clean.pcm ../dataqa351/i60_66ltest_speech_clean.pcm
+diff ../dataqa350/a31ltest_speech_clean.pcm ../dataqa351/a31ltest_speech_clean.pcm
+diff ../dataqa350/a32ltest_speech_clean.pcm ../dataqa351/a32ltest_speech_clean.pcm
+diff ../dataqa350/a33ltest_speech_clean.pcm ../dataqa351/a33ltest_speech_clean.pcm
+diff ../dataqa350/i30_67ltest_music.pcm ../dataqa351/i30_67ltest_music.pcm
+diff ../dataqa350/i60_67ltest_music.pcm ../dataqa351/i60_67ltest_music.pcm
+diff ../dataqa350/i30_68ltest_music.pcm ../dataqa351/i30_68ltest_music.pcm
+diff ../dataqa350/i60_68ltest_music.pcm ../dataqa351/i60_68ltest_music.pcm
+diff ../dataqa350/i30_69ltest_music.pcm ../dataqa351/i30_69ltest_music.pcm
+diff ../dataqa350/i60_69ltest_music.pcm ../dataqa351/i60_69ltest_music.pcm
+diff ../dataqa350/i30_70ltest_music.pcm ../dataqa351/i30_70ltest_music.pcm
+diff ../dataqa350/i60_70ltest_music.pcm ../dataqa351/i60_70ltest_music.pcm
+diff ../dataqa350/i30_71ltest_music.pcm ../dataqa351/i30_71ltest_music.pcm
+diff ../dataqa350/i60_71ltest_music.pcm ../dataqa351/i60_71ltest_music.pcm
+diff ../dataqa350/i30_72ltest_music.pcm ../dataqa351/i30_72ltest_music.pcm
+diff ../dataqa350/i60_72ltest_music.pcm ../dataqa351/i60_72ltest_music.pcm
+diff ../dataqa350/a34ltest_music.pcm ../dataqa351/a34ltest_music.pcm
+diff ../dataqa350/a35ltest_music.pcm ../dataqa351/a35ltest_music.pcm
+diff ../dataqa350/a36ltest_music.pcm ../dataqa351/a36ltest_music.pcm
+diff ../dataqa350/i30_73ltest_speech_noisy.pcm ../dataqa351/i30_73ltest_speech_noisy.pcm
+diff ../dataqa350/i60_73ltest_speech_noisy.pcm ../dataqa351/i60_73ltest_speech_noisy.pcm
+diff ../dataqa350/i30_74ltest_speech_noisy.pcm ../dataqa351/i30_74ltest_speech_noisy.pcm
+diff ../dataqa350/i60_74ltest_speech_noisy.pcm ../dataqa351/i60_74ltest_speech_noisy.pcm
+diff ../dataqa350/i30_75ltest_speech_noisy.pcm ../dataqa351/i30_75ltest_speech_noisy.pcm
+diff ../dataqa350/i60_75ltest_speech_noisy.pcm ../dataqa351/i60_75ltest_speech_noisy.pcm
+diff ../dataqa350/i30_76ltest_speech_noisy.pcm ../dataqa351/i30_76ltest_speech_noisy.pcm
+diff ../dataqa350/i60_76ltest_speech_noisy.pcm ../dataqa351/i60_76ltest_speech_noisy.pcm
+diff ../dataqa350/i30_77ltest_speech_noisy.pcm ../dataqa351/i30_77ltest_speech_noisy.pcm
+diff ../dataqa350/i60_77ltest_speech_noisy.pcm ../dataqa351/i60_77ltest_speech_noisy.pcm
+diff ../dataqa350/i30_78ltest_speech_noisy.pcm ../dataqa351/i30_78ltest_speech_noisy.pcm
+diff ../dataqa350/i60_78ltest_speech_noisy.pcm ../dataqa351/i60_78ltest_speech_noisy.pcm
+diff ../dataqa350/a37ltest_speech_noisy.pcm ../dataqa351/a37ltest_speech_noisy.pcm
+diff ../dataqa350/a38ltest_speech_noisy.pcm ../dataqa351/a38ltest_speech_noisy.pcm
+diff ../dataqa350/a39ltest_speech_noisy.pcm ../dataqa351/a39ltest_speech_noisy.pcm
+diff ../dataqa350/i30_79misc2.pcm ../dataqa351/i30_79misc2.pcm
+diff ../dataqa350/i60_79misc2.pcm ../dataqa351/i60_79misc2.pcm
+diff ../dataqa350/i30_80misc2.pcm ../dataqa351/i30_80misc2.pcm
+diff ../dataqa350/i60_80misc2.pcm ../dataqa351/i60_80misc2.pcm
+diff ../dataqa350/i30_81misc2.pcm ../dataqa351/i30_81misc2.pcm
+diff ../dataqa350/i60_81misc2.pcm ../dataqa351/i60_81misc2.pcm
+diff ../dataqa350/i30_82misc2.pcm ../dataqa351/i30_82misc2.pcm
+diff ../dataqa350/i60_82misc2.pcm ../dataqa351/i60_82misc2.pcm
+diff ../dataqa350/i30_83misc2.pcm ../dataqa351/i30_83misc2.pcm
+diff ../dataqa350/i60_83misc2.pcm ../dataqa351/i60_83misc2.pcm
+diff ../dataqa350/i30_84misc2.pcm ../dataqa351/i30_84misc2.pcm
+diff ../dataqa350/i60_84misc2.pcm ../dataqa351/i60_84misc2.pcm
+diff ../dataqa350/a40misc2.pcm ../dataqa351/a40misc2.pcm
+diff ../dataqa350/a41misc2.pcm ../dataqa351/a41misc2.pcm
+diff ../dataqa350/a42misc2.pcm ../dataqa351/a42misc2.pcm
+diff ../dataqa350/i30_85purenb.pcm ../dataqa351/i30_85purenb.pcm
+diff ../dataqa350/i60_85purenb.pcm ../dataqa351/i60_85purenb.pcm
+diff ../dataqa350/i30_86purenb.pcm ../dataqa351/i30_86purenb.pcm
+diff ../dataqa350/i60_86purenb.pcm ../dataqa351/i60_86purenb.pcm
+diff ../dataqa350/i30_87purenb.pcm ../dataqa351/i30_87purenb.pcm
+diff ../dataqa350/i60_87purenb.pcm ../dataqa351/i60_87purenb.pcm
+diff ../dataqa350/i30_88purenb.pcm ../dataqa351/i30_88purenb.pcm
+diff ../dataqa350/i60_88purenb.pcm ../dataqa351/i60_88purenb.pcm
+diff ../dataqa350/i30_89purenb.pcm ../dataqa351/i30_89purenb.pcm
+diff ../dataqa350/i60_89purenb.pcm ../dataqa351/i60_89purenb.pcm
+diff ../dataqa350/i30_90purenb.pcm ../dataqa351/i30_90purenb.pcm
+diff ../dataqa350/i60_90purenb.pcm ../dataqa351/i60_90purenb.pcm
+diff ../dataqa350/a43purenb.pcm ../dataqa351/a43purenb.pcm
+diff ../dataqa350/a44purenb.pcm ../dataqa351/a44purenb.pcm
+diff ../dataqa350/a45purenb.pcm ../dataqa351/a45purenb.pcm
+diff ../dataqa350/i30_91sawsweep_380_60.pcm ../dataqa351/i30_91sawsweep_380_60.pcm
+diff ../dataqa350/i60_91sawsweep_380_60.pcm ../dataqa351/i60_91sawsweep_380_60.pcm
+diff ../dataqa350/i30_92sawsweep_380_60.pcm ../dataqa351/i30_92sawsweep_380_60.pcm
+diff ../dataqa350/i60_92sawsweep_380_60.pcm ../dataqa351/i60_92sawsweep_380_60.pcm
+diff ../dataqa350/i30_93sawsweep_380_60.pcm ../dataqa351/i30_93sawsweep_380_60.pcm
+diff ../dataqa350/i60_93sawsweep_380_60.pcm ../dataqa351/i60_93sawsweep_380_60.pcm
+diff ../dataqa350/i30_94sawsweep_380_60.pcm ../dataqa351/i30_94sawsweep_380_60.pcm
+diff ../dataqa350/i60_94sawsweep_380_60.pcm ../dataqa351/i60_94sawsweep_380_60.pcm
+diff ../dataqa350/i30_95sawsweep_380_60.pcm ../dataqa351/i30_95sawsweep_380_60.pcm
+diff ../dataqa350/i60_95sawsweep_380_60.pcm ../dataqa351/i60_95sawsweep_380_60.pcm
+diff ../dataqa350/i30_96sawsweep_380_60.pcm ../dataqa351/i30_96sawsweep_380_60.pcm
+diff ../dataqa350/i60_96sawsweep_380_60.pcm ../dataqa351/i60_96sawsweep_380_60.pcm
+diff ../dataqa350/a46sawsweep_380_60.pcm ../dataqa351/a46sawsweep_380_60.pcm
+diff ../dataqa350/a47sawsweep_380_60.pcm ../dataqa351/a47sawsweep_380_60.pcm
+diff ../dataqa350/a48sawsweep_380_60.pcm ../dataqa351/a48sawsweep_380_60.pcm
+diff ../dataqa350/i30_97sinesweep.pcm ../dataqa351/i30_97sinesweep.pcm
+diff ../dataqa350/i60_97sinesweep.pcm ../dataqa351/i60_97sinesweep.pcm
+diff ../dataqa350/i30_98sinesweep.pcm ../dataqa351/i30_98sinesweep.pcm
+diff ../dataqa350/i60_98sinesweep.pcm ../dataqa351/i60_98sinesweep.pcm
+diff ../dataqa350/i30_99sinesweep.pcm ../dataqa351/i30_99sinesweep.pcm
+diff ../dataqa350/i60_99sinesweep.pcm ../dataqa351/i60_99sinesweep.pcm
+diff ../dataqa350/i30_100sinesweep.pcm ../dataqa351/i30_100sinesweep.pcm
+diff ../dataqa350/i60_100sinesweep.pcm ../dataqa351/i60_100sinesweep.pcm
+diff ../dataqa350/i30_101sinesweep.pcm ../dataqa351/i30_101sinesweep.pcm
+diff ../dataqa350/i60_101sinesweep.pcm ../dataqa351/i60_101sinesweep.pcm
+diff ../dataqa350/i30_102sinesweep.pcm ../dataqa351/i30_102sinesweep.pcm
+diff ../dataqa350/i60_102sinesweep.pcm ../dataqa351/i60_102sinesweep.pcm
+diff ../dataqa350/a49sinesweep.pcm ../dataqa351/a49sinesweep.pcm
+diff ../dataqa350/a50sinesweep.pcm ../dataqa351/a50sinesweep.pcm
+diff ../dataqa350/a51sinesweep.pcm ../dataqa351/a51sinesweep.pcm
+diff ../dataqa350/i30_103sinesweep_half.pcm ../dataqa351/i30_103sinesweep_half.pcm
+diff ../dataqa350/i60_103sinesweep_half.pcm ../dataqa351/i60_103sinesweep_half.pcm
+diff ../dataqa350/i30_104sinesweep_half.pcm ../dataqa351/i30_104sinesweep_half.pcm
+diff ../dataqa350/i60_104sinesweep_half.pcm ../dataqa351/i60_104sinesweep_half.pcm
+diff ../dataqa350/i30_105sinesweep_half.pcm ../dataqa351/i30_105sinesweep_half.pcm
+diff ../dataqa350/i60_105sinesweep_half.pcm ../dataqa351/i60_105sinesweep_half.pcm
+diff ../dataqa350/i30_106sinesweep_half.pcm ../dataqa351/i30_106sinesweep_half.pcm
+diff ../dataqa350/i60_106sinesweep_half.pcm ../dataqa351/i60_106sinesweep_half.pcm
+diff ../dataqa350/i30_107sinesweep_half.pcm ../dataqa351/i30_107sinesweep_half.pcm
+diff ../dataqa350/i60_107sinesweep_half.pcm ../dataqa351/i60_107sinesweep_half.pcm
+diff ../dataqa350/i30_108sinesweep_half.pcm ../dataqa351/i30_108sinesweep_half.pcm
+diff ../dataqa350/i60_108sinesweep_half.pcm ../dataqa351/i60_108sinesweep_half.pcm
+diff ../dataqa350/a52sinesweep_half.pcm ../dataqa351/a52sinesweep_half.pcm
+diff ../dataqa350/a53sinesweep_half.pcm ../dataqa351/a53sinesweep_half.pcm
+diff ../dataqa350/a54sinesweep_half.pcm ../dataqa351/a54sinesweep_half.pcm
+diff ../dataqa350/i30_109speechmusic.pcm ../dataqa351/i30_109speechmusic.pcm
+diff ../dataqa350/i60_109speechmusic.pcm ../dataqa351/i60_109speechmusic.pcm
+diff ../dataqa350/i30_110speechmusic.pcm ../dataqa351/i30_110speechmusic.pcm
+diff ../dataqa350/i60_110speechmusic.pcm ../dataqa351/i60_110speechmusic.pcm
+diff ../dataqa350/i30_111speechmusic.pcm ../dataqa351/i30_111speechmusic.pcm
+diff ../dataqa350/i60_111speechmusic.pcm ../dataqa351/i60_111speechmusic.pcm
+diff ../dataqa350/i30_112speechmusic.pcm ../dataqa351/i30_112speechmusic.pcm
+diff ../dataqa350/i60_112speechmusic.pcm ../dataqa351/i60_112speechmusic.pcm
+diff ../dataqa350/i30_113speechmusic.pcm ../dataqa351/i30_113speechmusic.pcm
+diff ../dataqa350/i60_113speechmusic.pcm ../dataqa351/i60_113speechmusic.pcm
+diff ../dataqa350/i30_114speechmusic.pcm ../dataqa351/i30_114speechmusic.pcm
+diff ../dataqa350/i60_114speechmusic.pcm ../dataqa351/i60_114speechmusic.pcm
+diff ../dataqa350/a55speechmusic.pcm ../dataqa351/a55speechmusic.pcm
+diff ../dataqa350/a56speechmusic.pcm ../dataqa351/a56speechmusic.pcm
+diff ../dataqa350/a57speechmusic.pcm ../dataqa351/a57speechmusic.pcm
+diff ../dataqa350/i30_115speechmusic_nb.pcm ../dataqa351/i30_115speechmusic_nb.pcm
+diff ../dataqa350/i60_115speechmusic_nb.pcm ../dataqa351/i60_115speechmusic_nb.pcm
+diff ../dataqa350/i30_116speechmusic_nb.pcm ../dataqa351/i30_116speechmusic_nb.pcm
+diff ../dataqa350/i60_116speechmusic_nb.pcm ../dataqa351/i60_116speechmusic_nb.pcm
+diff ../dataqa350/i30_117speechmusic_nb.pcm ../dataqa351/i30_117speechmusic_nb.pcm
+diff ../dataqa350/i60_117speechmusic_nb.pcm ../dataqa351/i60_117speechmusic_nb.pcm
+diff ../dataqa350/i30_118speechmusic_nb.pcm ../dataqa351/i30_118speechmusic_nb.pcm
+diff ../dataqa350/i60_118speechmusic_nb.pcm ../dataqa351/i60_118speechmusic_nb.pcm
+diff ../dataqa350/i30_119speechmusic_nb.pcm ../dataqa351/i30_119speechmusic_nb.pcm
+diff ../dataqa350/i60_119speechmusic_nb.pcm ../dataqa351/i60_119speechmusic_nb.pcm
+diff ../dataqa350/i30_120speechmusic_nb.pcm ../dataqa351/i30_120speechmusic_nb.pcm
+diff ../dataqa350/i60_120speechmusic_nb.pcm ../dataqa351/i60_120speechmusic_nb.pcm
+diff ../dataqa350/a58speechmusic_nb.pcm ../dataqa351/a58speechmusic_nb.pcm
+diff ../dataqa350/a59speechmusic_nb.pcm ../dataqa351/a59speechmusic_nb.pcm
+diff ../dataqa350/a60speechmusic_nb.pcm ../dataqa351/a60speechmusic_nb.pcm
+diff ../dataqa350/i30_121speechoffice0dB.pcm ../dataqa351/i30_121speechoffice0dB.pcm
+diff ../dataqa350/i60_121speechoffice0dB.pcm ../dataqa351/i60_121speechoffice0dB.pcm
+diff ../dataqa350/i30_122speechoffice0dB.pcm ../dataqa351/i30_122speechoffice0dB.pcm
+diff ../dataqa350/i60_122speechoffice0dB.pcm ../dataqa351/i60_122speechoffice0dB.pcm
+diff ../dataqa350/i30_123speechoffice0dB.pcm ../dataqa351/i30_123speechoffice0dB.pcm
+diff ../dataqa350/i60_123speechoffice0dB.pcm ../dataqa351/i60_123speechoffice0dB.pcm
+diff ../dataqa350/i30_124speechoffice0dB.pcm ../dataqa351/i30_124speechoffice0dB.pcm
+diff ../dataqa350/i60_124speechoffice0dB.pcm ../dataqa351/i60_124speechoffice0dB.pcm
+diff ../dataqa350/i30_125speechoffice0dB.pcm ../dataqa351/i30_125speechoffice0dB.pcm
+diff ../dataqa350/i60_125speechoffice0dB.pcm ../dataqa351/i60_125speechoffice0dB.pcm
+diff ../dataqa350/i30_126speechoffice0dB.pcm ../dataqa351/i30_126speechoffice0dB.pcm
+diff ../dataqa350/i60_126speechoffice0dB.pcm ../dataqa351/i60_126speechoffice0dB.pcm
+diff ../dataqa350/a61speechoffice0dB.pcm ../dataqa351/a61speechoffice0dB.pcm
+diff ../dataqa350/a62speechoffice0dB.pcm ../dataqa351/a62speechoffice0dB.pcm
+diff ../dataqa350/a63speechoffice0dB.pcm ../dataqa351/a63speechoffice0dB.pcm
+diff ../dataqa350/i30_127speech_and_misc_NB.pcm ../dataqa351/i30_127speech_and_misc_NB.pcm
+diff ../dataqa350/i60_127speech_and_misc_NB.pcm ../dataqa351/i60_127speech_and_misc_NB.pcm
+diff ../dataqa350/i30_128speech_and_misc_NB.pcm ../dataqa351/i30_128speech_and_misc_NB.pcm
+diff ../dataqa350/i60_128speech_and_misc_NB.pcm ../dataqa351/i60_128speech_and_misc_NB.pcm
+diff ../dataqa350/i30_129speech_and_misc_NB.pcm ../dataqa351/i30_129speech_and_misc_NB.pcm
+diff ../dataqa350/i60_129speech_and_misc_NB.pcm ../dataqa351/i60_129speech_and_misc_NB.pcm
+diff ../dataqa350/i30_130speech_and_misc_NB.pcm ../dataqa351/i30_130speech_and_misc_NB.pcm
+diff ../dataqa350/i60_130speech_and_misc_NB.pcm ../dataqa351/i60_130speech_and_misc_NB.pcm
+diff ../dataqa350/i30_131speech_and_misc_NB.pcm ../dataqa351/i30_131speech_and_misc_NB.pcm
+diff ../dataqa350/i60_131speech_and_misc_NB.pcm ../dataqa351/i60_131speech_and_misc_NB.pcm
+diff ../dataqa350/i30_132speech_and_misc_NB.pcm ../dataqa351/i30_132speech_and_misc_NB.pcm
+diff ../dataqa350/i60_132speech_and_misc_NB.pcm ../dataqa351/i60_132speech_and_misc_NB.pcm
+diff ../dataqa350/a64speech_and_misc_NB.pcm ../dataqa351/a64speech_and_misc_NB.pcm
+diff ../dataqa350/a65speech_and_misc_NB.pcm ../dataqa351/a65speech_and_misc_NB.pcm
+diff ../dataqa350/a66speech_and_misc_NB.pcm ../dataqa351/a66speech_and_misc_NB.pcm
+diff ../dataqa350/i30_133speech_and_misc_WB.pcm ../dataqa351/i30_133speech_and_misc_WB.pcm
+diff ../dataqa350/i60_133speech_and_misc_WB.pcm ../dataqa351/i60_133speech_and_misc_WB.pcm
+diff ../dataqa350/i30_134speech_and_misc_WB.pcm ../dataqa351/i30_134speech_and_misc_WB.pcm
+diff ../dataqa350/i60_134speech_and_misc_WB.pcm ../dataqa351/i60_134speech_and_misc_WB.pcm
+diff ../dataqa350/i30_135speech_and_misc_WB.pcm ../dataqa351/i30_135speech_and_misc_WB.pcm
+diff ../dataqa350/i60_135speech_and_misc_WB.pcm ../dataqa351/i60_135speech_and_misc_WB.pcm
+diff ../dataqa350/i30_136speech_and_misc_WB.pcm ../dataqa351/i30_136speech_and_misc_WB.pcm
+diff ../dataqa350/i60_136speech_and_misc_WB.pcm ../dataqa351/i60_136speech_and_misc_WB.pcm
+diff ../dataqa350/i30_137speech_and_misc_WB.pcm ../dataqa351/i30_137speech_and_misc_WB.pcm
+diff ../dataqa350/i60_137speech_and_misc_WB.pcm ../dataqa351/i60_137speech_and_misc_WB.pcm
+diff ../dataqa350/i30_138speech_and_misc_WB.pcm ../dataqa351/i30_138speech_and_misc_WB.pcm
+diff ../dataqa350/i60_138speech_and_misc_WB.pcm ../dataqa351/i60_138speech_and_misc_WB.pcm
+diff ../dataqa350/a67speech_and_misc_WB.pcm ../dataqa351/a67speech_and_misc_WB.pcm
+diff ../dataqa350/a68speech_and_misc_WB.pcm ../dataqa351/a68speech_and_misc_WB.pcm
+diff ../dataqa350/a69speech_and_misc_WB.pcm ../dataqa351/a69speech_and_misc_WB.pcm
+diff ../dataqa350/i30_139testM4.pcm ../dataqa351/i30_139testM4.pcm
+diff ../dataqa350/i60_139testM4.pcm ../dataqa351/i60_139testM4.pcm
+diff ../dataqa350/i30_140testM4.pcm ../dataqa351/i30_140testM4.pcm
+diff ../dataqa350/i60_140testM4.pcm ../dataqa351/i60_140testM4.pcm
+diff ../dataqa350/i30_141testM4.pcm ../dataqa351/i30_141testM4.pcm
+diff ../dataqa350/i60_141testM4.pcm ../dataqa351/i60_141testM4.pcm
+diff ../dataqa350/i30_142testM4.pcm ../dataqa351/i30_142testM4.pcm
+diff ../dataqa350/i60_142testM4.pcm ../dataqa351/i60_142testM4.pcm
+diff ../dataqa350/i30_143testM4.pcm ../dataqa351/i30_143testM4.pcm
+diff ../dataqa350/i60_143testM4.pcm ../dataqa351/i60_143testM4.pcm
+diff ../dataqa350/i30_144testM4.pcm ../dataqa351/i30_144testM4.pcm
+diff ../dataqa350/i60_144testM4.pcm ../dataqa351/i60_144testM4.pcm
+diff ../dataqa350/a70testM4.pcm ../dataqa351/a70testM4.pcm
+diff ../dataqa350/a71testM4.pcm ../dataqa351/a71testM4.pcm
+diff ../dataqa350/a72testM4.pcm ../dataqa351/a72testM4.pcm
+diff ../dataqa350/i30_145testM4D_rev.pcm ../dataqa351/i30_145testM4D_rev.pcm
+diff ../dataqa350/i60_145testM4D_rev.pcm ../dataqa351/i60_145testM4D_rev.pcm
+diff ../dataqa350/i30_146testM4D_rev.pcm ../dataqa351/i30_146testM4D_rev.pcm
+diff ../dataqa350/i60_146testM4D_rev.pcm ../dataqa351/i60_146testM4D_rev.pcm
+diff ../dataqa350/i30_147testM4D_rev.pcm ../dataqa351/i30_147testM4D_rev.pcm
+diff ../dataqa350/i60_147testM4D_rev.pcm ../dataqa351/i60_147testM4D_rev.pcm
+diff ../dataqa350/i30_148testM4D_rev.pcm ../dataqa351/i30_148testM4D_rev.pcm
+diff ../dataqa350/i60_148testM4D_rev.pcm ../dataqa351/i60_148testM4D_rev.pcm
+diff ../dataqa350/i30_149testM4D_rev.pcm ../dataqa351/i30_149testM4D_rev.pcm
+diff ../dataqa350/i60_149testM4D_rev.pcm ../dataqa351/i60_149testM4D_rev.pcm
+diff ../dataqa350/i30_150testM4D_rev.pcm ../dataqa351/i30_150testM4D_rev.pcm
+diff ../dataqa350/i60_150testM4D_rev.pcm ../dataqa351/i60_150testM4D_rev.pcm
+diff ../dataqa350/a73testM4D_rev.pcm ../dataqa351/a73testM4D_rev.pcm
+diff ../dataqa350/a74testM4D_rev.pcm ../dataqa351/a74testM4D_rev.pcm
+diff ../dataqa350/a75testM4D_rev.pcm ../dataqa351/a75testM4D_rev.pcm
+diff ../dataqa350/i30_151testM4D.pcm ../dataqa351/i30_151testM4D.pcm
+diff ../dataqa350/i60_151testM4D.pcm ../dataqa351/i60_151testM4D.pcm
+diff ../dataqa350/i30_152testM4D.pcm ../dataqa351/i30_152testM4D.pcm
+diff ../dataqa350/i60_152testM4D.pcm ../dataqa351/i60_152testM4D.pcm
+diff ../dataqa350/i30_153testM4D.pcm ../dataqa351/i30_153testM4D.pcm
+diff ../dataqa350/i60_153testM4D.pcm ../dataqa351/i60_153testM4D.pcm
+diff ../dataqa350/i30_154testM4D.pcm ../dataqa351/i30_154testM4D.pcm
+diff ../dataqa350/i60_154testM4D.pcm ../dataqa351/i60_154testM4D.pcm
+diff ../dataqa350/i30_155testM4D.pcm ../dataqa351/i30_155testM4D.pcm
+diff ../dataqa350/i60_155testM4D.pcm ../dataqa351/i60_155testM4D.pcm
+diff ../dataqa350/i30_156testM4D.pcm ../dataqa351/i30_156testM4D.pcm
+diff ../dataqa350/i60_156testM4D.pcm ../dataqa351/i60_156testM4D.pcm
+diff ../dataqa350/a76testM4D.pcm ../dataqa351/a76testM4D.pcm
+diff ../dataqa350/a77testM4D.pcm ../dataqa351/a77testM4D.pcm
+diff ../dataqa350/a78testM4D.pcm ../dataqa351/a78testM4D.pcm
+diff ../dataqa350/i30_157testfile.pcm ../dataqa351/i30_157testfile.pcm
+diff ../dataqa350/i60_157testfile.pcm ../dataqa351/i60_157testfile.pcm
+diff ../dataqa350/i30_158testfile.pcm ../dataqa351/i30_158testfile.pcm
+diff ../dataqa350/i60_158testfile.pcm ../dataqa351/i60_158testfile.pcm
+diff ../dataqa350/i30_159testfile.pcm ../dataqa351/i30_159testfile.pcm
+diff ../dataqa350/i60_159testfile.pcm ../dataqa351/i60_159testfile.pcm
+diff ../dataqa350/i30_160testfile.pcm ../dataqa351/i30_160testfile.pcm
+diff ../dataqa350/i60_160testfile.pcm ../dataqa351/i60_160testfile.pcm
+diff ../dataqa350/i30_161testfile.pcm ../dataqa351/i30_161testfile.pcm
+diff ../dataqa350/i60_161testfile.pcm ../dataqa351/i60_161testfile.pcm
+diff ../dataqa350/i30_162testfile.pcm ../dataqa351/i30_162testfile.pcm
+diff ../dataqa350/i60_162testfile.pcm ../dataqa351/i60_162testfile.pcm
+diff ../dataqa350/a79testfile.pcm ../dataqa351/a79testfile.pcm
+diff ../dataqa350/a80testfile.pcm ../dataqa351/a80testfile.pcm
+diff ../dataqa350/a81testfile.pcm ../dataqa351/a81testfile.pcm
+diff ../dataqa350/i30_163tone_cisco.pcm ../dataqa351/i30_163tone_cisco.pcm
+diff ../dataqa350/i60_163tone_cisco.pcm ../dataqa351/i60_163tone_cisco.pcm
+diff ../dataqa350/i30_164tone_cisco.pcm ../dataqa351/i30_164tone_cisco.pcm
+diff ../dataqa350/i60_164tone_cisco.pcm ../dataqa351/i60_164tone_cisco.pcm
+diff ../dataqa350/i30_165tone_cisco.pcm ../dataqa351/i30_165tone_cisco.pcm
+diff ../dataqa350/i60_165tone_cisco.pcm ../dataqa351/i60_165tone_cisco.pcm
+diff ../dataqa350/i30_166tone_cisco.pcm ../dataqa351/i30_166tone_cisco.pcm
+diff ../dataqa350/i60_166tone_cisco.pcm ../dataqa351/i60_166tone_cisco.pcm
+diff ../dataqa350/i30_167tone_cisco.pcm ../dataqa351/i30_167tone_cisco.pcm
+diff ../dataqa350/i60_167tone_cisco.pcm ../dataqa351/i60_167tone_cisco.pcm
+diff ../dataqa350/i30_168tone_cisco.pcm ../dataqa351/i30_168tone_cisco.pcm
+diff ../dataqa350/i60_168tone_cisco.pcm ../dataqa351/i60_168tone_cisco.pcm
+diff ../dataqa350/a82tone_cisco.pcm ../dataqa351/a82tone_cisco.pcm
+diff ../dataqa350/a83tone_cisco.pcm ../dataqa351/a83tone_cisco.pcm
+diff ../dataqa350/a84tone_cisco.pcm ../dataqa351/a84tone_cisco.pcm
+diff ../dataqa350/i30_169tone_cisco_long.pcm ../dataqa351/i30_169tone_cisco_long.pcm
+diff ../dataqa350/i60_169tone_cisco_long.pcm ../dataqa351/i60_169tone_cisco_long.pcm
+diff ../dataqa350/i30_170tone_cisco_long.pcm ../dataqa351/i30_170tone_cisco_long.pcm
+diff ../dataqa350/i60_170tone_cisco_long.pcm ../dataqa351/i60_170tone_cisco_long.pcm
+diff ../dataqa350/i30_171tone_cisco_long.pcm ../dataqa351/i30_171tone_cisco_long.pcm
+diff ../dataqa350/i60_171tone_cisco_long.pcm ../dataqa351/i60_171tone_cisco_long.pcm
+diff ../dataqa350/i30_172tone_cisco_long.pcm ../dataqa351/i30_172tone_cisco_long.pcm
+diff ../dataqa350/i60_172tone_cisco_long.pcm ../dataqa351/i60_172tone_cisco_long.pcm
+diff ../dataqa350/i30_173tone_cisco_long.pcm ../dataqa351/i30_173tone_cisco_long.pcm
+diff ../dataqa350/i60_173tone_cisco_long.pcm ../dataqa351/i60_173tone_cisco_long.pcm
+diff ../dataqa350/i30_174tone_cisco_long.pcm ../dataqa351/i30_174tone_cisco_long.pcm
+diff ../dataqa350/i60_174tone_cisco_long.pcm ../dataqa351/i60_174tone_cisco_long.pcm
+diff ../dataqa350/a85tone_cisco_long.pcm ../dataqa351/a85tone_cisco_long.pcm
+diff ../dataqa350/a86tone_cisco_long.pcm ../dataqa351/a86tone_cisco_long.pcm
+diff ../dataqa350/a87tone_cisco_long.pcm ../dataqa351/a87tone_cisco_long.pcm
+diff ../dataqa350/i30_175wb_contspeech.pcm ../dataqa351/i30_175wb_contspeech.pcm
+diff ../dataqa350/i60_175wb_contspeech.pcm ../dataqa351/i60_175wb_contspeech.pcm
+diff ../dataqa350/i30_176wb_contspeech.pcm ../dataqa351/i30_176wb_contspeech.pcm
+diff ../dataqa350/i60_176wb_contspeech.pcm ../dataqa351/i60_176wb_contspeech.pcm
+diff ../dataqa350/i30_177wb_contspeech.pcm ../dataqa351/i30_177wb_contspeech.pcm
+diff ../dataqa350/i60_177wb_contspeech.pcm ../dataqa351/i60_177wb_contspeech.pcm
+diff ../dataqa350/i30_178wb_contspeech.pcm ../dataqa351/i30_178wb_contspeech.pcm
+diff ../dataqa350/i60_178wb_contspeech.pcm ../dataqa351/i60_178wb_contspeech.pcm
+diff ../dataqa350/i30_179wb_contspeech.pcm ../dataqa351/i30_179wb_contspeech.pcm
+diff ../dataqa350/i60_179wb_contspeech.pcm ../dataqa351/i60_179wb_contspeech.pcm
+diff ../dataqa350/i30_180wb_contspeech.pcm ../dataqa351/i30_180wb_contspeech.pcm
+diff ../dataqa350/i60_180wb_contspeech.pcm ../dataqa351/i60_180wb_contspeech.pcm
+diff ../dataqa350/a88wb_contspeech.pcm ../dataqa351/a88wb_contspeech.pcm
+diff ../dataqa350/a89wb_contspeech.pcm ../dataqa351/a89wb_contspeech.pcm
+diff ../dataqa350/a90wb_contspeech.pcm ../dataqa351/a90wb_contspeech.pcm
+diff ../dataqa350/i30_181wb_speech_office25db.pcm ../dataqa351/i30_181wb_speech_office25db.pcm
+diff ../dataqa350/i60_181wb_speech_office25db.pcm ../dataqa351/i60_181wb_speech_office25db.pcm
+diff ../dataqa350/i30_182wb_speech_office25db.pcm ../dataqa351/i30_182wb_speech_office25db.pcm
+diff ../dataqa350/i60_182wb_speech_office25db.pcm ../dataqa351/i60_182wb_speech_office25db.pcm
+diff ../dataqa350/i30_183wb_speech_office25db.pcm ../dataqa351/i30_183wb_speech_office25db.pcm
+diff ../dataqa350/i60_183wb_speech_office25db.pcm ../dataqa351/i60_183wb_speech_office25db.pcm
+diff ../dataqa350/i30_184wb_speech_office25db.pcm ../dataqa351/i30_184wb_speech_office25db.pcm
+diff ../dataqa350/i60_184wb_speech_office25db.pcm ../dataqa351/i60_184wb_speech_office25db.pcm
+diff ../dataqa350/i30_185wb_speech_office25db.pcm ../dataqa351/i30_185wb_speech_office25db.pcm
+diff ../dataqa350/i60_185wb_speech_office25db.pcm ../dataqa351/i60_185wb_speech_office25db.pcm
+diff ../dataqa350/i30_186wb_speech_office25db.pcm ../dataqa351/i30_186wb_speech_office25db.pcm
+diff ../dataqa350/i60_186wb_speech_office25db.pcm ../dataqa351/i60_186wb_speech_office25db.pcm
+diff ../dataqa350/a91wb_speech_office25db.pcm ../dataqa351/a91wb_speech_office25db.pcm
+diff ../dataqa350/a92wb_speech_office25db.pcm ../dataqa351/a92wb_speech_office25db.pcm
+diff ../dataqa350/a93wb_speech_office25db.pcm ../dataqa351/a93wb_speech_office25db.pcm
+diff ../dataqa350/a30_1DTMF_16kHz_short.pcm ../dataqa351/a30_1DTMF_16kHz_short.pcm
+diff ../dataqa350/a60_1DTMF_16kHz_short.pcm ../dataqa351/a60_1DTMF_16kHz_short.pcm
+diff ../dataqa350/a30_2ltest_speech_noisy.pcm ../dataqa351/a30_2ltest_speech_noisy.pcm
+diff ../dataqa350/a60_2ltest_speech_noisy.pcm ../dataqa351/a60_2ltest_speech_noisy.pcm
+diff ../dataqa350/a30_3misc2.pcm ../dataqa351/a30_3misc2.pcm
+diff ../dataqa350/a60_3misc2.pcm ../dataqa351/a60_3misc2.pcm
+diff ../dataqa350/a30_4sinesweep.pcm ../dataqa351/a30_4sinesweep.pcm
+diff ../dataqa350/a60_4sinesweep.pcm ../dataqa351/a60_4sinesweep.pcm
+diff ../dataqa350/a30_5speechmusic.pcm ../dataqa351/a30_5speechmusic.pcm
+diff ../dataqa350/a60_5speechmusic.pcm ../dataqa351/a60_5speechmusic.pcm
+diff ../dataqa350/a30_6tone_cisco.pcm ../dataqa351/a30_6tone_cisco.pcm
+diff ../dataqa350/a60_6tone_cisco.pcm ../dataqa351/a60_6tone_cisco.pcm
+diff ../dataqa350/a60_7tone_cisco.pcm ../dataqa351/a60_7tone_cisco.pcm
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSACPLC.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSACPLC.txt
new file mode 100644
index 0000000..9e3629b
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/diffiSACPLC.txt
@@ -0,0 +1,20 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logplc.txt
+echo "START PLC TEST" > $LOGFILE
+
+OUTDIR1=../dataqaplc_0
+OUTDIR2=../dataqaplc_1
+
+diff $OUTDIR1/outplc1.pcm $OUTDIR2/outplc1.pcm
+diff $OUTDIR1/outplc2.pcm $OUTDIR2/outplc2.pcm
+diff $OUTDIR1/outplc3.pcm $OUTDIR2/outplc3.pcm
+diff $OUTDIR1/outplc4.pcm $OUTDIR2/outplc4.pcm
+diff $OUTDIR1/outplc5.pcm $OUTDIR2/outplc5.pcm
+diff $OUTDIR1/outplc6.pcm $OUTDIR2/outplc6.pcm
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACLongtest.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACLongtest.txt
new file mode 100644
index 0000000..eeffc0c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACLongtest.txt
@@ -0,0 +1,61 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logNormal.txt
+echo "START ISAC TEST" > $LOGFILE
+echo >> $LOGFILE
+
+ISAC=../Release/kenny.exe
+ISACFIXFLOAT=../Release/testFixFloat.exe
+
+INFILES=$(cat InputFiles.txt)
+SUBSET=$(cat InputFilesFew.txt)
+CHANNELFILES=$(cat ChannelFiles.txt)
+CHANNELLIST=($(cat ChannelFiles.txt))
+INDIR=../data/orig
+OUTDIR=../dataqa
+mkdir -p $OUTDIR
+
+TARGETRATE=(10000 15000 20000 25000 30000 32000)
+#echo ${CHANNELFILES[1]}
+
+index1=0
+index2=0
+
+for file in $INFILES # loop over all input files
+ do
+
+ for rate in ${TARGETRATE[*]}
+ do
+ let "index1=index1+1"
+ $ISAC -I $rate -FL 30 $INDIR/"$file" $OUTDIR/i30_$index1"$file" >> $LOGFILE
+ $ISAC -I $rate -FL 60 $INDIR/"$file" $OUTDIR/i60_$index1"$file" >> $LOGFILE
+ done
+ for channel in $CHANNELFILES
+ do
+ let "index2=index2+1"
+ $ISAC $INDIR/$channel $INDIR/"$file" $OUTDIR/a$index2"$file" >> $LOGFILE
+ done
+
+done
+
+index1=0
+
+for file in $SUBSET # loop over the subset of input files
+ do
+ let "index1=index1+1"
+ $ISAC $INDIR/${CHANNELLIST[0]} -FL 30 -FIXED_FL $INDIR/"$file" $OUTDIR/a30_$index1"$file" >> $LOGFILE
+ $ISAC $INDIR/${CHANNELLIST[0]} -FL 60 -FIXED_FL $INDIR/"$file" $OUTDIR/a60_$index1"$file" >> $LOGFILE
+done
+
+let "index1=index1+1"
+ $ISAC $INDIR/${CHANNELLIST[0]} -INITRATE 25000 -FL 30 $INDIR/"$file" $OUTDIR/a60_$index1"$file" >> $LOGFILE
+
+# Run fault test
+
+#./runiSACfault.txt
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACNB.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACNB.txt
new file mode 100644
index 0000000..605595c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACNB.txt
@@ -0,0 +1,45 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logNB.txt
+echo "START NARROWBAND TEST" > $LOGFILE
+echo >> $LOGFILE
+
+ISAC=../Release/kenny.exe
+ISACFIXFLOAT=../Release/testFixFloat.exe
+
+INFILES=$(cat InputFiles.txt)
+SUBSET=$(cat InputFilesFew.txt)
+CHANNELFILES=$(cat ChannelFiles.txt)
+CHANNELLIST=($(cat ChannelFiles.txt))
+INDIR=../data/orig
+OUTDIR=../dataqaNB
+mkdir -p $OUTDIR
+
+TARGETRATE=(10000 15000 20000 25000 30000 32000)
+#echo ${CHANNELFILES[1]}
+
+index1=0
+index2=0
+
+# Narrowband Interfaces
+
+for file in $SUBSET # loop over all input files
+ do
+ for rate in ${TARGETRATE[*]}
+ do
+ let "index1=index1+1"
+ $ISAC $rate -FL 30 -NB 1 $INDIR/"$file" $OUTDIR/nb130_$index1"$file" >> $LOGFILE
+ $ISAC $rate -FL 60 -NB 1 $INDIR/"$file" $OUTDIR/nb160_$index1"$file" >> $LOGFILE
+ $ISAC $rate -FL 30 -NB 2 $INDIR/"$file" $OUTDIR/nb230_$index1"$file" >> $LOGFILE
+ $ISAC $rate -FL 60 -NB 2 $INDIR/"$file" $OUTDIR/nb260_$index1"$file" >> $LOGFILE
+ $ISAC $rate -FL 30 -NB 2 -PL 10 $INDIR/"$file" $OUTDIR/nb2plc30_$index1"$file" >> $LOGFILE
+ $ISAC $rate -FL 60 -NB 2 -PL 10 $INDIR/"$file" $OUTDIR/nb2plc60_$index1"$file" >> $LOGFILE
+ done
+
+done
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACPLC.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACPLC.txt
new file mode 100644
index 0000000..6bee6f7
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACPLC.txt
@@ -0,0 +1,23 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logplc.txt
+echo "START PLC TEST" > $LOGFILE
+
+ISAC=../Release/kenny.exe
+
+INDIR=../data/orig
+OUTDIR=../dataqaplc_0
+mkdir -p $OUTDIR
+
+$ISAC 12000 -PL 15 $INDIR/speechmusic.pcm $OUTDIR/outplc1.pcm
+$ISAC 20000 -PL 15 $INDIR/speechmusic.pcm $OUTDIR/outplc2.pcm
+$ISAC 32000 -PL 15 $INDIR/speechmusic.pcm $OUTDIR/outplc3.pcm
+$ISAC 12000 -PL 15 $INDIR/tone_cisco.pcm $OUTDIR/outplc4.pcm
+$ISAC 20000 -PL 15 $INDIR/tone_cisco.pcm $OUTDIR/outplc5.pcm
+$ISAC 32000 -PL 15 $INDIR/tone_cisco.pcm $OUTDIR/outplc6.pcm
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACRate.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACRate.txt
new file mode 100644
index 0000000..d8403e0
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACRate.txt
@@ -0,0 +1,23 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGG=loggRate.txt
+OUTDIR=../dataqaRate
+mkdir -p $OUTDIR
+
+../Release/kenny.exe 13000 -FIXED_FL -FL 30 -MAX 100 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_1.pcm > $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 30 -MAXRATE 32000 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_2.pcm >> $LOGG
+../Release/kenny.exe 13000 -FIXED_FL -FL 30 -MAX 100 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_3.pcm >> $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 30 -MAXRATE 32000 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_4.pcm >> $LOGG
+../Release/kenny.exe 13000 -FIXED_FL -FL 60 -MAX 100 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_5.pcm >> $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 60 -MAXRATE 32000 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_6.pcm >> $LOGG
+../Release/kenny.exe 13000 -INIT_RATE 32000 -FIXED_FL -FL 60 -MAX 100 ../data/orig/sawsweep_380_60.pcm $OUTDIR/out_napi_7.pcm >> $LOGG
+
+../Release/kenny.exe 13000 -FIXED_FL -FL 30 -MAX 100 ../data/orig/longspeech.pcm $OUTDIR/out_napi_11.pcm >> $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 30 -MAXRATE 32000 ../data/orig/longspeech.pcm $OUTDIR/out_napi_12.pcm >> $LOGG
+../Release/kenny.exe 13000 -FIXED_FL -FL 30 -MAX 100 ../data/orig/longspeech.pcm $OUTDIR/out_napi_13.pcm >> $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 30 -MAXRATE 32000 ../data/orig/longspeech.pcm $OUTDIR/out_napi_14.pcm >> $LOGG
+../Release/kenny.exe 13000 -FIXED_FL -FL 60 -MAX 100 ../data/orig/longspeech.pcm $OUTDIR/out_napi_15.pcm >> $LOGG
+../Release/kenny.exe ../data/orig/bottlenecks.txt -FIXED_FL -FL 60 -MAXRATE 32000 ../data/orig/longspeech.pcm $OUTDIR/out_napi_16.pcm >> $LOGG
+../Release/kenny.exe 13000 -INIT_RATE 32000 -FIXED_FL -FL 60 -MAX 100 ../data/orig/longspeech.pcm $OUTDIR/out_napi_17.pcm >> $LOGG
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfault.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfault.txt
new file mode 100644
index 0000000..f4d9478
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfault.txt
@@ -0,0 +1,40 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logfault.txt
+echo "START FAULT TEST" > $LOGFILE
+
+ISAC=../Release/kenny.exe
+ISACFIXFLOAT=../Release/testFixFloat.exe
+
+INFILES=$(cat InputFiles.txt)
+SUBSET=$(cat InputFilesFew.txt)
+CHANNELFILES=$(cat ChannelFiles.txt)
+CHANNELLIST=($(cat ChannelFiles.txt))
+INDIR=../data/orig
+OUTDIR=../dataqaft
+mkdir -p $OUTDIR
+
+TARGETRATE=(10000 15000 20000 25000 30000 32000)
+FAULTTEST=(1 2 3 4 5 6 7 9)
+
+index1=0
+
+file=wb_contspeech.pcm
+
+# Fault test
+for testnr in ${FAULTTEST[*]}
+ do
+ $ISAC 32000 -F $testnr $INDIR/"$file" $OUTDIR/ft$testnr"$file" >> $LOGFILE
+done
+
+# Fault test number 10, error in bitstream
+ $ISAC 32000 -F 10 $INDIR/"$file" $OUTDIR/ft10_"$file" >> $LOGFILE
+ $ISAC 32000 -F 10 -PL 10 $INDIR/"$file" $OUTDIR/ft10plc_"$file" >> $LOGFILE
+ $ISAC 32000 -F 10 -NB 1 $INDIR/"$file" $OUTDIR/ft10nb1_"$file" >> $LOGFILE
+ $ISAC 32000 -F 10 -NB 2 -PL 10 $INDIR/"$file" $OUTDIR/ft10nb2_"$file" >> $LOGFILE
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfixfloat.txt b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfixfloat.txt
new file mode 100644
index 0000000..c9e02df
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/QA/runiSACfixfloat.txt
@@ -0,0 +1,47 @@
+#!/bin/bash
+(set -o igncr) 2>/dev/null && set -o igncr; # force bash to ignore \r character
+
+LOGFILE=logfxfl.txt
+echo "START FIX-FLOAT TEST" > $LOGFILE
+
+
+ISACFIXFLOAT=../testFixFloat.exe
+
+INFILES=$(cat InputFiles.txt)
+SUBSET=$(cat InputFilesFew.txt)
+CHANNELFILES=$(cat ChannelFiles.txt)
+CHANNELLIST=($(cat ChannelFiles.txt))
+INDIR=../data/orig
+OUTDIR=../dataqafxfl
+mkdir -p $OUTDIR
+
+index1=0
+
+for file in $INFILES # loop over all input files
+ do
+
+ for channel in $CHANNELFILES
+ do
+ let "index1=index1+1"
+
+ $ISACFIXFLOAT $INDIR/$channel -m 1 -PLC $INDIR/"$file" $OUTDIR/flfx$index1"$file" >> $LOGFILE
+ $ISACFIXFLOAT $INDIR/$channel -m 2 -PLC $INDIR/"$file" $OUTDIR/fxfl$index1"$file" >> $LOGFILE
+ done
+
+done
+
+index1=0
+
+for file in $SUBSET # loop over the subset of input files
+ do
+ let "index1=index1+1"
+ $ISACFIXFLOAT $INDIR/$channel -m 1 -NB 1 $INDIR/"$file" $OUTDIR/flfxnb1_$index1"$file" >> $LOGFILE
+ $ISACFIXFLOAT $INDIR/$channel -m 2 -NB 1 $INDIR/"$file" $OUTDIR/fxflnb1_$index1"$file" >> $LOGFILE
+ $ISACFIXFLOAT $INDIR/$channel -m 1 -NB 2 -PLC $INDIR/"$file" $OUTDIR/flfxnb2_$index1"$file" >> $LOGFILE
+ $ISACFIXFLOAT $INDIR/$channel -m 2 -NB 2 -PLC $INDIR/"$file" $OUTDIR/fxflnb2_$index1"$file" >> $LOGFILE
+done
+
+echo DONE!
+
+
+
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc b/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc
new file mode 100644
index 0000000..bef71e9
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc
@@ -0,0 +1,96 @@
+/*
+ * 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 <typedefs.h>
+
+#include "gtest/gtest.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "system_wrappers/interface/cpu_features_wrapper.h"
+
+class IsacUnitTest : public testing::Test {
+ protected:
+ // Pass a function pointer to the Tester function.
+ void CalculateResidualEnergyTester(CalculateResidualEnergy
+ CalculateResidualEnergyFunction) {
+ const int kIntOrder = 10;
+ const int32_t kInt32QDomain = 5;
+ const int kIntShift = 11;
+ int16_t a[kIntOrder + 1] = {32760, 122, 7, 0, -32760, -3958,
+ -48, 18745, 498, 9, 23456};
+ int32_t corr[kIntOrder + 1] = {11443647, -27495, 0,
+ 98745, -11443600, 1, 1, 498, 9, 888, 23456};
+ int q_shift_residual = 0;
+ int32_t residual_energy = 0;
+
+ // Test the code path where (residual_energy >= 0x10000).
+ residual_energy = CalculateResidualEnergyFunction(kIntOrder,
+ kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(1789023310, residual_energy);
+ EXPECT_EQ(2, q_shift_residual);
+
+ // Test the code path where (residual_energy < 0x10000)
+ // and ((energy & 0x8000) != 0).
+ for(int i = 0; i < kIntOrder + 1; i++) {
+ a[i] = 24575 >> i;
+ corr[i] = i;
+ }
+ residual_energy = CalculateResidualEnergyFunction(kIntOrder,
+ kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(1595279092, residual_energy);
+ EXPECT_EQ(26, q_shift_residual);
+
+ // Test the code path where (residual_energy <= 0x7fff).
+ for(int i = 0; i < kIntOrder + 1; i++) {
+ a[i] = 2457 >> i;
+ }
+ residual_energy = CalculateResidualEnergyFunction(kIntOrder,
+ kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(2029266944, residual_energy);
+ EXPECT_EQ(33, q_shift_residual);
+ }
+};
+
+TEST_F(IsacUnitTest, CalculateResidualEnergyTest) {
+ CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyC);
+#ifdef WEBRTC_DETECT_ARM_NEON
+ if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
+ CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyNeon);
+ }
+#elif defined(WEBRTC_ARCH_ARM_NEON)
+ CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyNeon);
+#endif
+}
+
+TEST_F(IsacUnitTest, HighpassFilterFixDec32Test) {
+ const int kSamples = 20;
+ int16_t in[kSamples];
+ int32_t state[2] = {12345, 987654};
+#ifdef WEBRTC_ARCH_ARM_V7
+ int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20018, 7917,
+ -1279, -8552, -14494, -7558, -23537, -27258, -30554, -32768, -3432, -32768,
+ 25215, -27536, 22436};
+#else
+ int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20017, 7915,
+ -1280, -8554, -14496, -7561, -23541, -27263, -30560, -32768, -3441, -32768,
+ 25203, -27550, 22419};
+#endif
+
+ for(int i = 0; i < kSamples; i++) {
+ in[i] = WEBRTC_SPL_WORD32_MAX / (i + 1);
+ }
+
+ WebRtcIsacfix_HighpassFilterFixDec32(in, kSamples,
+ WebRtcIsacfix_kHPStCoeffOut1Q30, state);
+
+ for(int i = 0; i < kSamples; i++) {
+ EXPECT_EQ(out[i], in[i]);
+ }
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/kenny.c b/src/modules/audio_coding/codecs/isac/fix/test/kenny.c
new file mode 100644
index 0000000..8b04c98
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/kenny.c
@@ -0,0 +1,853 @@
+/*
+ * 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.
+ */
+
+/* kenny.c - Main function for the iSAC coder */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include "isacfix.h"
+
+
+/* Defines */
+#define SEED_FILE "randseed.txt" /* Used when running decoder on garbage data */
+#define MAX_FRAMESAMPLES 960 /* max number of samples per frame (= 60 ms frame) */
+#define FRAMESAMPLES_10ms 160 /* number of samples per 10ms frame */
+#define FS 16000 /* sampling frequency (Hz) */
+
+/* Function for reading audio data from PCM file */
+int readframe(WebRtc_Word16 *data, FILE *inp, int length) {
+
+ short k, rlen, status = 0;
+
+ rlen = fread(data, sizeof(WebRtc_Word16), length, inp);
+ if (rlen < length) {
+ for (k = rlen; k < length; k++)
+ data[k] = 0;
+ status = 1;
+ }
+
+ return status;
+}
+
+/* Struct for bottleneck model */
+typedef struct {
+ WebRtc_UWord32 send_time; /* samples */
+ WebRtc_UWord32 arrival_time; /* samples */
+ WebRtc_UWord32 sample_count; /* samples */
+ WebRtc_UWord16 rtp_number;
+} BottleNeckModel;
+
+void get_arrival_time(int current_framesamples, /* samples */
+ int packet_size, /* bytes */
+ int bottleneck, /* excluding headers; bits/s */
+ BottleNeckModel *BN_data)
+{
+ const int HeaderSize = 35;
+ int HeaderRate;
+
+ HeaderRate = HeaderSize * 8 * FS / current_framesamples; /* bits/s */
+
+ /* everything in samples */
+ BN_data->sample_count = BN_data->sample_count + current_framesamples;
+
+ BN_data->arrival_time += ((packet_size + HeaderSize) * 8 * FS) / (bottleneck + HeaderRate);
+ BN_data->send_time += current_framesamples;
+
+ if (BN_data->arrival_time < BN_data->sample_count)
+ BN_data->arrival_time = BN_data->sample_count;
+
+ BN_data->rtp_number++;
+}
+
+void get_arrival_time2(int current_framesamples,
+ int current_delay,
+ BottleNeckModel *BN_data)
+{
+ if (current_delay == -1)
+ //dropped packet
+ {
+ BN_data->arrival_time += current_framesamples;
+ }
+ else if (current_delay != -2)
+ {
+ //
+ BN_data->arrival_time += (current_framesamples + ((FS/1000) * current_delay));
+ }
+ //else
+ //current packet has same timestamp as previous packet
+
+ BN_data->rtp_number++;
+}
+
+int main(int argc, char* argv[])
+{
+
+ char inname[100], outname[100], outbitsname[100], bottleneck_file[100];
+ FILE *inp, *outp, *f_bn, *outbits;
+ int endfile;
+
+ int i, errtype, h = 0, k, packetLossPercent = 0;
+ WebRtc_Word16 CodingMode;
+ WebRtc_Word16 bottleneck;
+ WebRtc_Word16 framesize = 30; /* ms */
+ int cur_framesmpls, err = 0, lostPackets = 0;
+
+ /* Runtime statistics */
+ double starttime, runtime, length_file;
+
+ WebRtc_Word16 stream_len = 0;
+ WebRtc_Word16 framecnt, declen = 0;
+ WebRtc_Word16 shortdata[FRAMESAMPLES_10ms];
+ WebRtc_Word16 decoded[MAX_FRAMESAMPLES];
+ WebRtc_UWord16 streamdata[500];
+ WebRtc_Word16 speechType[1];
+ WebRtc_Word16 prevFrameSize = 1;
+ WebRtc_Word16 rateBPS = 0;
+ WebRtc_Word16 fixedFL = 0;
+ WebRtc_Word16 payloadSize = 0;
+ WebRtc_Word32 payloadRate = 0;
+ int setControlBWE = 0;
+ int readLoss;
+ FILE *plFile = NULL;
+
+ char version_number[20];
+ char tmpBit[5] = ".bit";
+
+ double kbps;
+ int totalbits =0;
+ int totalsmpls =0;
+#ifdef _DEBUG
+ FILE *fy;
+#endif
+ WebRtc_Word16 testNum, testCE;
+
+ FILE *fp_gns = NULL;
+ int gns = 0;
+ int cur_delay = 0;
+ char gns_file[100];
+
+ int nbTest = 0;
+ WebRtc_Word16 lostFrame;
+ float scale = (float)0.7;
+ /* only one structure used for ISAC encoder */
+ ISACFIX_MainStruct *ISAC_main_inst;
+
+ /* For fault test 10, garbage data */
+ FILE *seedfile;
+ unsigned int random_seed = (unsigned int) time(NULL);//1196764538
+
+ BottleNeckModel BN_data;
+ f_bn = NULL;
+
+#ifdef _DEBUG
+ fy = fopen("bit_rate.dat", "w");
+ fclose(fy);
+ fy = fopen("bytes_frames.dat", "w");
+ fclose(fy);
+#endif
+
+ readLoss = 0;
+ packetLossPercent = 0;
+
+ /* Handling wrong input arguments in the command line */
+ if ((argc<3) || (argc>21)) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("\n");
+ WebRtcIsacfix_version(version_number);
+ printf("iSAC version %s \n\n", version_number);
+
+ printf("Usage:\n\n");
+ printf("./kenny.exe [-F num][-I] bottleneck_value infile outfile \n\n");
+ printf("with:\n");
+ printf("[-I] :if -I option is specified, the coder will use\n");
+ printf(" an instantaneous Bottleneck value. If not, it\n");
+ printf(" will be an adaptive Bottleneck value.\n\n");
+ printf("bottleneck_value :the value of the bottleneck provided either\n");
+ printf(" as a fixed value (e.g. 25000) or\n");
+ printf(" read from a file (e.g. bottleneck.txt)\n\n");
+ printf("[-INITRATE num] :Set a new value for initial rate. Note! Only used"
+ " in adaptive mode.\n\n");
+ printf("[-FL num] :Set (initial) frame length in msec. Valid length"
+ " are 30 and 60 msec.\n\n");
+ printf("[-FIXED_FL] :Frame length will be fixed to initial value.\n\n");
+ printf("[-MAX num] :Set the limit for the payload size of iSAC"
+ " in bytes. \n");
+ printf(" Minimum 100, maximum 400.\n\n");
+ printf("[-MAXRATE num] :Set the maxrate for iSAC in bits per second. \n");
+ printf(" Minimum 32000, maximum 53400.\n\n");
+ printf("[-F num] :if -F option is specified, the test function\n");
+ printf(" will run the iSAC API fault scenario specified"
+ " by the\n");
+ printf(" supplied number.\n");
+ printf(" F 1 - Call encoder prior to init encoder call\n");
+ printf(" F 2 - Call decoder prior to init decoder call\n");
+ printf(" F 3 - Call decoder prior to encoder call\n");
+ printf(" F 4 - Call decoder with a too short coded"
+ " sequence\n");
+ printf(" F 5 - Call decoder with a too long coded"
+ " sequence\n");
+ printf(" F 6 - Call decoder with random bit stream\n");
+ printf(" F 7 - Call init encoder/decoder at random"
+ " during a call\n");
+ printf(" F 8 - Call encoder/decoder without having"
+ " allocated memory for \n");
+ printf(" encoder/decoder instance\n");
+ printf(" F 9 - Call decodeB without calling decodeA\n");
+ printf(" F 10 - Call decodeB with garbage data\n");
+ printf("[-PL num] : if -PL option is specified 0<num<100 will "
+ "specify the\n");
+ printf(" percentage of packet loss\n\n");
+ printf("[-G file] : if -G option is specified the file given is"
+ " a .gns file\n");
+ printf(" that represents a network profile\n\n");
+ printf("[-NB num] : if -NB option, use the narrowband interfaces\n");
+ printf(" num=1 => encode with narrowband encoder"
+ " (infile is narrowband)\n");
+ printf(" num=2 => decode with narrowband decoder"
+ " (outfile is narrowband)\n\n");
+ printf("[-CE num] : Test of APIs used by Conference Engine.\n");
+ printf(" CE 1 - createInternal, freeInternal,"
+ " getNewBitstream \n");
+ printf(" CE 2 - transcode, getBWE \n");
+ printf(" CE 3 - getSendBWE, setSendBWE. \n\n");
+ printf("[-RTP_INIT num] : if -RTP_INIT option is specified num will be"
+ " the initial\n");
+ printf(" value of the rtp sequence number.\n\n");
+ printf("infile : Normal speech input file\n\n");
+ printf("outfile : Speech output file\n\n");
+ printf("Example usage : \n\n");
+ printf("./kenny.exe -I bottleneck.txt speechIn.pcm speechOut.pcm\n\n");
+ exit(0);
+
+ }
+
+ /* Print version number */
+ WebRtcIsacfix_version(version_number);
+ printf("iSAC version %s \n\n", version_number);
+
+ /* Loop over all command line arguments */
+ CodingMode = 0;
+ testNum = 0;
+ testCE = 0;
+ for (i = 1; i < argc-2;i++) {
+ /* Instantaneous mode */
+ if (!strcmp ("-I", argv[i])) {
+ printf("\nInstantaneous BottleNeck\n");
+ CodingMode = 1;
+ i++;
+ }
+
+ /* Set (initial) bottleneck value */
+ if (!strcmp ("-INITRATE", argv[i])) {
+ rateBPS = atoi(argv[i + 1]);
+ setControlBWE = 1;
+ if ((rateBPS < 10000) || (rateBPS > 32000)) {
+ printf("\n%d is not a initial rate. "
+ "Valid values are in the range 10000 to 32000.\n", rateBPS);
+ exit(0);
+ }
+ printf("\nNew initial rate: %d\n", rateBPS);
+ i++;
+ }
+
+ /* Set (initial) framelength */
+ if (!strcmp ("-FL", argv[i])) {
+ framesize = atoi(argv[i + 1]);
+ if ((framesize != 30) && (framesize != 60)) {
+ printf("\n%d is not a valid frame length. "
+ "Valid length are 30 and 60 msec.\n", framesize);
+ exit(0);
+ }
+ printf("\nFrame Length: %d\n", framesize);
+ i++;
+ }
+
+ /* Fixed frame length */
+ if (!strcmp ("-FIXED_FL", argv[i])) {
+ fixedFL = 1;
+ setControlBWE = 1;
+ }
+
+ /* Set maximum allowed payload size in bytes */
+ if (!strcmp ("-MAX", argv[i])) {
+ payloadSize = atoi(argv[i + 1]);
+ printf("Maximum Payload Size: %d\n", payloadSize);
+ i++;
+ }
+
+ /* Set maximum rate in bytes */
+ if (!strcmp ("-MAXRATE", argv[i])) {
+ payloadRate = atoi(argv[i + 1]);
+ printf("Maximum Rate in kbps: %d\n", payloadRate);
+ i++;
+ }
+
+ /* Test of fault scenarious */
+ if (!strcmp ("-F", argv[i])) {
+ testNum = atoi(argv[i + 1]);
+ printf("\nFault test: %d\n", testNum);
+ if (testNum < 1 || testNum > 10) {
+ printf("\n%d is not a valid Fault Scenario number."
+ " Valid Fault Scenarios are numbered 1-10.\n", testNum);
+ exit(0);
+ }
+ i++;
+ }
+
+ /* Packet loss test */
+ if (!strcmp ("-PL", argv[i])) {
+ if( isdigit( *argv[i+1] ) ) {
+ packetLossPercent = atoi( argv[i+1] );
+ if( (packetLossPercent < 0) | (packetLossPercent > 100) ) {
+ printf( "\nInvalid packet loss perentage \n" );
+ exit( 0 );
+ }
+ if( packetLossPercent > 0 ) {
+ printf( "\nSimulating %d %% of independent packet loss\n",
+ packetLossPercent );
+ } else {
+ printf( "\nNo Packet Loss Is Simulated \n" );
+ }
+ readLoss = 0;
+ } else {
+ readLoss = 1;
+ plFile = fopen( argv[i+1], "rb" );
+ if( plFile == NULL ) {
+ printf( "\n couldn't open the frameloss file: %s\n", argv[i+1] );
+ exit( 0 );
+ }
+ printf( "\nSimulating packet loss through the given "
+ "channel file: %s\n", argv[i+1] );
+ }
+ i++;
+ }
+
+ /* Random packetlosses */
+ if (!strcmp ("-rnd", argv[i])) {
+ srand(time(NULL) );
+ printf( "\n Random pattern in lossed packets \n" );
+ }
+
+ /* Use gns file */
+ if (!strcmp ("-G", argv[i])) {
+ sscanf(argv[i + 1], "%s", gns_file);
+ fp_gns = fopen(gns_file, "rb");
+ if (fp_gns == NULL) {
+ printf("Cannot read file %s.\n", gns_file);
+ exit(0);
+ }
+ gns = 1;
+ i++;
+ }
+
+ /* Run Narrowband interfaces (either encoder or decoder) */
+ if (!strcmp ("-NB", argv[i])) {
+ nbTest = atoi(argv[i + 1]);
+ i++;
+ }
+
+ /* Run Conference Engine APIs */
+ if (!strcmp ("-CE", argv[i])) {
+ testCE = atoi(argv[i + 1]);
+ if (testCE==1 || testCE==2) {
+ i++;
+ scale = (float)atof( argv[i+1] );
+ } else if (testCE < 1 || testCE > 3) {
+ printf("\n%d is not a valid CE-test number, valid Fault "
+ "Scenarios are numbered 1-3\n", testCE);
+ exit(0);
+ }
+ i++;
+ }
+
+ /* Set initial RTP number */
+ if (!strcmp ("-RTP_INIT", argv[i])) {
+ i++;
+ }
+ }
+
+ /* Get Bottleneck value */
+ /* Gns files and bottleneck should not and can not be used simultaneously */
+ bottleneck = atoi(argv[CodingMode+1]);
+ if (bottleneck == 0 && gns == 0) {
+ sscanf(argv[CodingMode+1], "%s", bottleneck_file);
+ f_bn = fopen(bottleneck_file, "rb");
+ if (f_bn == NULL) {
+ printf("No value provided for BottleNeck and cannot read file %s\n", bottleneck_file);
+ exit(0);
+ } else {
+ int aux_var;
+ printf("reading bottleneck rates from file %s\n\n",bottleneck_file);
+ if (fscanf(f_bn, "%d", &aux_var) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ if (fscanf(f_bn, "%d", &aux_var) == EOF) {
+ exit(0);
+ }
+ }
+ bottleneck = (WebRtc_Word16)aux_var;
+ /* Bottleneck is a cosine function
+ * Matlab code for writing the bottleneck file:
+ * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
+ * fid = fopen('bottleneck.txt', 'wb');
+ * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
+ */
+ }
+ } else {
+ f_bn = NULL;
+ printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+ }
+
+ if (CodingMode == 0) {
+ printf("\nAdaptive BottleNeck\n");
+ }
+
+ /* Get Input and Output files */
+ sscanf(argv[argc-2], "%s", inname);
+ sscanf(argv[argc-1], "%s", outname);
+
+ /* Add '.bit' to output bitstream file */
+ while ((int)outname[h] != 0) {
+ outbitsname[h] = outname[h];
+ h++;
+ }
+ for (k=0; k<5; k++) {
+ outbitsname[h] = tmpBit[k];
+ h++;
+ }
+ if ((inp = fopen(inname,"rb")) == NULL) {
+ printf(" iSAC: Cannot read file %s\n", inname);
+ exit(1);
+ }
+ if ((outp = fopen(outname,"wb")) == NULL) {
+ printf(" iSAC: Cannot write file %s\n", outname);
+ exit(1);
+ }
+
+ if ((outbits = fopen(outbitsname,"wb")) == NULL) {
+ printf(" iSAC: Cannot write file %s\n", outbitsname);
+ exit(1);
+ }
+ printf("\nInput:%s\nOutput:%s\n\n", inname, outname);
+
+ /* Error test number 10, garbage data */
+ if (testNum == 10) {
+ /* Test to run decoder with garbage data */
+ srand(random_seed);
+
+ if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
+ printf("Error: Could not open file %s\n", SEED_FILE);
+ }
+ else {
+ fprintf(seedfile, "%u\n", random_seed);
+ fclose(seedfile);
+ }
+ }
+
+ /* Runtime statistics */
+ starttime = clock()/(double)CLOCKS_PER_SEC;
+
+ /* Initialize the ISAC and BN structs */
+ if (testNum != 8)
+ {
+ if(1){
+ err =WebRtcIsacfix_Create(&ISAC_main_inst);
+ }else{
+ /* Test the Assign functions */
+ int sss;
+ void *ppp;
+ err =WebRtcIsacfix_AssignSize(&sss);
+ ppp=malloc(sss);
+ err =WebRtcIsacfix_Assign(&ISAC_main_inst,ppp);
+ }
+ /* Error check */
+ if (err < 0) {
+ printf("\n\n Error in create.\n\n");
+ }
+ if (testCE == 1) {
+ err = WebRtcIsacfix_CreateInternal(ISAC_main_inst);
+ /* Error check */
+ if (err < 0) {
+ printf("\n\n Error in createInternal.\n\n");
+ }
+ }
+ }
+
+ /* Init of bandwidth data */
+ BN_data.send_time = 0;
+ BN_data.arrival_time = 0;
+ BN_data.sample_count = 0;
+ BN_data.rtp_number = 0;
+
+ /* Initialize encoder and decoder */
+ framecnt= 0;
+ endfile = 0;
+ if (testNum != 1) {
+ WebRtcIsacfix_EncoderInit(ISAC_main_inst, CodingMode);
+ }
+ if (testNum != 2) {
+ WebRtcIsacfix_DecoderInit(ISAC_main_inst);
+ }
+
+ if (CodingMode == 1) {
+ err = WebRtcIsacfix_Control(ISAC_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in control: %d.\n\n", errtype);
+ }
+ } else if(setControlBWE == 1) {
+ err = WebRtcIsacfix_ControlBwe(ISAC_main_inst, rateBPS, framesize, fixedFL);
+ }
+
+ if (payloadSize != 0) {
+ err = WebRtcIsacfix_SetMaxPayloadSize(ISAC_main_inst, payloadSize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in SetMaxPayloadSize: %d.\n\n", errtype);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (payloadRate != 0) {
+ err = WebRtcIsacfix_SetMaxRate(ISAC_main_inst, payloadRate);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in SetMaxRateInBytes: %d.\n\n", errtype);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ *speechType = 1;
+
+
+ while (endfile == 0) {
+
+ if(testNum == 7 && (rand()%2 == 0)) {
+ err = WebRtcIsacfix_EncoderInit(ISAC_main_inst, CodingMode);
+ /* Error check */
+ if (err < 0) {
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in encoderinit: %d.\n\n", errtype);
+ }
+
+ err = WebRtcIsacfix_DecoderInit(ISAC_main_inst);
+ /* Error check */
+ if (err < 0) {
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in decoderinit: %d.\n\n", errtype);
+ }
+ }
+
+
+ cur_framesmpls = 0;
+ while (1) {
+ /* Read 10 ms speech block */
+ if (nbTest != 1) {
+ endfile = readframe(shortdata, inp, FRAMESAMPLES_10ms);
+ } else {
+ endfile = readframe(shortdata, inp, (FRAMESAMPLES_10ms/2));
+ }
+
+ if (testNum == 7) {
+ srand(time(NULL));
+ }
+
+ /* iSAC encoding */
+ if (!(testNum == 3 && framecnt == 0)) {
+ if (nbTest != 1) {
+ short bwe;
+
+ /* Encode */
+ stream_len = WebRtcIsacfix_Encode(ISAC_main_inst,
+ shortdata,
+ (WebRtc_Word16*)streamdata);
+
+ /* If packet is ready, and CE testing, call the different API functions
+ from the internal API. */
+ if (stream_len>0) {
+ if (testCE == 1) {
+ err = WebRtcIsacfix_ReadBwIndex((WebRtc_Word16*)streamdata, &bwe);
+ stream_len = WebRtcIsacfix_GetNewBitStream(
+ ISAC_main_inst,
+ bwe,
+ scale,
+ (WebRtc_Word16*)streamdata);
+ } else if (testCE == 2) {
+ /* transcode function not supported */
+ } else if (testCE == 3) {
+ /* Only for Function testing. The functions should normally
+ not be used in this way */
+
+ err = WebRtcIsacfix_GetDownLinkBwIndex(ISAC_main_inst, &bwe);
+ /* Error Check */
+ if (err < 0) {
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in getSendBWE: %d.\n", errtype);
+ }
+
+ err = WebRtcIsacfix_UpdateUplinkBw(ISAC_main_inst, bwe);
+ /* Error Check */
+ if (err < 0) {
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in setBWE: %d.\n", errtype);
+ }
+
+ }
+ }
+ } else {
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ stream_len = WebRtcIsacfix_EncodeNb(ISAC_main_inst,
+ shortdata,
+ streamdata);
+#else
+ stream_len = -1;
+#endif
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ if (stream_len < 0 || err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in encoder: %d.\n", errtype);
+ } else {
+ if (fwrite(streamdata, sizeof(char),
+ stream_len, outbits) != (size_t)stream_len) {
+ return -1;
+ }
+ }
+
+ cur_framesmpls += FRAMESAMPLES_10ms;
+
+ /* read next bottleneck rate */
+ if (f_bn != NULL) {
+ int aux_var;
+ if (fscanf(f_bn, "%d", &aux_var) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ if (fscanf(f_bn, "%d", &aux_var) == EOF) {
+ exit(0);
+ }
+ }
+ bottleneck = (WebRtc_Word16)aux_var;
+ if (CodingMode == 1) {
+ WebRtcIsacfix_Control(ISAC_main_inst, bottleneck, framesize);
+ }
+ }
+
+ /* exit encoder loop if the encoder returned a bitstream */
+ if (stream_len != 0) break;
+ }
+
+ /* make coded sequence to short be inreasing */
+ /* the length the decoder expects */
+ if (testNum == 4) {
+ stream_len += 10;
+ }
+
+ /* make coded sequence to long be decreasing */
+ /* the length the decoder expects */
+ if (testNum == 5) {
+ stream_len -= 10;
+ }
+
+ if (testNum == 6) {
+ srand(time(NULL));
+ for (i = 0; i < stream_len; i++ ) {
+ streamdata[i] = rand();
+ }
+ }
+
+ /* set pointer to beginning of file */
+ if (fp_gns != NULL) {
+ if (fscanf(fp_gns, "%d", &cur_delay) == EOF) {
+ fseek(fp_gns, 0L, SEEK_SET);
+ if (fscanf(fp_gns, "%d", &cur_delay) == EOF) {
+ exit(0);
+ }
+ }
+ }
+
+ /* simulate packet handling through NetEq and the modem */
+ if (!(testNum == 3 && framecnt == 0)) {
+ if (gns == 0) {
+ get_arrival_time(cur_framesmpls, stream_len, bottleneck,
+ &BN_data);
+ } else {
+ get_arrival_time2(cur_framesmpls, cur_delay, &BN_data);
+ }
+ }
+
+ /* packet not dropped */
+ if (cur_delay != -1) {
+
+ /* Error test number 10, garbage data */
+ if (testNum == 10) {
+ for ( i = 0; i < stream_len; i++) {
+ streamdata[i] = (short) (streamdata[i] + (short) rand());
+ }
+ }
+
+ if (testNum != 9) {
+ err = WebRtcIsacfix_UpdateBwEstimate(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.send_time,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in decoder: %d.\n", errtype);
+ }
+ }
+#ifdef _DEBUG
+ fprintf(stderr," \rframe = %7d", framecnt);
+#endif
+
+ if( readLoss == 1 ) {
+ if( fread( &lostFrame, sizeof(WebRtc_Word16), 1, plFile ) != 1 ) {
+ rewind( plFile );
+ }
+ lostFrame = !lostFrame;
+ } else {
+ lostFrame = (rand()%100 < packetLossPercent);
+ }
+
+
+
+ /* iSAC decoding */
+ if( lostFrame && framecnt > 0) {
+ if (nbTest !=2) {
+ declen = WebRtcIsacfix_DecodePlc(ISAC_main_inst,
+ decoded, prevFrameSize );
+ } else {
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ declen = WebRtcIsacfix_DecodePlcNb(ISAC_main_inst, decoded,
+ prevFrameSize );
+#else
+ declen = -1;
+#endif
+ }
+ lostPackets++;
+ } else {
+ if (nbTest !=2 ) {
+ short FL;
+ /* Call getFramelen, only used here for function test */
+ err = WebRtcIsacfix_ReadFrameLen((WebRtc_Word16*)streamdata, &FL);
+ declen = WebRtcIsacfix_Decode( ISAC_main_inst, streamdata, stream_len,
+ decoded, speechType );
+ /* Error check */
+ if (err<0 || declen<0 || FL!=declen) {
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in decode_B/or getFrameLen: %d.\n", errtype);
+ }
+ prevFrameSize = declen/480;
+
+ } else {
+#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
+ declen = WebRtcIsacfix_DecodeNb( ISAC_main_inst, streamdata,
+ stream_len, decoded, speechType );
+#else
+ declen = -1;
+#endif
+ prevFrameSize = declen/240;
+ }
+ }
+
+ if (declen <= 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
+ printf("\nError in decoder: %d.\n", errtype);
+ }
+
+ /* Write decoded speech frame to file */
+ if (fwrite(decoded, sizeof(WebRtc_Word16),
+ declen, outp) != (size_t)declen) {
+ return -1;
+ }
+ // fprintf( ratefile, "%f \n", stream_len / ( ((double)declen)/
+ // ((double)FS) ) * 8 );
+ } else {
+ lostPackets++;
+ }
+ framecnt++;
+
+ totalsmpls += declen;
+ totalbits += 8 * stream_len;
+ kbps = ((double) FS) / ((double) cur_framesmpls) * 8.0 *
+ stream_len / 1000.0;// kbits/s
+
+ /* Error test number 10, garbage data */
+ if (testNum == 10) {
+ if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
+ printf( "Error: Could not open file %s\n", SEED_FILE);
+ }
+ else {
+ fprintf(seedfile, "ok\n\n");
+ fclose(seedfile);
+ }
+ }
+
+#ifdef _DEBUG
+
+ fy = fopen("bit_rate.dat", "a");
+ fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
+ fclose(fy);
+
+#endif /* _DEBUG */
+
+ }
+ printf("\nLost Frames %d ~ %4.1f%%\n", lostPackets,
+ (double)lostPackets/(double)framecnt*100.0 );
+ printf("\n\ntotal bits = %d bits", totalbits);
+ printf("\nmeasured average bitrate = %0.3f kbits/s",
+ (double)totalbits *(FS/1000) / totalsmpls);
+ printf("\n");
+
+#ifdef _DEBUG
+ /* fprintf(stderr,"\n\ntotal bits = %d bits", totalbits);
+ fprintf(stderr,"\nmeasured average bitrate = %0.3f kbits/s",
+ (double)totalbits *(FS/1000) / totalsmpls);
+ fprintf(stderr,"\n");
+ */
+#endif /* _DEBUG */
+
+ /* Runtime statistics */
+
+
+ runtime = (double)(((double)clock()/(double)CLOCKS_PER_SEC)-starttime);
+ length_file = ((double)framecnt*(double)declen/FS);
+ printf("\n\nLength of speech file: %.1f s\n", length_file);
+ printf("Time to run iSAC: %.2f s (%.2f %% of realtime)\n\n",
+ runtime, (100*runtime/length_file));
+ printf("\n\n_______________________________________________\n");
+
+ fclose(inp);
+ fclose(outp);
+ fclose(outbits);
+
+ if ( testCE == 1) {
+ WebRtcIsacfix_FreeInternal(ISAC_main_inst);
+ }
+ WebRtcIsacfix_Free(ISAC_main_inst);
+ return 0;
+}
diff --git a/src/modules/audio_coding/codecs/isac/fix/test/test_iSACfixfloat.c b/src/modules/audio_coding/codecs/isac/fix/test/test_iSACfixfloat.c
new file mode 100644
index 0000000..57c30ca
--- /dev/null
+++ b/src/modules/audio_coding/codecs/isac/fix/test/test_iSACfixfloat.c
@@ -0,0 +1,693 @@
+/*
+ * 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.
+ */
+
+/*
+ * test_iSACfixfloat.c
+ *
+ * Test compatibility and quality between floating- and fixed-point code
+ * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* include API */
+#include "isac.h"
+#include "isacfix.h"
+
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms 160
+/* sampling frequency (Hz) */
+#define FS 16000
+
+
+
+/* Runtime statistics */
+#include <time.h>
+#define CLOCKS_PER_SEC 1000
+
+
+
+// FILE *histfile, *ratefile;
+
+
+/* function for reading audio data from PCM file */
+int readframe(WebRtc_Word16 *data, FILE *inp, int length) {
+
+ short k, rlen, status = 0;
+
+ rlen = fread(data, sizeof(WebRtc_Word16), length, inp);
+ if (rlen < length) {
+ for (k = rlen; k < length; k++)
+ data[k] = 0;
+ status = 1;
+ }
+
+ return status;
+}
+
+typedef struct {
+ WebRtc_UWord32 send_time; /* samples */
+ WebRtc_UWord32 arrival_time; /* samples */
+ WebRtc_UWord32 sample_count; /* samples */
+ WebRtc_UWord16 rtp_number;
+} BottleNeckModel;
+
+void get_arrival_time(int current_framesamples, /* samples */
+ int packet_size, /* bytes */
+ int bottleneck, /* excluding headers; bits/s */
+ BottleNeckModel *BN_data)
+{
+ const int HeaderSize = 35;
+ int HeaderRate;
+
+ HeaderRate = HeaderSize * 8 * FS / current_framesamples; /* bits/s */
+
+ /* everything in samples */
+ BN_data->sample_count = BN_data->sample_count + current_framesamples;
+
+ BN_data->arrival_time += ((packet_size + HeaderSize) * 8 * FS) / (bottleneck + HeaderRate);
+ BN_data->send_time += current_framesamples;
+
+ if (BN_data->arrival_time < BN_data->sample_count)
+ BN_data->arrival_time = BN_data->sample_count;
+
+ BN_data->rtp_number++;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+
+ char inname[50], outname[50], bottleneck_file[50], bitfilename[60], bitending[10]="_bits.pcm";
+ FILE *inp, *outp, *f_bn, *bitsp;
+ int framecnt, endfile;
+
+
+ int i,j,errtype, plc=0;
+ WebRtc_Word16 CodingMode;
+ WebRtc_Word16 bottleneck;
+
+ WebRtc_Word16 framesize = 30; /* ms */
+ //WebRtc_Word16 framesize = 60; /* To invoke cisco complexity case at frame 2252 */
+
+ int cur_framesmpls, err;
+
+ /* Runtime statistics */
+ double starttime;
+ double runtime;
+ double length_file;
+
+ WebRtc_Word16 stream_len = 0;
+ WebRtc_Word16 declen;
+
+ WebRtc_Word16 shortdata[FRAMESAMPLES_10ms];
+ WebRtc_Word16 decoded[MAX_FRAMESAMPLES];
+ WebRtc_UWord16 streamdata[600];
+ WebRtc_Word16 speechType[1];
+
+// WebRtc_Word16 *iSACstruct;
+
+ char version_number[20];
+ int mode=-1, tmp, nbTest=0; /*,sss;*/
+
+#ifdef _DEBUG
+ FILE *fy;
+ double kbps;
+ int totalbits =0;
+ int totalsmpls =0;
+#endif /* _DEBUG */
+
+
+
+
+ /* only one structure used for ISAC encoder */
+ ISAC_MainStruct *ISAC_main_inst;
+ ISACFIX_MainStruct *ISACFIX_main_inst;
+
+ BottleNeckModel BN_data;
+ f_bn = NULL;
+
+#ifdef _DEBUG
+ fy = fopen("bit_rate.dat", "w");
+ fclose(fy);
+ fy = fopen("bytes_frames.dat", "w");
+ fclose(fy);
+#endif /* _DEBUG */
+
+
+//histfile = fopen("histo.dat", "ab");
+//ratefile = fopen("rates.dat", "ab");
+
+ /* handling wrong input arguments in the command line */
+ if ((argc<6) || (argc>10)) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("\n");
+ WebRtcIsacfix_version(version_number);
+ printf("iSAC version %s \n\n", version_number);
+
+ printf("Usage:\n\n");
+ printf("./kenny.exe [-I] bottleneck_value infile outfile \n\n");
+ printf("with:\n");
+
+ printf("[-I] : if -I option is specified, the coder will use\n");
+ printf(" an instantaneous Bottleneck value. If not, it\n");
+ printf(" will be an adaptive Bottleneck value.\n\n");
+ printf("bottleneck_value : the value of the bottleneck provided either\n");
+ printf(" as a fixed value (e.g. 25000) or\n");
+ printf(" read from a file (e.g. bottleneck.txt)\n\n");
+ printf("[-m] mode : Mode (encoder - decoder):\n");
+ printf(" : 0 - float - float \n");
+ printf(" : 1 - float - fix \n");
+ printf(" : 2 - fix - float \n");
+ printf(" : 3 - fix - fix \n");
+ printf("[-PLC] : Test PLC packetlosses\n");
+ printf("[-NB] num : Test NB interfaces, num=1 encNB, num=2 decNB\n");
+ printf("infile : Normal speech input file\n\n");
+ printf("outfile : Speech output file\n\n");
+ printf("Example usage:\n\n");
+ printf("./kenny.exe -I bottleneck.txt -m 1 speechIn.pcm speechOut.pcm\n\n");
+ exit(0);
+
+ }
+
+
+ printf("--------------------START---------------------\n\n");
+ WebRtcIsac_version(version_number);
+ printf("iSAC FLOAT version %s \n", version_number);
+ WebRtcIsacfix_version(version_number);
+ printf("iSAC FIX version %s \n\n", version_number);
+
+ CodingMode = 0;
+ tmp=1;
+ for (i = 1; i < argc;i++)
+ {
+ if (!strcmp ("-I", argv[i]))
+ {
+ printf("\nInstantaneous BottleNeck\n");
+ CodingMode = 1;
+ i++;
+ tmp=0;
+ }
+
+ if (!strcmp ("-m", argv[i])) {
+ mode=atoi(argv[i+1]);
+ i++;
+ }
+
+ if (!strcmp ("-PLC", argv[i]))
+ {
+ plc=1;
+ }
+
+ if (!strcmp ("-NB", argv[i]))
+ {
+ nbTest = atoi(argv[i + 1]);
+ i++;
+ }
+
+ }
+
+ if(mode<0) {
+ printf("\nError! Mode must be set: -m 0 \n");
+ exit(0);
+ }
+
+ if (CodingMode == 0)
+ {
+ printf("\nAdaptive BottleNeck\n");
+ }
+
+
+
+ /* Get Bottleneck value */
+ bottleneck = atoi(argv[2-tmp]);
+ if (bottleneck == 0)
+ {
+ sscanf(argv[2-tmp], "%s", bottleneck_file);
+ f_bn = fopen(bottleneck_file, "rb");
+ if (f_bn == NULL)
+ {
+ printf("No value provided for BottleNeck and cannot read file %s.\n", bottleneck_file);
+ exit(0);
+ }
+ else {
+ printf("reading bottleneck rates from file %s\n\n",bottleneck_file);
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ fscanf(f_bn, "%d", &bottleneck);
+ }
+
+ /* Bottleneck is a cosine function
+ * Matlab code for writing the bottleneck file:
+ * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
+ * fid = fopen('bottleneck.txt', 'wb');
+ * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
+ */
+ }
+ }
+ else
+ {
+ printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+ }
+
+
+
+ /* Get Input and Output files */
+ sscanf(argv[argc-2], "%s", inname);
+ sscanf(argv[argc-1], "%s", outname);
+
+ if ((inp = fopen(inname,"rb")) == NULL) {
+ printf(" iSAC: Cannot read file %s.\n", inname);
+ exit(1);
+ }
+ if ((outp = fopen(outname,"wb")) == NULL) {
+ printf(" iSAC: Cannot write file %s.\n", outname);
+ exit(1);
+ }
+ printf("\nInput:%s\nOutput:%s\n", inname, outname);
+
+ i=0;
+ while (outname[i]!='\0') {
+ bitfilename[i]=outname[i];
+ i++;
+ }
+ i-=4;
+ for (j=0;j<9;j++, i++)
+ bitfilename[i]=bitending[j];
+ bitfilename[i]='\0';
+ if ((bitsp = fopen(bitfilename,"wb")) == NULL) {
+ printf(" iSAC: Cannot read file %s.\n", bitfilename);
+ exit(1);
+ }
+ printf("Bitstream:%s\n\n", bitfilename);
+
+
+
+ starttime = clock()/(double)CLOCKS_PER_SEC; /* Runtime statistics */
+
+
+ /* Initialize the ISAC and BN structs */
+ WebRtcIsac_create(&ISAC_main_inst);
+/* WebRtcIsacfix_AssignSize(&sss);
+ iSACstruct=malloc(sss);
+ WebRtcIsacfix_Assign(&ISACFIX_main_inst,iSACstruct);*/
+ WebRtcIsacfix_Create(&ISACFIX_main_inst);
+
+ BN_data.send_time = 0;
+ BN_data.arrival_time = 0;
+ BN_data.sample_count = 0;
+ BN_data.rtp_number = 0;
+
+ /* Initialize encoder and decoder */
+ framecnt= 0;
+ endfile = 0;
+
+ if (mode==0) { /* Encode using FLOAT, decode using FLOAT */
+
+ printf("Coding mode: Encode using FLOAT, decode using FLOAT \n\n");
+
+ /* Init iSAC FLOAT */
+ WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ // exit(EXIT_FAILURE);
+ }
+ }
+
+ } else if (mode==1) { /* Encode using FLOAT, decode using FIX */
+
+ printf("Coding mode: Encode using FLOAT, decode using FIX \n\n");
+
+ /* Init iSAC FLOAT */
+ WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ // exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Init iSAC FIX */
+ WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
+ WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ }
+ } else if (mode==2) { /* Encode using FIX, decode using FLOAT */
+
+ printf("Coding mode: Encode using FIX, decode using FLOAT \n\n");
+
+ /* Init iSAC FLOAT */
+ WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Init iSAC FIX */
+ WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
+ WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ }
+ } else if (mode==3) {
+
+ printf("Coding mode: Encode using FIX, decode using FIX \n\n");
+
+ WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
+ WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\n Error in initialization: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ }
+
+ } else
+ printf("Mode must be value between 0 and 3\n");
+ *speechType = 1;
+
+//#define BI_TEST 1
+#ifdef BI_TEST
+ err = WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_main_inst, 300);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\n Error in setMaxPayloadSize: %d.\n\n", errtype);
+ fclose(inp);
+ fclose(outp);
+ fclose(bitsp);
+ return(EXIT_FAILURE);
+ }
+#endif
+
+
+ while (endfile == 0) {
+
+ cur_framesmpls = 0;
+ while (1) {
+ /* Read 10 ms speech block */
+ if (nbTest != 1)
+ endfile = readframe(shortdata, inp, FRAMESAMPLES_10ms);
+ else
+ endfile = readframe(shortdata, inp, (FRAMESAMPLES_10ms/2));
+
+ /* iSAC encoding */
+
+ if (mode==0 || mode ==1) {
+ stream_len = WebRtcIsac_Encode(ISAC_main_inst, shortdata, streamdata);
+ if (stream_len < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\nError in encoder: %d.\n\n", errtype);
+ // exit(EXIT_FAILURE);
+ }
+ } else if (mode==2 || mode==3) {
+ /* iSAC encoding */
+ if (nbTest != 1)
+ stream_len = WebRtcIsacfix_Encode(ISACFIX_main_inst, shortdata, streamdata);
+ else
+ stream_len = WebRtcIsacfix_EncodeNb(ISACFIX_main_inst, shortdata, streamdata);
+
+ if (stream_len < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\nError in encoder: %d.\n\n", errtype);
+ // exit(EXIT_FAILURE);
+ }
+ }
+
+ cur_framesmpls += FRAMESAMPLES_10ms;
+
+ /* read next bottleneck rate */
+ if (f_bn != NULL) {
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ fscanf(f_bn, "%d", &bottleneck);
+ }
+ if (CodingMode == 1) {
+ if (mode==0 || mode==1)
+ WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ else if (mode==2 || mode==3)
+ WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
+ }
+ }
+
+ /* exit encoder loop if the encoder returned a bitstream */
+ if (stream_len != 0) break;
+ }
+
+ fwrite(streamdata, 1, stream_len, bitsp); /* NOTE! Writes bytes to file */
+
+ /* simulate packet handling through NetEq and the modem */
+ get_arrival_time(cur_framesmpls, stream_len, bottleneck,
+ &BN_data);
+//*****************************
+ if (1){
+ if (mode==0) {
+ err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ /* iSAC decoding */
+ declen = WebRtcIsac_Decode(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ if (declen <= 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ } else if (mode==1) {
+
+ err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+ err = WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+
+ declen = WebRtcIsac_Decode(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+
+ /* iSAC decoding */
+ if (plc && (framecnt+1)%10 == 0) {
+ if (nbTest !=2 )
+ declen = WebRtcIsacfix_DecodePlc( ISACFIX_main_inst, decoded, 1 );
+ else
+ declen = WebRtcIsacfix_DecodePlcNb( ISACFIX_main_inst, decoded, 1 );
+ } else {
+ if (nbTest !=2 )
+ declen = WebRtcIsacfix_Decode(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ else
+ declen = WebRtcIsacfix_DecodeNb(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ }
+
+ if (declen <= 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ } else if (mode==2) {
+ err = WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+
+ err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ /* iSAC decoding */
+ declen = WebRtcIsac_Decode(ISAC_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ if (declen <= 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ } else if (mode==3) {
+ err = WebRtcIsacfix_UpdateBwEstimate(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ BN_data.rtp_number,
+ BN_data.send_time,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ /* iSAC decoding */
+
+ if (plc && (framecnt+1)%10 == 0) {
+ if (nbTest !=2 )
+ declen = WebRtcIsacfix_DecodePlc( ISACFIX_main_inst, decoded, 1 );
+ else
+ declen = WebRtcIsacfix_DecodePlcNb( ISACFIX_main_inst, decoded, 1 );
+ } else {
+ if (nbTest !=2 )
+ declen = WebRtcIsacfix_Decode(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ else
+ declen = WebRtcIsacfix_DecodeNb(ISACFIX_main_inst,
+ streamdata,
+ stream_len,
+ decoded,
+ speechType);
+ }
+ if (declen <= 0) {
+ /* exit if returned with error */
+ errtype=WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
+ printf("\n\nError in decoder: %d.\n\n", errtype);
+ //exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Write decoded speech frame to file */
+ fwrite(decoded, sizeof(WebRtc_Word16), declen, outp);
+ }
+
+ fprintf(stderr," \rframe = %d", framecnt);
+ framecnt++;
+
+
+
+#ifdef _DEBUG
+
+ totalsmpls += declen;
+ totalbits += 8 * stream_len;
+ kbps = ((double) FS) / ((double) cur_framesmpls) * 8.0 * stream_len / 1000.0;// kbits/s
+ fy = fopen("bit_rate.dat", "a");
+ fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
+ fclose(fy);
+
+#endif /* _DEBUG */
+
+ }
+
+#ifdef _DEBUG
+ printf("\n\ntotal bits = %d bits", totalbits);
+ printf("\nmeasured average bitrate = %0.3f kbits/s", (double)totalbits *(FS/1000) / totalsmpls);
+ printf("\n");
+#endif /* _DEBUG */
+
+ /* Runtime statistics */
+ runtime = (double)(clock()/(double)CLOCKS_PER_SEC-starttime);
+ length_file = ((double)framecnt*(double)declen/FS);
+ printf("\n\nLength of speech file: %.1f s\n", length_file);
+ printf("Time to run iSAC: %.2f s (%.2f %% of realtime)\n\n", runtime, (100*runtime/length_file));
+ printf("---------------------END----------------------\n");
+
+ fclose(inp);
+ fclose(outp);
+
+ WebRtcIsac_Free(ISAC_main_inst);
+ WebRtcIsacfix_Free(ISACFIX_main_inst);
+
+
+
+// fclose(histfile);
+// fclose(ratefile);
+
+ return 0;
+
+}
+
+
diff --git a/src/system_wrappers/interface/atomic32.h b/src/system_wrappers/interface/atomic32.h
new file mode 100644
index 0000000..e2b1258
--- /dev/null
+++ b/src/system_wrappers/interface/atomic32.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+// Atomic, system independent 32-bit integer. Unless you know what you're
+// doing, use locks instead! :-)
+//
+// Note: uses full memory barriers.
+// Note: assumes 32-bit (or higher) system
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
+
+#include <cstddef>
+
+#include "common_types.h"
+#include "constructor_magic.h"
+
+namespace webrtc {
+
+// 32 bit atomic variable. Note that this class relies on the compiler to
+// align the 32 bit value correctly (on a 32 bit boundary), so as long as you're
+// not doing things like reinterpret_cast over some custom allocated memory
+// without being careful with alignment, you should be fine.
+class Atomic32
+{
+public:
+ Atomic32(WebRtc_Word32 initialValue = 0);
+ ~Atomic32();
+
+ // Prefix operator!
+ WebRtc_Word32 operator++();
+ WebRtc_Word32 operator--();
+
+ WebRtc_Word32 operator+=(WebRtc_Word32 value);
+ WebRtc_Word32 operator-=(WebRtc_Word32 value);
+
+ // Sets the value atomically to newValue if the value equals compare value.
+ // The function returns true if the exchange happened.
+ bool CompareExchange(WebRtc_Word32 newValue, WebRtc_Word32 compareValue);
+ WebRtc_Word32 Value() const;
+
+private:
+ // Disable the + and - operator since it's unclear what these operations
+ // should do.
+ Atomic32 operator+(const Atomic32& other);
+ Atomic32 operator-(const Atomic32& other);
+
+ // Checks if |_value| is 32bit aligned.
+ inline bool Is32bitAligned() const {
+ return (reinterpret_cast<ptrdiff_t>(&_value) & 3) == 0;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(Atomic32);
+
+ WebRtc_Word32 _value;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
diff --git a/src/system_wrappers/interface/atomic32_wrapper.h b/src/system_wrappers/interface/atomic32_wrapper.h
deleted file mode 100644
index 40862fb..0000000
--- a/src/system_wrappers/interface/atomic32_wrapper.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit integer.
-// Note: uses full memory barriers.
-// Note: assumes 32-bit (or higher) system
-#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
-#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl;
-class Atomic32Wrapper
-{
-public:
- Atomic32Wrapper(WebRtc_Word32 initialValue = 0);
- ~Atomic32Wrapper();
-
- // Prefix operator!
- WebRtc_Word32 operator++();
- WebRtc_Word32 operator--();
-
- Atomic32Wrapper& operator=(const Atomic32Wrapper& rhs);
- Atomic32Wrapper& operator=(WebRtc_Word32 rhs);
-
- WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- // Sets the value atomically to newValue if the value equals compare value.
- // The function returns true if the exchange happened.
- bool CompareExchange(WebRtc_Word32 newValue, WebRtc_Word32 compareValue);
- WebRtc_Word32 Value() const;
-private:
- // Disable the + and - operator since it's unclear what these operations
- // should do.
- Atomic32Wrapper operator+(const Atomic32Wrapper& rhs);
- Atomic32Wrapper operator-(const Atomic32Wrapper& rhs);
-
- WebRtc_Word32& operator++(int);
- WebRtc_Word32& operator--(int);
-
- // Cheshire cat to hide the implementation (faster than
- // using virtual functions)
- Atomic32Impl& _impl;
-};
-} // namespace webrtc
-#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
diff --git a/src/system_wrappers/interface/compile_assert.h b/src/system_wrappers/interface/compile_assert.h
new file mode 100644
index 0000000..4feda86
--- /dev/null
+++ b/src/system_wrappers/interface/compile_assert.h
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
+
+/* Use this macro to verify at compile time that certain restrictions are met.
+ * The argument is the boolean expression to evaluate.
+ * Example:
+ * COMPILE_ASSERT(sizeof(foo) < 128);
+*/
+#define COMPILE_ASSERT(expression) switch(0){case 0: case expression:;}
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
diff --git a/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h b/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h
new file mode 100644
index 0000000..d85c724
--- /dev/null
+++ b/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file under third_party_mods/chromium directory of
+// source tree or at
+// http://src.chromium.org/viewvc/chrome/trunk/src/LICENSE
+
+// Various inline functions and macros to fix compilation of 32 bit target
+// on MSVC with /Wp64 flag enabled.
+
+// The original code can be found here:
+// http://src.chromium.org/svn/trunk/src/base/fix_wp64.h
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
+
+#include <windows.h>
+
+// Platform SDK fixes when building with /Wp64 for a 32 bits target.
+#if !defined(_WIN64) && defined(_Wp64)
+
+#ifdef InterlockedExchangePointer
+#undef InterlockedExchangePointer
+// The problem is that the macro provided for InterlockedExchangePointer() is
+// doing a (LONG) C-style cast that triggers invariably the warning C4312 when
+// building on 32 bits.
+inline void* InterlockedExchangePointer(void* volatile* target, void* value) {
+ return reinterpret_cast<void*>(static_cast<LONG_PTR>(InterlockedExchange(
+ reinterpret_cast<volatile LONG*>(target),
+ static_cast<LONG>(reinterpret_cast<LONG_PTR>(value)))));
+}
+#endif // #ifdef InterlockedExchangePointer
+
+#endif // #if !defined(_WIN64) && defined(_Wp64)
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
diff --git a/src/system_wrappers/interface/ref_count.h b/src/system_wrappers/interface/ref_count.h
index f90b0b3..5112bd9 100644
--- a/src/system_wrappers/interface/ref_count.h
+++ b/src/system_wrappers/interface/ref_count.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -11,7 +11,7 @@
#ifndef SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
#define SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
-#include "system_wrappers/interface/atomic32_wrapper.h"
+#include "system_wrappers/interface/atomic32.h"
namespace webrtc {
@@ -74,7 +74,7 @@
}
protected:
- Atomic32Wrapper ref_count_;
+ Atomic32 ref_count_;
};
} // namespace webrtc
diff --git a/src/system_wrappers/interface/sleep.h b/src/system_wrappers/interface/sleep.h
new file mode 100644
index 0000000..c0205bf
--- /dev/null
+++ b/src/system_wrappers/interface/sleep.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+// An OS-independent sleep function.
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
+
+namespace webrtc {
+
+// This function sleeps for the specified number of milliseconds.
+// It may return early if the thread is woken by some other event,
+// such as the delivery of a signal on Unix.
+void SleepMs(int msecs);
+
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
diff --git a/src/system_wrappers/interface/static_instance.h b/src/system_wrappers/interface/static_instance.h
index 8fe91cc..b670f96 100644
--- a/src/system_wrappers/interface/static_instance.h
+++ b/src/system_wrappers/interface/static_instance.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -128,10 +128,8 @@
// local copy.
T* new_instance = T::CreateInstance();
if (1 == InterlockedIncrement(&instance_count)) {
- T* old_value = static_cast<T*> (InterlockedExchangePointer(
- reinterpret_cast<void* volatile*>(&instance), new_instance));
- assert(old_value == NULL);
- assert(instance);
+ InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&instance),
+ new_instance);
} else {
InterlockedDecrement(&instance_count);
if (new_instance) {
diff --git a/src/system_wrappers/interface/thread_wrapper.h b/src/system_wrappers/interface/thread_wrapper.h
index 72a06e8..030ac8a 100644
--- a/src/system_wrappers/interface/thread_wrapper.h
+++ b/src/system_wrappers/interface/thread_wrapper.h
@@ -16,6 +16,9 @@
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
+#include "common_types.h"
+#include "typedefs.h"
+
namespace webrtc {
// Object that will be passed by the spawned thread when it enters the callback
// function.
@@ -51,9 +54,12 @@
// threadName NULL terminated thread name, will be visable in the Windows
// debugger.
static ThreadWrapper* CreateThread(ThreadRunFunction func = 0,
- ThreadObj obj= 0,
- ThreadPriority prio = kNormalPriority,
- const char* threadName = 0);
+ ThreadObj obj= 0,
+ ThreadPriority prio = kNormalPriority,
+ const char* threadName = 0);
+
+ // Get the current thread's kernel thread ID.
+ static uint32_t GetThreadId();
// Non blocking termination of the spawned thread. Note that it is not safe
// to delete this class until the spawned thread has been reclaimed.
@@ -69,8 +75,9 @@
// should be lower than (number of CPUs - 1). amountOfProcessors should be
// equal to the number of processors listed in processorNumbers
virtual bool SetAffinity(const int* /*processorNumbers*/,
- const unsigned int /*amountOfProcessors*/)
- {return false;}
+ const unsigned int /*amountOfProcessors*/) {
+ return false;
+ }
// Stops the spawned thread and waits for it to be reclaimed with a timeout
// of two seconds. Will return false if the thread was not reclaimed.
diff --git a/src/system_wrappers/interface/tick_util.h b/src/system_wrappers/interface/tick_util.h
index e78e53d..0cd85d0 100644
--- a/src/system_wrappers/interface/tick_util.h
+++ b/src/system_wrappers/interface/tick_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -19,6 +19,9 @@
#include <mmsystem.h>
#elif WEBRTC_LINUX
#include <ctime>
+#elif WEBRTC_MAC
+#include <mach/mach_time.h>
+#include <string.h>
#else
#include <sys/time.h>
#include <time.h>
@@ -133,6 +136,7 @@
{
TickTime result;
#if _WIN32
+ // TODO(wu): Remove QueryPerformanceCounter implementation.
#ifdef USE_QUERY_PERFORMANCE_COUNTER
// QueryPerformanceCounter returns the value from the TSC which is
// incremented at the CPU frequency. The algorithm used requires
@@ -164,12 +168,27 @@
#endif
#elif defined(WEBRTC_LINUX)
struct timespec ts;
+ // TODO(wu): Remove CLOCK_REALTIME implementation.
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
clock_gettime(CLOCK_REALTIME, &ts);
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
+#elif defined(WEBRTC_MAC)
+ static mach_timebase_info_data_t timebase;
+ if (timebase.denom == 0) {
+ // Get the timebase if this is the first time we run.
+ // Recommended by Apple's QA1398.
+ kern_return_t retval = mach_timebase_info(&timebase);
+ if (retval != KERN_SUCCESS) {
+ // TODO(wu): Implement CHECK similar to chrome for all the platforms.
+ // Then replace this with a CHECK(retval == KERN_SUCCESS);
+ asm("int3");
+ }
+ }
+ // Use timebase to convert absolute time tick units into nanoseconds.
+ result._ticks = mach_absolute_time() * timebase.numer / timebase.denom;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -189,7 +208,7 @@
#else
return now._ticks;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return now._ticks / 1000000LL;
#else
return now._ticks / 1000LL;
@@ -208,7 +227,7 @@
#else
return now._ticks *1000LL;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return now._ticks / 1000LL;
#else
return now._ticks;
@@ -230,7 +249,7 @@
#else
return ms;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return ms * 1000000LL;
#else
return ms * 1000LL;
@@ -247,7 +266,7 @@
#else
return ticks;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return ticks / 1000000LL;
#else
return ticks / 1000LL;
@@ -280,7 +299,7 @@
// _interval is in ms
return _interval;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
// _interval is in ns
return _interval / 1000000;
#else
@@ -300,7 +319,7 @@
// _interval is in ms
return _interval *1000LL;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
// _interval is in ns
return _interval / 1000;
#else
diff --git a/src/system_wrappers/interface/trace.h b/src/system_wrappers/interface/trace.h
index 8330f7c..f88d23f 100644
--- a/src/system_wrappers/interface/trace.h
+++ b/src/system_wrappers/interface/trace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -45,11 +45,11 @@
// Sets the file name. If addFileCounter is false the same file will be
// reused when it fills up. If it's true a new file with incremented name
// will be used.
- static WebRtc_Word32 SetTraceFile(const WebRtc_Word8* fileName,
+ static WebRtc_Word32 SetTraceFile(const char* fileName,
const bool addFileCounter = false);
// Returns the name of the file that the trace is currently writing to.
- static WebRtc_Word32 TraceFile(WebRtc_Word8 fileName[1024]);
+ static WebRtc_Word32 TraceFile(char fileName[1024]);
// Registers callback to receive trace messages. TODO (hellner)
// why not use OutStream instead? Why is TraceCallback not defined in this
@@ -70,7 +70,6 @@
const TraceModule module,
const WebRtc_Word32 id,
const char* msg, ...);
-
};
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
diff --git a/src/system_wrappers/source/Android.mk b/src/system_wrappers/source/Android.mk
index 575580a..dee84ca 100644
--- a/src/system_wrappers/source/Android.mk
+++ b/src/system_wrappers/source/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+# 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
@@ -17,15 +17,15 @@
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
+ android/cpu-features.c \
+ cpu_features_android.c \
map.cc \
- rw_lock_generic.cc \
sort.cc \
aligned_malloc.cc \
- atomic32.cc \
+ atomic32_posix.cc \
condition_variable.cc \
cpu_no_op.cc \
cpu_features.cc \
- cpu_features_arm.c \
cpu_info.cc \
critical_section.cc \
event.cc \
@@ -38,6 +38,7 @@
cpu_linux.cc \
critical_section_posix.cc \
event_posix.cc \
+ sleep.cc \
thread_posix.cc \
trace_posix.cc \
rw_lock_posix.cc
diff --git a/src/system_wrappers/source/android/cpu-features.c b/src/system_wrappers/source/android/cpu-features.c
new file mode 100644
index 0000000..6a5cd8f
--- /dev/null
+++ b/src/system_wrappers/source/android/cpu-features.c
@@ -0,0 +1,396 @@
+/*
+ * 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 <sys/system_properties.h>
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+#include <pthread.h>
+#include "cpu-features.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static pthread_once_t g_once;
+static AndroidCpuFamily g_cpuFamily;
+static uint64_t g_cpuFeatures;
+static int g_cpuCount;
+
+static const int android_cpufeatures_debug = 0;
+
+#ifdef __arm__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM
+#elif defined __i386__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86
+#else
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN
+#endif
+
+#define D(...) \
+ do { \
+ if (android_cpufeatures_debug) { \
+ printf(__VA_ARGS__); fflush(stdout); \
+ } \
+ } while (0)
+
+#ifdef __i386__
+static __inline__ void x86_cpuid(int func, int values[4])
+{
+ int a, b, c, d;
+ /* We need to preserve ebx since we're compiling PIC code */
+ /* this means we can't use "=b" for the second output register */
+ __asm__ __volatile__ ( \
+ "push %%ebx\n"
+ "cpuid\n" \
+ "mov %1, %%ebx\n"
+ "pop %%ebx\n"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "a" (func) \
+ );
+ values[0] = a;
+ values[1] = b;
+ values[2] = c;
+ values[3] = d;
+}
+#endif
+
+/* Read the content of /proc/cpuinfo into a user-provided buffer.
+ * Return the length of the data, or -1 on error. Does *not*
+ * zero-terminate the content. Will not read more
+ * than 'buffsize' bytes.
+ */
+static int
+read_file(const char* pathname, char* buffer, size_t buffsize)
+{
+ int fd, len;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ do {
+ len = read(fd, buffer, buffsize);
+ } while (len < 0 && errno == EINTR);
+
+ close(fd);
+
+ return len;
+}
+
+/* Extract the content of a the first occurence of a given field in
+ * the content of /proc/cpuinfo and return it as a heap-allocated
+ * string that must be freed by the caller.
+ *
+ * Return NULL if not found
+ */
+static char*
+extract_cpuinfo_field(char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ char* bufend = buffer + buflen;
+ char* result = NULL;
+ int len, ignore;
+ const char *p, *q;
+
+ /* Look for first field occurence, and ensures it starts the line.
+ */
+ p = buffer;
+ bufend = buffer + buflen;
+ for (;;) {
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ goto EXIT;
+
+ if (p == buffer || p[-1] == '\n')
+ break;
+
+ p += fieldlen;
+ }
+
+ /* Skip to the first column followed by a space */
+ p += fieldlen;
+ p = memchr(p, ':', bufend-p);
+ if (p == NULL || p[1] != ' ')
+ goto EXIT;
+
+ /* Find the end of the line */
+ p += 2;
+ q = memchr(p, '\n', bufend-p);
+ if (q == NULL)
+ q = bufend;
+
+ /* Copy the line into a heap-allocated buffer */
+ len = q-p;
+ result = malloc(len+1);
+ if (result == NULL)
+ goto EXIT;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+EXIT:
+ return result;
+}
+
+/* Count the number of occurences of a given field prefix in /proc/cpuinfo.
+ */
+static int
+count_cpuinfo_field(char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ const char* p = buffer;
+ const char* bufend = buffer + buflen;
+ const char* q;
+ int count = 0;
+
+ for (;;) {
+ const char* q;
+
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ break;
+
+ /* Ensure that the field is at the start of a line */
+ if (p > buffer && p[-1] != '\n') {
+ p += fieldlen;
+ continue;
+ }
+
+
+ /* skip any whitespace */
+ q = p + fieldlen;
+ while (q < bufend && (*q == ' ' || *q == '\t'))
+ q++;
+
+ /* we must have a colon now */
+ if (q < bufend && *q == ':') {
+ count += 1;
+ q ++;
+ }
+ p = q;
+ }
+
+ return count;
+}
+
+/* Like strlen(), but for constant string literals */
+#define STRLEN_CONST(x) ((sizeof(x)-1)
+
+
+/* Checks that a space-separated list of items contains one given 'item'.
+ * Returns 1 if found, 0 otherwise.
+ */
+static int
+has_list_item(const char* list, const char* item)
+{
+ const char* p = list;
+ int itemlen = strlen(item);
+
+ if (list == NULL)
+ return 0;
+
+ while (*p) {
+ const char* q;
+
+ /* skip spaces */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* find end of current list item */
+ q = p;
+ while (*q && *q != ' ' && *q != '\t')
+ q++;
+
+ if (itemlen == q-p && !memcmp(p, item, itemlen))
+ return 1;
+
+ /* skip to next item */
+ p = q;
+ }
+ return 0;
+}
+
+
+static void
+android_cpuInit(void)
+{
+ char cpuinfo[4096];
+ int cpuinfo_len;
+
+ g_cpuFamily = DEFAULT_CPU_FAMILY;
+ g_cpuFeatures = 0;
+ g_cpuCount = 1;
+
+ cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo);
+ D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
+ cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
+
+ if (cpuinfo_len < 0) /* should not happen */ {
+ return;
+ }
+
+ /* Count the CPU cores, the value may be 0 for single-core CPUs */
+ g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor");
+ if (g_cpuCount == 0) {
+ g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor");
+ if (g_cpuCount == 0) {
+ g_cpuCount = 1;
+ }
+ }
+
+ D("found cpuCount = %d\n", g_cpuCount);
+
+#ifdef __ARM_ARCH__
+ {
+ char* features = NULL;
+ char* architecture = NULL;
+
+ /* Extract architecture from the "CPU Architecture" field.
+ * The list is well-known, unlike the the output of
+ * the 'Processor' field which can vary greatly.
+ *
+ * See the definition of the 'proc_arch' array in
+ * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
+ * same file.
+ */
+ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+
+ if (cpuArch != NULL) {
+ char* end;
+ long archNumber;
+ int hasARMv7 = 0;
+
+ D("found cpuArch = '%s'\n", cpuArch);
+
+ /* read the initial decimal number, ignore the rest */
+ archNumber = strtol(cpuArch, &end, 10);
+
+ /* Here we assume that ARMv8 will be upwards compatible with v7
+ * in the future. Unfortunately, there is no 'Features' field to
+ * indicate that Thumb-2 is supported.
+ */
+ if (end > cpuArch && archNumber >= 7) {
+ hasARMv7 = 1;
+ }
+
+ /* Unfortunately, it seems that certain ARMv6-based CPUs
+ * report an incorrect architecture number of 7!
+ *
+ * See http://code.google.com/p/android/issues/detail?id=10812
+ *
+ * We try to correct this by looking at the 'elf_format'
+ * field reported by the 'Processor' field, which is of the
+ * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+ * an ARMv6-one.
+ */
+ if (hasARMv7) {
+ char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
+ "Processor");
+ if (cpuProc != NULL) {
+ D("found cpuProc = '%s'\n", cpuProc);
+ if (has_list_item(cpuProc, "(v6l)")) {
+ D("CPU processor and architecture mismatch!!\n");
+ hasARMv7 = 0;
+ }
+ free(cpuProc);
+ }
+ }
+
+ if (hasARMv7) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
+ }
+
+ /* The LDREX / STREX instructions are available from ARMv6 */
+ if (archNumber >= 6) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
+ }
+
+ free(cpuArch);
+ }
+
+ /* Extract the list of CPU features from 'Features' field */
+ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+
+ if (cpuFeatures != NULL) {
+
+ D("found cpuFeatures = '%s'\n", cpuFeatures);
+
+ if (has_list_item(cpuFeatures, "vfpv3"))
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ else if (has_list_item(cpuFeatures, "vfpv3d16"))
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ if (has_list_item(cpuFeatures, "neon")) {
+ /* Note: Certain kernels only report neon but not vfpv3
+ * in their features list. However, ARM mandates
+ * that if Neon is implemented, so must be VFPv3
+ * so always set the flag.
+ */
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON |
+ ANDROID_CPU_ARM_FEATURE_VFPv3;
+ }
+ free(cpuFeatures);
+ }
+ }
+#endif /* __ARM_ARCH__ */
+
+#ifdef __i386__
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86;
+
+ int regs[4];
+
+/* According to http://en.wikipedia.org/wiki/CPUID */
+#define VENDOR_INTEL_b 0x756e6547
+#define VENDOR_INTEL_c 0x6c65746e
+#define VENDOR_INTEL_d 0x49656e69
+
+ x86_cpuid(0, regs);
+ int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
+ regs[2] == VENDOR_INTEL_c &&
+ regs[3] == VENDOR_INTEL_d);
+
+ x86_cpuid(1, regs);
+ if ((regs[2] & (1 << 9)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
+ }
+ if ((regs[2] & (1 << 23)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
+ }
+ if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
+ }
+#endif
+}
+
+
+AndroidCpuFamily
+android_getCpuFamily(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFamily;
+}
+
+
+uint64_t
+android_getCpuFeatures(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFeatures;
+}
+
+
+int
+android_getCpuCount(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuCount;
+}
diff --git a/src/system_wrappers/source/android/cpu-features.h b/src/system_wrappers/source/android/cpu-features.h
new file mode 100644
index 0000000..f20c0bc
--- /dev/null
+++ b/src/system_wrappers/source/android/cpu-features.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+// You can download Android source at
+// http://source.android.com/source/downloading.html
+// Original files are in ndk/sources/android/cpufeatures
+// Revision is Change-Id: I9a0629efba36a6023f05e5f092e7addcc1b7d2a9
+
+#ifndef CPU_FEATURES_H
+#define CPU_FEATURES_H
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+typedef enum {
+ ANDROID_CPU_FAMILY_UNKNOWN = 0,
+ ANDROID_CPU_FAMILY_ARM,
+ ANDROID_CPU_FAMILY_X86,
+
+ ANDROID_CPU_FAMILY_MAX /* do not remove */
+
+} AndroidCpuFamily;
+
+/* Return family of the device's CPU */
+extern AndroidCpuFamily android_getCpuFamily(void);
+
+enum {
+ ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
+ ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
+ ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
+ ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
+};
+
+enum {
+ ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
+ ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
+ ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
+};
+
+extern uint64_t android_getCpuFeatures(void);
+
+/* Return the number of CPU cores detected on this device. */
+extern int android_getCpuCount(void);
+
+__END_DECLS
+
+#endif /* CPU_FEATURES_H */
diff --git a/src/system_wrappers/source/atomic32.cc b/src/system_wrappers/source/atomic32.cc
deleted file mode 100644
index 588dd3e..0000000
--- a/src/system_wrappers/source/atomic32.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 "atomic32_wrapper.h"
-
-#if defined(_WIN32)
- #include "atomic32_win.h"
-#elif defined(WEBRTC_LINUX)
- #include "atomic32_linux.h"
-#elif defined(WEBRTC_MAC)
- #include "atomic32_mac.h"
-#else
- #error unsupported os!
-#endif
-
-namespace webrtc {
-Atomic32Wrapper::Atomic32Wrapper(WebRtc_Word32 initialValue)
- : _impl(*new Atomic32Impl(initialValue))
-{
-}
-
-Atomic32Wrapper::~Atomic32Wrapper()
-{
- delete &_impl;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator++()
-{
- return ++_impl;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator--()
-{
- return --_impl;
-}
-
-// Read and write to properly aligned variables are atomic operations.
-// Ex reference (for Windows): http://msdn.microsoft.com/en-us/library/ms684122(v=VS.85).aspx
-// TODO (hellner) operator= and Atomic32Wrapper::Value() can be fully
-// implemented here.
-Atomic32Wrapper& Atomic32Wrapper::operator=(const Atomic32Wrapper& rhs)
-{
- if(this == &rhs)
- {
- return *this;
- }
- _impl = rhs._impl;
- return *this;
-}
-
-Atomic32Wrapper& Atomic32Wrapper::operator=(WebRtc_Word32 rhs)
-{
- _impl = rhs;
- return *this;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator+=(WebRtc_Word32 rhs)
-{
- return _impl += rhs;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator-=(WebRtc_Word32 rhs)
-{
- return _impl -= rhs;
-}
-
-bool Atomic32Wrapper::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return _impl.CompareExchange(newValue,compareValue);
-}
-
-WebRtc_Word32 Atomic32Wrapper::Value() const
-{
- return _impl.Value();
-}
-} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_linux.h b/src/system_wrappers/source/atomic32_linux.h
deleted file mode 100644
index f9f5650..0000000
--- a/src/system_wrappers/source/atomic32_linux.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit signed integer.
-// Linux implementation.
-// Note: Requires gcc 4.1.2 or later.
-#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
-#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
-
-#include <inttypes.h>
-#include <malloc.h>
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl
-{
-public:
- inline Atomic32Impl(WebRtc_Word32 initialValue);
- inline ~Atomic32Impl();
-
- inline WebRtc_Word32 operator++();
- inline WebRtc_Word32 operator--();
-
- inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
- inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- inline bool CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue);
-
- inline WebRtc_Word32 Value() const;
-private:
- void* _ptrMemory;
- // Volatile ensures full memory barriers.
- volatile WebRtc_Word32* _value;
-};
-
-// TODO (hellner) use aligned_malloc instead of doing it manually.
-inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
- : _ptrMemory(NULL),
- _value(NULL)
-{ // Align the memory associated with _value on a 32-bit boundary. This is a
- // requirement for the used Linux APIs to be atomic.
- // Keep _ptrMemory to be able to reclaim memory.
- _ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
- _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
- *_value = initialValue;
-}
-
-inline Atomic32Impl::~Atomic32Impl()
-{
- if(_ptrMemory != NULL)
- {
- free(_ptrMemory);
- }
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator++()
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,1);
- returnValue++;
- return returnValue;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator--()
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,1);
- returnValue--;
- return returnValue;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
-{
- *_value = *rhs._value;
- return *this;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
-{
- *_value = rhs;
- return *this;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,rhs);
- returnValue += rhs;
- return returnValue;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,rhs);
- returnValue -= rhs;
- return returnValue;
-}
-
-inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return __sync_bool_compare_and_swap(_value,compareValue,newValue);
-}
-
-inline WebRtc_Word32 Atomic32Impl::Value() const
-{
- return *_value;
-}
-} // namespace webrtc
-
-#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
diff --git a/src/system_wrappers/source/atomic32_mac.cc b/src/system_wrappers/source/atomic32_mac.cc
new file mode 100644
index 0000000..9a493b5
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_mac.cc
@@ -0,0 +1,60 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <libkern/OSAtomic.h>
+#include <stdlib.h>
+
+#include "common_types.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return OSAtomicIncrement32Barrier(&_value);
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return OSAtomicDecrement32Barrier(&_value);
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ return OSAtomicAdd32Barrier(value, &_value);
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ return OSAtomicAdd32Barrier(-value, &_value);
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ return OSAtomicCompareAndSwap32Barrier(compareValue, newValue, &_value);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_mac.h b/src/system_wrappers/source/atomic32_mac.h
deleted file mode 100644
index bf8febc..0000000
--- a/src/system_wrappers/source/atomic32_mac.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit signed integer.
-// Mac implementation.
-#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
-#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
-
-#include <stdlib.h>
-#include <libkern/OSAtomic.h>
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl
-{
-public:
- inline Atomic32Impl(WebRtc_Word32 initialValue);
- inline ~Atomic32Impl();
-
- inline WebRtc_Word32 operator++();
- inline WebRtc_Word32 operator--();
-
- inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
- inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- inline bool CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue);
-
- inline WebRtc_Word32 Value() const;
-private:
- void* _ptrMemory;
- // Volatile ensures full memory barriers.
- volatile WebRtc_Word32* _value;
-};
-
-// TODO (hellner) use aligned_malloc instead of doing it manually.
-inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
- :
- _ptrMemory(NULL),
- _value(NULL)
-{ // Align the memory associated with _value on a 32-bit boundary. This is a
- // requirement for the used Mac APIs to be atomic.
- // Keep _ptrMemory to be able to reclaim memory.
- _ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
- _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
- *_value = initialValue;
-}
-
-inline Atomic32Impl::~Atomic32Impl()
-{
- if(_ptrMemory != NULL)
- {
- free(_ptrMemory);
- }
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator++()
-{
- return OSAtomicIncrement32Barrier(
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator--()
-{
- return OSAtomicDecrement32Barrier(
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
-{
- *_value = *rhs._value;
- return *this;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
-{
- *_value = rhs;
- return *this;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
-{
- return OSAtomicAdd32Barrier(rhs,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
-{
- return OSAtomicAdd32Barrier(-rhs,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return OSAtomicCompareAndSwap32Barrier(
- compareValue,
- newValue,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::Value() const
-{
- return *_value;
-}
-} // namespace webrtc
-#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
diff --git a/src/system_wrappers/source/atomic32_posix.cc b/src/system_wrappers/source/atomic32_posix.cc
new file mode 100644
index 0000000..05b0e57
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_posix.cc
@@ -0,0 +1,64 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <malloc.h>
+
+#include "common_types.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return __sync_fetch_and_add(&_value, 1) + 1;
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return __sync_fetch_and_sub(&_value, 1) - 1;
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ WebRtc_Word32 returnValue = __sync_fetch_and_add(&_value, value);
+ returnValue += value;
+ return returnValue;
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ WebRtc_Word32 returnValue = __sync_fetch_and_sub(&_value, value);
+ returnValue -= value;
+ return returnValue;
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ return __sync_bool_compare_and_swap(&_value, compareValue, newValue);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_win.cc b/src/system_wrappers/source/atomic32_win.cc
new file mode 100644
index 0000000..2fa9d3d
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_win.cc
@@ -0,0 +1,72 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <windows.h>
+
+#include "common_types.h"
+#include "compile_assert.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ // Make sure that the counter variable we're using is of the same size
+ // as what the API expects.
+ COMPILE_ASSERT(sizeof(_value) == sizeof(LONG));
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return static_cast<WebRtc_Word32>(InterlockedIncrement(
+ reinterpret_cast<volatile LONG*>(&_value)));
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return static_cast<WebRtc_Word32>(InterlockedDecrement(
+ reinterpret_cast<volatile LONG*>(&_value)));
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&_value),
+ value);
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&_value),
+ -value);
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ const LONG oldValue = InterlockedCompareExchange(
+ reinterpret_cast<volatile LONG*>(&_value),
+ newValue,
+ compareValue);
+ // If the old value and the compare value is the same an exchange happened.
+ return (oldValue == compareValue);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_unittest.cc b/src/system_wrappers/source/condition_variable_unittest.cc
new file mode 100644
index 0000000..a9fdd0d
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_unittest.cc
@@ -0,0 +1,208 @@
+/*
+ * 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 "system_wrappers/interface/condition_variable_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/critical_section_wrapper.h"
+#include "system_wrappers/interface/thread_wrapper.h"
+#include "system_wrappers/interface/trace.h"
+#include "system_wrappers/source/unittest_utilities.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kLogTrace = false; // Set to true to enable debug logging to stdout.
+const int kLongWaitMs = 100*1000; // A long time in testing terms
+const int kShortWaitMs = 2*1000; // Long enough for process switches to happen
+
+#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
+
+// A Baton is one possible control structure one can build using
+// conditional variables.
+// A Baton is always held by one and only one active thread - unlike
+// a lock, it can never be free.
+// One can pass it or grab it - both calls have timeouts.
+// Note - a production tool would guard against passing it without
+// grabbing it first. This one is for testing, so it doesn't.
+class Baton {
+ public:
+ Baton()
+ : giver_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+ crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+ cond_var_(ConditionVariableWrapper::CreateConditionVariable()),
+ being_passed_(false),
+ pass_count_(0) {
+ }
+
+ ~Baton() {
+ delete giver_sect_;
+ delete crit_sect_;
+ delete cond_var_;
+ }
+
+ // Pass the baton. Returns false if baton is not picked up in |max_msecs|.
+ // Only one process can pass at the same time; this property is
+ // ensured by the |giver_sect_| lock.
+ bool Pass(WebRtc_UWord32 max_msecs) {
+ LOG("Locking giver_sect");
+ CriticalSectionScoped cs_giver(giver_sect_);
+ LOG("Locked giver_sect, locking crit_sect");
+ CriticalSectionScoped cs(crit_sect_);
+ SignalBatonAvailable();
+ const bool result = TakeBatonIfStillFree(max_msecs);
+ if (result) {
+ ++pass_count_;
+ LOG("Pass count is %d", pass_count_);
+ }
+ return result;
+ }
+
+ // Grab the baton. Returns false if baton is not passed.
+ bool Grab(WebRtc_UWord32 max_msecs) {
+ CriticalSectionScoped cs(crit_sect_);
+ return WaitUntilBatonOffered(max_msecs);
+ }
+
+ int PassCount() {
+ // We don't allow polling PassCount() during a Pass()-call since there is
+ // no guarantee that |pass_count_| is incremented until the Pass()-call
+ // finishes. I.e. the Grab()-call may finish before |pass_count_| has been
+ // incremented.
+ // Thus, this function waits on giver_sect_.
+ CriticalSectionScoped cs(giver_sect_);
+ return pass_count_;
+ }
+
+ private:
+ // Wait/Signal forms a classical semaphore on |being_passed_|.
+ // These functions must be called with crit_sect_ held.
+ bool WaitUntilBatonOffered(int timeout_ms) {
+ while (!being_passed_) {
+ LOG("Wait waiting");
+ if (!cond_var_->SleepCS(*crit_sect_, timeout_ms)) {
+ LOG("Wait timeout");
+ return false;
+ }
+ }
+ being_passed_ = false;
+ cond_var_->Wake();
+ return true;
+ }
+
+ void SignalBatonAvailable() {
+ assert(!being_passed_);
+ being_passed_ = true;
+ LOG("Signal waking");
+ cond_var_->Wake();
+ }
+
+ // Timeout extension: Wait for a limited time for someone else to
+ // take it, and take it if it's not taken.
+ // Returns true if resource is taken by someone else, false
+ // if it is taken back by the caller.
+ // This function must be called with both |giver_sect_| and
+ // |crit_sect_| held.
+ bool TakeBatonIfStillFree(int timeout_ms) {
+ bool not_timeout = true;
+ while (being_passed_ && not_timeout) {
+ LOG("Takeback waiting");
+ not_timeout = cond_var_->SleepCS(*crit_sect_, timeout_ms);
+ // If we're woken up while variable is still held, we may have
+ // gotten a wakeup destined for a grabber thread.
+ // This situation is not treated specially here.
+ }
+ if (!being_passed_) {
+ return true;
+ } else {
+ LOG("Takeback grab");
+ assert(!not_timeout);
+ being_passed_ = false;
+ return false;
+ }
+ }
+
+ // Lock that ensures that there is only one thread in the active
+ // part of Pass() at a time.
+ // |giver_sect_| must always be acquired before |cond_var_|.
+ CriticalSectionWrapper* giver_sect_;
+ // Lock that protects |being_passed_|.
+ CriticalSectionWrapper* crit_sect_;
+ ConditionVariableWrapper* cond_var_;
+ bool being_passed_;
+ // Statistics information: Number of successfull passes.
+ int pass_count_;
+};
+
+// Function that waits on a Baton, and passes it right back.
+// We expect these calls never to time out.
+bool WaitingRunFunction(void* obj) {
+ Baton* the_baton = static_cast<Baton*> (obj);
+ LOG("Thread waiting");
+ EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
+ LOG("Thread waking parent");
+ EXPECT_TRUE(the_baton->Pass(kLongWaitMs));
+ return true;
+}
+
+class CondVarTest : public ::testing::Test {
+ public:
+ CondVarTest()
+ : trace_(kLogTrace) {
+ }
+
+ virtual void SetUp() {
+ thread_ = ThreadWrapper::CreateThread(&WaitingRunFunction,
+ &baton_);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread_->Start(id));
+ }
+
+ virtual void TearDown() {
+ // We have to wake the thread in order to make it obey the stop order.
+ // But we don't know if the thread has completed the run function, so
+ // we don't know if it will exit before or after the Pass.
+ // Thus, we need to pin it down inside its Run function (between Grab
+ // and Pass).
+ ASSERT_TRUE(baton_.Pass(kShortWaitMs));
+ thread_->SetNotAlive();
+ ASSERT_TRUE(baton_.Grab(kShortWaitMs));
+ ASSERT_TRUE(thread_->Stop());
+ delete thread_;
+ }
+
+ protected:
+ Baton baton_;
+
+ private:
+ ScopedTracing trace_;
+ ThreadWrapper* thread_;
+};
+
+// The SetUp and TearDown functions use condition variables.
+// This test verifies those pieces in isolation.
+TEST_F(CondVarTest, InitFunctionsWork) {
+ // All relevant asserts are in the SetUp and TearDown functions.
+}
+
+// This test verifies that one can use the baton multiple times.
+TEST_F(CondVarTest, PassBatonMultipleTimes) {
+ const int kNumberOfRounds = 2;
+ for (int i = 0; i < kNumberOfRounds; ++i) {
+ ASSERT_TRUE(baton_.Pass(kShortWaitMs));
+ ASSERT_TRUE(baton_.Grab(kShortWaitMs));
+ }
+ EXPECT_EQ(2*kNumberOfRounds, baton_.PassCount());
+}
+
+} // anonymous namespace
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_win.cc b/src/system_wrappers/source/condition_variable_win.cc
new file mode 100644
index 0000000..f4fae0b
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_win.cc
@@ -0,0 +1,224 @@
+/*
+ * Use of this source code is governed by the ACE copyright license which
+ * can be found in the LICENSE file in the third_party_mods/ace directory of
+ * the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html.
+ */
+/*
+ * This source code contain modifications to the original source code
+ * which can be found here:
+ * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
+ * Modifications:
+ * 1) Dynamic detection of native support for condition variables.
+ * 2) Use of WebRTC defined types and classes. Renaming of some functions.
+ * 3) Introduction of a second event for wake all functionality. This prevents
+ * a thread from spinning on the same condition variable, preventing other
+ * threads from waking up.
+ */
+
+// TODO (hellner): probably nicer to split up native and generic
+// implementation into two different files
+
+#include "condition_variable_win.h"
+
+#include "critical_section_win.h"
+#include "trace.h"
+
+namespace webrtc {
+bool ConditionVariableWindows::_winSupportConditionVariablesPrimitive = false;
+static HMODULE library = NULL;
+
+PInitializeConditionVariable _PInitializeConditionVariable;
+PSleepConditionVariableCS _PSleepConditionVariableCS;
+PWakeConditionVariable _PWakeConditionVariable;
+PWakeAllConditionVariable _PWakeAllConditionVariable;
+
+typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
+typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
+ PCRITICAL_SECTION, DWORD);
+typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
+typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
+
+ConditionVariableWindows::ConditionVariableWindows()
+ : _eventID(WAKEALL_0)
+{
+ if (!library)
+ {
+ // Use native implementation if supported (i.e Vista+)
+ library = LoadLibrary(TEXT("Kernel32.dll"));
+ if (library)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Kernel.dll");
+
+ _PInitializeConditionVariable =
+ (PInitializeConditionVariable) GetProcAddress(
+ library,
+ "InitializeConditionVariable");
+ _PSleepConditionVariableCS =
+ (PSleepConditionVariableCS)GetProcAddress(
+ library,
+ "SleepConditionVariableCS");
+ _PWakeConditionVariable =
+ (PWakeConditionVariable)GetProcAddress(
+ library,
+ "WakeConditionVariable");
+ _PWakeAllConditionVariable =
+ (PWakeAllConditionVariable)GetProcAddress(
+ library,
+ "WakeAllConditionVariable");
+
+ if(_PInitializeConditionVariable &&
+ _PSleepConditionVariableCS &&
+ _PWakeConditionVariable &&
+ _PWakeAllConditionVariable)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded native condition variables");
+ _winSupportConditionVariablesPrimitive = true;
+ }
+ }
+ }
+
+ if (_winSupportConditionVariablesPrimitive)
+ {
+ _PInitializeConditionVariable(&_conditionVariable);
+
+ _events[WAKEALL_0] = NULL;
+ _events[WAKEALL_1] = NULL;
+ _events[WAKE] = NULL;
+
+ } else {
+ memset(&_numWaiters[0],0,sizeof(_numWaiters));
+
+ InitializeCriticalSection(&_numWaitersCritSect);
+
+ _events[WAKEALL_0] = CreateEvent(NULL, // no security attributes
+ TRUE, // manual-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+
+ _events[WAKEALL_1] = CreateEvent(NULL, // no security attributes
+ TRUE, // manual-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+
+ _events[WAKE] = CreateEvent(NULL, // no security attributes
+ FALSE, // auto-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+ }
+}
+
+ConditionVariableWindows::~ConditionVariableWindows()
+{
+ if(!_winSupportConditionVariablesPrimitive)
+ {
+ CloseHandle(_events[WAKE]);
+ CloseHandle(_events[WAKEALL_1]);
+ CloseHandle(_events[WAKEALL_0]);
+
+ DeleteCriticalSection(&_numWaitersCritSect);
+ }
+}
+
+void ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect)
+{
+ SleepCS(critSect, INFINITE);
+}
+
+bool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect,
+ unsigned long maxTimeInMS)
+{
+ CriticalSectionWindows* cs = reinterpret_cast<CriticalSectionWindows*>(
+ &critSect);
+
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ BOOL retVal = _PSleepConditionVariableCS(&_conditionVariable,
+ &(cs->crit),maxTimeInMS);
+ return (retVal == 0) ? false : true;
+
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ // Get the eventID for the event that will be triggered by next
+ // WakeAll() call and start waiting for it.
+ const EventWakeUpType eventID = (WAKEALL_0 == _eventID) ?
+ WAKEALL_1 : WAKEALL_0;
+ ++(_numWaiters[eventID]);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ LeaveCriticalSection(&cs->crit);
+ HANDLE events[2];
+ events[0] = _events[WAKE];
+ events[1] = _events[eventID];
+ const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
+ events,
+ FALSE, // Wait for either.
+ maxTimeInMS);
+
+ const bool retVal = (result != WAIT_TIMEOUT);
+
+ EnterCriticalSection(&_numWaitersCritSect);
+ --(_numWaiters[eventID]);
+ // Last waiter should only be true for WakeAll(). WakeAll() correspond
+ // to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
+ const bool lastWaiter = (result == WAIT_OBJECT_0 + 1) &&
+ (_numWaiters[eventID] == 0);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (lastWaiter)
+ {
+ // Reset/unset the WakeAll() event since all threads have been
+ // released.
+ ResetEvent(_events[eventID]);
+ }
+
+ EnterCriticalSection(&cs->crit);
+ return retVal;
+ }
+}
+
+void
+ConditionVariableWindows::Wake()
+{
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ _PWakeConditionVariable(&_conditionVariable);
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ const bool haveWaiters = (_numWaiters[WAKEALL_0] > 0) ||
+ (_numWaiters[WAKEALL_1] > 0);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (haveWaiters)
+ {
+ SetEvent(_events[WAKE]);
+ }
+ }
+}
+
+void
+ConditionVariableWindows::WakeAll()
+{
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ _PWakeAllConditionVariable(&_conditionVariable);
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ // Update current WakeAll() event
+ _eventID = (WAKEALL_0 == _eventID) ? WAKEALL_1 : WAKEALL_0;
+ // Trigger current event
+ const EventWakeUpType eventID = _eventID;
+ const bool haveWaiters = _numWaiters[eventID] > 0;
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (haveWaiters)
+ {
+ SetEvent(_events[eventID]);
+ }
+ }
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_win.h b/src/system_wrappers/source/condition_variable_win.h
new file mode 100644
index 0000000..aab2564
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_win.h
@@ -0,0 +1,67 @@
+/*
+ * 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_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
+
+#include "condition_variable_wrapper.h"
+
+#include <windows.h>
+
+namespace webrtc {
+#if !defined CONDITION_VARIABLE_INIT
+ typedef struct _RTL_CONDITION_VARIABLE
+ {
+ void* Ptr;
+ } RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
+
+ typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
+#endif
+
+typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
+typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
+ PCRITICAL_SECTION, DWORD);
+typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
+typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
+
+
+class ConditionVariableWindows : public ConditionVariableWrapper
+{
+public:
+ ConditionVariableWindows();
+ ~ConditionVariableWindows();
+
+ void SleepCS(CriticalSectionWrapper& critSect);
+ bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
+ void Wake();
+ void WakeAll();
+
+private:
+ enum EventWakeUpType
+ {
+ WAKEALL_0 = 0,
+ WAKEALL_1 = 1,
+ WAKE = 2,
+ EVENT_COUNT = 3
+ };
+
+private:
+ // Native support for Windows Vista+
+ static bool _winSupportConditionVariablesPrimitive;
+ CONDITION_VARIABLE _conditionVariable;
+
+ unsigned int _numWaiters[2];
+ EventWakeUpType _eventID;
+ CRITICAL_SECTION _numWaitersCritSect;
+ HANDLE _events[EVENT_COUNT];
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
diff --git a/src/system_wrappers/source/cpu_features_android.c b/src/system_wrappers/source/cpu_features_android.c
new file mode 100644
index 0000000..7a4fa6e
--- /dev/null
+++ b/src/system_wrappers/source/cpu_features_android.c
@@ -0,0 +1,15 @@
+/*
+ * 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 "android/cpu-features.h"
+
+uint64_t WebRtc_GetCPUFeaturesARM(void) {
+ return android_getCpuFeatures();
+}
diff --git a/src/system_wrappers/source/cpu_features_arm.c b/src/system_wrappers/source/cpu_features_arm.c
deleted file mode 100644
index 1065118..0000000
--- a/src/system_wrappers/source/cpu_features_arm.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * 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.
- */
-
-// This file is derived from Android's NDK package r7, located at
-// <ndk>/sources/android/cpufeatures/ (downloadable from
-// http://developer.android.com/sdk/ndk/index.html).
-
-#include "cpu_features_wrapper.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-// Define CPU family.
-typedef enum {
- CPU_FAMILY_UNKNOWN = 0,
- CPU_FAMILY_ARM,
- CPU_FAMILY_X86,
- CPU_FAMILY_MAX // Do not remove.
-} CpuFamily;
-
-static pthread_once_t g_once;
-static CpuFamily g_cpuFamily;
-static uint64_t g_cpuFeatures;
-static int g_cpuCount;
-
-static const int cpufeatures_debug = 0;
-
-#ifdef __arm__
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_ARM
-#elif defined __i386__
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_X86
-#else
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_UNKNOWN
-#endif
-
-#define D(...) \
- do { \
- if (cpufeatures_debug) { \
- printf(__VA_ARGS__); fflush(stdout); \
- } \
- } while (0)
-
-/* Read the content of /proc/cpuinfo into a user-provided buffer.
- * Return the length of the data, or -1 on error. Does *not*
- * zero-terminate the content. Will not read more
- * than 'buffsize' bytes.
- */
-static int read_file(const char* pathname, char* buffer, size_t buffsize) {
- int fd, len;
-
- fd = open(pathname, O_RDONLY);
- if (fd < 0)
- return -1;
-
- do {
- len = read(fd, buffer, buffsize);
- } while (len < 0 && errno == EINTR);
-
- close(fd);
-
- return len;
-}
-
-/* Extract the content of a the first occurence of a given field in
- * the content of /proc/cpuinfo and return it as a heap-allocated
- * string that must be freed by the caller.
- *
- * Return NULL if not found
- */
-static char* extract_cpuinfo_field(char* buffer, int buflen, const char* field) {
- int fieldlen = strlen(field);
- char* bufend = buffer + buflen;
- char* result = NULL;
- int len, ignore;
- const char* p, *q;
-
- /* Look for first field occurence, and ensures it starts the line.
- */
- p = buffer;
- bufend = buffer + buflen;
- for (;;) {
- p = memmem(p, bufend - p, field, fieldlen);
- if (p == NULL)
- goto EXIT;
-
- if (p == buffer || p[-1] == '\n')
- break;
-
- p += fieldlen;
- }
-
- /* Skip to the first column followed by a space */
- p += fieldlen;
- p = memchr(p, ':', bufend - p);
- if (p == NULL || p[1] != ' ')
- goto EXIT;
-
- /* Find the end of the line */
- p += 2;
- q = memchr(p, '\n', bufend - p);
- if (q == NULL)
- q = bufend;
-
- /* Copy the line into a heap-allocated buffer */
- len = q - p;
- result = malloc(len + 1);
- if (result == NULL)
- goto EXIT;
-
- memcpy(result, p, len);
- result[len] = '\0';
-
-EXIT:
- return result;
-}
-
-/* Count the number of occurences of a given field prefix in /proc/cpuinfo.
- */
-static int count_cpuinfo_field(char* buffer, int buflen, const char* field) {
- int fieldlen = strlen(field);
- const char* p = buffer;
- const char* bufend = buffer + buflen;
- const char* q;
- int count = 0;
-
- for (;;) {
- const char* q;
-
- p = memmem(p, bufend - p, field, fieldlen);
- if (p == NULL)
- break;
-
- /* Ensure that the field is at the start of a line */
- if (p > buffer && p[-1] != '\n') {
- p += fieldlen;
- continue;
- }
-
-
- /* skip any whitespace */
- q = p + fieldlen;
- while (q < bufend && (*q == ' ' || *q == '\t'))
- q++;
-
- /* we must have a colon now */
- if (q < bufend && *q == ':') {
- count += 1;
- q ++;
- }
- p = q;
- }
-
- return count;
-}
-
-/* Like strlen(), but for constant string literals */
-#define STRLEN_CONST(x) ((sizeof(x)-1)
-
-
-/* Checks that a space-separated list of items contains one given 'item'.
- * Returns 1 if found, 0 otherwise.
- */
-static int has_list_item(const char* list, const char* item) {
- const char* p = list;
- int itemlen = strlen(item);
-
- if (list == NULL)
- return 0;
-
- while (*p) {
- const char* q;
-
- /* skip spaces */
- while (*p == ' ' || *p == '\t')
- p++;
-
- /* find end of current list item */
- q = p;
- while (*q && *q != ' ' && *q != '\t')
- q++;
-
- if (itemlen == q - p && !memcmp(p, item, itemlen))
- return 1;
-
- /* skip to next item */
- p = q;
- }
- return 0;
-}
-
-
-static void cpuInit(void) {
- char cpuinfo[4096];
- int cpuinfo_len;
-
- g_cpuFamily = DEFAULT_CPU_FAMILY;
- g_cpuFeatures = 0;
- g_cpuCount = 1;
-
- cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo);
- D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
- cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
-
- if (cpuinfo_len < 0) { /* should not happen */
- return;
- }
-
- /* Count the CPU cores, the value may be 0 for single-core CPUs */
- g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor");
- if (g_cpuCount == 0) {
- g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor");
- if (g_cpuCount == 0) {
- g_cpuCount = 1;
- }
- }
-
- D("found cpuCount = %d\n", g_cpuCount);
-
-#ifdef __arm__
- {
- char* features = NULL;
- char* architecture = NULL;
-
- /* Extract architecture from the "CPU Architecture" field.
- * The list is well-known, unlike the the output of
- * the 'Processor' field which can vary greatly.
- *
- * See the definition of the 'proc_arch' array in
- * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
- * same file.
- */
- char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "CPU architecture");
-
- if (cpuArch != NULL) {
- char* end;
- long archNumber;
- int hasARMv7 = 0;
-
- D("found cpuArch = '%s'\n", cpuArch);
-
- /* read the initial decimal number, ignore the rest */
- archNumber = strtol(cpuArch, &end, 10);
-
- /* Here we assume that ARMv8 will be upwards compatible with v7
- * in the future. Unfortunately, there is no 'Features' field to
- * indicate that Thumb-2 is supported.
- */
- if (end > cpuArch && archNumber >= 7) {
- hasARMv7 = 1;
- }
-
- /* Unfortunately, it seems that certain ARMv6-based CPUs
- * report an incorrect architecture number of 7!
- *
- * We try to correct this by looking at the 'elf_format'
- * field reported by the 'Processor' field, which is of the
- * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
- * an ARMv6-one.
- */
- if (hasARMv7) {
- char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "Processor");
- if (cpuProc != NULL) {
- D("found cpuProc = '%s'\n", cpuProc);
- if (has_list_item(cpuProc, "(v6l)")) {
- D("CPU processor and architecture mismatch!!\n");
- hasARMv7 = 0;
- }
- free(cpuProc);
- }
- }
-
- if (hasARMv7) {
- g_cpuFeatures |= kCPUFeatureARMv7;
- }
-
- /* The LDREX / STREX instructions are available from ARMv6 */
- if (archNumber >= 6) {
- g_cpuFeatures |= kCPUFeatureLDREXSTREX;
- }
-
- free(cpuArch);
- }
-
- /* Extract the list of CPU features from 'Features' field */
- char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "Features");
-
- if (cpuFeatures != NULL) {
-
- D("found cpuFeatures = '%s'\n", cpuFeatures);
-
- if (has_list_item(cpuFeatures, "vfpv3"))
- g_cpuFeatures |= kCPUFeatureVFPv3;
-
- else if (has_list_item(cpuFeatures, "vfpv3d16"))
- g_cpuFeatures |= kCPUFeatureVFPv3;
-
- if (has_list_item(cpuFeatures, "neon")) {
- /* Note: Certain kernels only report neon but not vfpv3
- * in their features list. However, ARM mandates
- * that if Neon is implemented, so must be VFPv3
- * so always set the flag.
- */
- g_cpuFeatures |= kCPUFeatureNEON |
- kCPUFeatureVFPv3;
- }
- free(cpuFeatures);
- }
- }
-#endif // __arm__
-
-#ifdef __i386__
- g_cpuFamily = CPU_FAMILY_X86;
-#endif
-}
-
-
-uint64_t WebRtc_GetCPUFeaturesARM(void) {
- pthread_once(&g_once, cpuInit);
- return g_cpuFeatures;
-}
diff --git a/src/system_wrappers/source/cpu_linux.cc b/src/system_wrappers/source/cpu_linux.cc
index 9d7d89d..8e8ecda 100644
--- a/src/system_wrappers/source/cpu_linux.cc
+++ b/src/system_wrappers/source/cpu_linux.cc
@@ -179,6 +179,7 @@
char line[100];
if (!fgets(line, 100, fp))
{
+ fclose(fp);
return -1;
}
int numCores = -1;
diff --git a/src/system_wrappers/source/cpu_measurement_harness.cc b/src/system_wrappers/source/cpu_measurement_harness.cc
new file mode 100644
index 0000000..237e776
--- /dev/null
+++ b/src/system_wrappers/source/cpu_measurement_harness.cc
@@ -0,0 +1,127 @@
+/*
+ * 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 "system_wrappers/interface/cpu_wrapper.h"
+#include "system_wrappers/interface/event_wrapper.h"
+#include "system_wrappers/interface/scoped_ptr.h"
+#include "system_wrappers/source/cpu_measurement_harness.h"
+
+const int kCpuCheckPeriodMs = 100;
+
+namespace webrtc {
+
+CpuMeasurementHarness* CpuMeasurementHarness::Create(
+ CpuTarget* target,
+ int work_period_ms,
+ int work_iterations_per_period,
+ int duration_ms) {
+ if (target == NULL) {
+ return NULL;
+ }
+ if (work_period_ms > duration_ms) {
+ return NULL;
+ }
+ if (work_period_ms < 0) {
+ return NULL;
+ }
+ if (duration_ms < 0) {
+ return NULL;
+ }
+ if (work_iterations_per_period < 1) {
+ return NULL;
+ }
+ return new CpuMeasurementHarness(target, work_period_ms,
+ work_iterations_per_period, duration_ms);
+}
+
+CpuMeasurementHarness::CpuMeasurementHarness(CpuTarget* target,
+ int work_period_ms,
+ int work_iterations_per_period,
+ int duration_ms)
+ : cpu_target_(target),
+ work_period_ms_(work_period_ms),
+ work_iterations_per_period_(work_iterations_per_period),
+ duration_ms_(duration_ms),
+ cpu_sum_(0),
+ cpu_iterations_(0),
+ cpu_(CpuWrapper::CreateCpu()),
+ event_(EventWrapper::Create()) {
+}
+
+CpuMeasurementHarness::~CpuMeasurementHarness() {
+}
+
+bool CpuMeasurementHarness::Run() {
+ if (!WaitForCpuInit()) {
+ return false;
+ }
+ // No need for precision. Run for approximately the asked for duration.
+ // TODO(hellner): very low prio if at all, the actual duration of the test
+ // will be longer if calling DoWork() is not negligable and/or called many
+ // times. It may make sense to compensate for drift here. This will,
+ // however, only add complexity with minimal gains. Perhaps renaming the
+ // duration_ms_ to something more fuzzy is a better idea. However, the name
+ // would be very convoluted if it is to be self documenting.
+ int elapsed_time_ms = 0;
+ int last_measured_time = 0;
+ while (elapsed_time_ms < duration_ms_) {
+ if (((elapsed_time_ms - last_measured_time) / kCpuCheckPeriodMs) >= 1) {
+ last_measured_time = elapsed_time_ms;
+ Measure();
+ }
+ if (!DoWork()) {
+ return false;
+ }
+ event_->Wait(work_period_ms_);
+ elapsed_time_ms += work_period_ms_;
+ }
+ return true;
+}
+
+int CpuMeasurementHarness::AverageCpu() {
+ if (cpu_iterations_ == 0) {
+ return 0;
+ }
+ assert(cpu_sum_ >= 0);
+ assert(cpu_iterations_ >= 0);
+ return cpu_sum_ / cpu_iterations_;
+}
+
+bool CpuMeasurementHarness::WaitForCpuInit() {
+ bool cpu_usage_available = false;
+ int num_iterations = 0;
+ // Initializing the CPU measurements may take a couple of seconds on Windows.
+ // Since the initialization is lazy we need to wait until it is completed.
+ // Should not take more than 10000 ms.
+ while (!cpu_usage_available && (++num_iterations < 10000)) {
+ event_->Wait(1);
+ cpu_usage_available = cpu_->CpuUsage() != -1;
+ }
+ return cpu_usage_available;
+}
+
+void CpuMeasurementHarness::Measure() {
+ WebRtc_UWord32 num_cores = 0;
+ WebRtc_UWord32* cores = NULL;
+ // Return the average CPU for now.
+ cpu_sum_ = cpu_->CpuUsageMultiCore(num_cores, cores);
+ ++cpu_iterations_;
+}
+
+bool CpuMeasurementHarness::DoWork() {
+ for (int i = 0; i < work_iterations_per_period_; ++i) {
+ if (!cpu_target_->DoWork()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/cpu_measurement_harness.h b/src/system_wrappers/source/cpu_measurement_harness.h
new file mode 100644
index 0000000..3b87f27
--- /dev/null
+++ b/src/system_wrappers/source/cpu_measurement_harness.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
+#define SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
+
+#include "system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class CpuWrapper;
+class EventWrapper;
+class ThreadWrapper;
+
+// This abstract class provides an interface that should be passed to
+// CpuMeasurementHarness. CpuMeasurementHarness will call it with the
+// frequency requested and measure the CPU usage for all calls.
+class CpuTarget {
+ public:
+ // Callback function for which the CPU usage should be calculated.
+ virtual bool DoWork() = 0;
+
+ protected:
+ CpuTarget() {}
+ virtual ~CpuTarget() {}
+};
+
+class CpuMeasurementHarness {
+ public:
+ static CpuMeasurementHarness* Create(CpuTarget* target,
+ int work_period_ms,
+ int work_iterations_per_period,
+ int duration_ms);
+ ~CpuMeasurementHarness();
+ bool Run();
+ int AverageCpu();
+
+ protected:
+ CpuMeasurementHarness(CpuTarget* target, int work_period_ms,
+ int work_iterations_per_period, int duration_ms);
+
+ private:
+ bool WaitForCpuInit();
+ void Measure();
+ bool DoWork();
+
+ CpuTarget* cpu_target_;
+ const int work_period_ms_;
+ const int work_iterations_per_period_;
+ const int duration_ms_;
+ int cpu_sum_;
+ int cpu_iterations_;
+ scoped_ptr<CpuWrapper> cpu_;
+ scoped_ptr<EventWrapper> event_;
+};
+
+} // namespace webrtc
+
+#endif // SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
diff --git a/src/system_wrappers/source/cpu_win.cc b/src/system_wrappers/source/cpu_win.cc
new file mode 100644
index 0000000..86a6a6a
--- /dev/null
+++ b/src/system_wrappers/source/cpu_win.cc
@@ -0,0 +1,530 @@
+/*
+ * 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 "cpu_win.h"
+
+#define _WIN32_DCOM
+
+#include <assert.h>
+#include <iostream>
+#include <Wbemidl.h>
+
+#pragma comment(lib, "wbemuuid.lib")
+
+#include "condition_variable_wrapper.h"
+#include "critical_section_wrapper.h"
+#include "event_wrapper.h"
+#include "thread_wrapper.h"
+
+namespace webrtc {
+WebRtc_Word32 CpuWindows::CpuUsage()
+{
+ if (!has_initialized_)
+ {
+ return -1;
+ }
+ // Last element is the average
+ return cpu_usage_[number_of_objects_ - 1];
+}
+
+WebRtc_Word32 CpuWindows::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
+ WebRtc_UWord32*& cpu_usage)
+{
+ if (has_terminated_) {
+ num_cores = 0;
+ cpu_usage = NULL;
+ return -1;
+ }
+ if (!has_initialized_)
+ {
+ num_cores = 0;
+ cpu_usage = NULL;
+ return -1;
+ }
+ num_cores = number_of_objects_ - 1;
+ cpu_usage = cpu_usage_;
+ return cpu_usage_[number_of_objects_-1];
+}
+
+CpuWindows::CpuWindows()
+ : cpu_polling_thread(NULL),
+ initialize_(true),
+ has_initialized_(false),
+ terminate_(false),
+ has_terminated_(false),
+ cpu_usage_(NULL),
+ wbem_enum_access_(NULL),
+ number_of_objects_(0),
+ cpu_usage_handle_(0),
+ previous_processor_timestamp_(NULL),
+ timestamp_sys_100_ns_handle_(0),
+ previous_100ns_timestamp_(NULL),
+ wbem_service_(NULL),
+ wbem_service_proxy_(NULL),
+ wbem_refresher_(NULL),
+ wbem_enum_(NULL)
+{
+ // All resources are allocated in PollingCpu().
+ if (AllocateComplexDataTypes())
+ {
+ StartPollingCpu();
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+CpuWindows::~CpuWindows()
+{
+ // All resources are reclaimed in StopPollingCpu().
+ StopPollingCpu();
+ DeAllocateComplexDataTypes();
+}
+
+bool CpuWindows::AllocateComplexDataTypes()
+{
+ cpu_polling_thread = ThreadWrapper::CreateThread(
+ CpuWindows::Process,
+ reinterpret_cast<void*>(this),
+ kNormalPriority,
+ "CpuWindows");
+ init_crit_ = CriticalSectionWrapper::CreateCriticalSection();
+ init_cond_ = ConditionVariableWrapper::CreateConditionVariable();
+ terminate_crit_ = CriticalSectionWrapper::CreateCriticalSection();
+ terminate_cond_ = ConditionVariableWrapper::CreateConditionVariable();
+ sleep_event = EventWrapper::Create();
+ return (cpu_polling_thread != NULL) && (init_crit_ != NULL) &&
+ (init_cond_ != NULL) && (terminate_crit_ != NULL) &&
+ (terminate_cond_ != NULL) && (sleep_event != NULL);
+}
+
+void CpuWindows::DeAllocateComplexDataTypes()
+{
+ if (sleep_event != NULL)
+ {
+ delete sleep_event;
+ sleep_event = NULL;
+ }
+ if (terminate_cond_ != NULL)
+ {
+ delete terminate_cond_;
+ terminate_cond_ = NULL;
+ }
+ if (terminate_crit_ != NULL)
+ {
+ delete terminate_crit_;
+ terminate_crit_ = NULL;
+ }
+ if (init_cond_ != NULL)
+ {
+ delete init_cond_;
+ init_cond_ = NULL;
+ }
+ if (init_crit_ != NULL)
+ {
+ delete init_crit_;
+ init_crit_ = NULL;
+ }
+ if (cpu_polling_thread != NULL)
+ {
+ delete cpu_polling_thread;
+ cpu_polling_thread = NULL;
+ }
+}
+
+void CpuWindows::StartPollingCpu()
+{
+ unsigned int dummy_id = 0;
+ if (!cpu_polling_thread->Start(dummy_id))
+ {
+ initialize_ = false;
+ has_terminated_ = true;
+ assert(false);
+ }
+}
+
+bool CpuWindows::StopPollingCpu()
+{
+ {
+ // If StopPollingCpu is called immediately after StartPollingCpu() it is
+ // possible that cpu_polling_thread is in the process of initializing.
+ // Let initialization finish to avoid getting into a bad state.
+ CriticalSectionScoped cs(init_crit_);
+ while(initialize_)
+ {
+ init_cond_->SleepCS(*init_crit_);
+ }
+ }
+
+ CriticalSectionScoped cs(terminate_crit_);
+ terminate_ = true;
+ sleep_event->Set();
+ while (!has_terminated_)
+ {
+ terminate_cond_->SleepCS(*terminate_crit_);
+ }
+ cpu_polling_thread->Stop();
+ delete cpu_polling_thread;
+ cpu_polling_thread = NULL;
+ return true;
+}
+
+bool CpuWindows::Process(void* thread_object)
+{
+ return reinterpret_cast<CpuWindows*>(thread_object)->ProcessImpl();
+}
+
+bool CpuWindows::ProcessImpl()
+{
+ {
+ CriticalSectionScoped cs(terminate_crit_);
+ if (terminate_)
+ {
+ Terminate();
+ terminate_cond_->WakeAll();
+ return false;
+ }
+ }
+ // Initialize on first iteration
+ if (initialize_)
+ {
+ CriticalSectionScoped cs(init_crit_);
+ initialize_ = false;
+ const bool success = Initialize();
+ init_cond_->WakeAll();
+ if (!success || !has_initialized_)
+ {
+ has_initialized_ = false;
+ terminate_ = true;
+ return true;
+ }
+ }
+ // Approximately one seconds sleep for each CPU measurement. Precision is
+ // not important. 1 second refresh rate is also used by Performance Monitor
+ // (perfmon).
+ if(kEventTimeout != sleep_event->Wait(1000))
+ {
+ // Terminating. No need to update CPU usage.
+ assert(terminate_);
+ return true;
+ }
+
+ // UpdateCpuUsage() returns false if a single (or more) CPU read(s) failed.
+ // Not a major problem if it happens.
+ UpdateCpuUsage();
+ return true;
+}
+
+bool CpuWindows::CreateWmiConnection()
+{
+ IWbemLocator* service_locator = NULL;
+ HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL,
+ CLSCTX_INPROC_SERVER, IID_IWbemLocator,
+ reinterpret_cast<void**> (&service_locator));
+ if (FAILED(hr))
+ {
+ return false;
+ }
+ // To get the WMI service specify the WMI namespace.
+ BSTR wmi_namespace = SysAllocString(L"\\\\.\\root\\cimv2");
+ if (wmi_namespace == NULL)
+ {
+ // This type of failure signifies running out of memory.
+ service_locator->Release();
+ return false;
+ }
+ hr = service_locator->ConnectServer(wmi_namespace, NULL, NULL, NULL, 0L,
+ NULL, NULL, &wbem_service_);
+ SysFreeString(wmi_namespace);
+ service_locator->Release();
+ return !FAILED(hr);
+}
+
+// Sets up WMI refresher and enum
+bool CpuWindows::CreatePerfOsRefresher()
+{
+ // Create refresher.
+ HRESULT hr = CoCreateInstance(CLSID_WbemRefresher, NULL,
+ CLSCTX_INPROC_SERVER, IID_IWbemRefresher,
+ reinterpret_cast<void**> (&wbem_refresher_));
+ if (FAILED(hr))
+ {
+ return false;
+ }
+ // Create PerfOS_Processor enum.
+ IWbemConfigureRefresher* wbem_refresher_config = NULL;
+ hr = wbem_refresher_->QueryInterface(
+ IID_IWbemConfigureRefresher,
+ reinterpret_cast<void**> (&wbem_refresher_config));
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ // Create a proxy to the IWbemServices so that a local authentication
+ // can be set up (this is needed to be able to successfully call
+ // IWbemConfigureRefresher::AddEnum). Setting authentication with
+ // CoInitializeSecurity is process-wide (which is too intrusive).
+ hr = CoCopyProxy(static_cast<IUnknown*> (wbem_service_),
+ reinterpret_cast<IUnknown**> (&wbem_service_proxy_));
+ if(FAILED(hr))
+ {
+ return false;
+ }
+ // Set local authentication.
+ // RPC_C_AUTHN_WINNT means using NTLM instead of Kerberos which is default.
+ hr = CoSetProxyBlanket(static_cast<IUnknown*> (wbem_service_proxy_),
+ RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_DEFAULT,
+ RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+ if(FAILED(hr))
+ {
+ return false;
+ }
+
+ // Don't care about the particular id for the enum.
+ long enum_id = 0;
+ hr = wbem_refresher_config->AddEnum(wbem_service_proxy_,
+ L"Win32_PerfRawData_PerfOS_Processor",
+ 0, NULL, &wbem_enum_, &enum_id);
+ wbem_refresher_config->Release();
+ wbem_refresher_config = NULL;
+ return !FAILED(hr);
+}
+
+// Have to pull the first round of data to be able set the handles.
+bool CpuWindows::CreatePerfOsCpuHandles()
+{
+ // Update the refresher so that there is data available in wbem_enum_.
+ wbem_refresher_->Refresh(0L);
+
+ // The number of enumerators is the number of processor + 1 (the total).
+ // This is unknown at this point.
+ DWORD number_returned = 0;
+ HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
+ wbem_enum_access_, &number_returned);
+ // number_returned indicates the number of enumerators that are needed.
+ if (hr == WBEM_E_BUFFER_TOO_SMALL &&
+ number_returned > number_of_objects_)
+ {
+ // Allocate the number IWbemObjectAccess asked for by the
+ // GetObjects(..) function.
+ wbem_enum_access_ = new IWbemObjectAccess*[number_returned];
+ cpu_usage_ = new WebRtc_UWord32[number_returned];
+ previous_processor_timestamp_ = new unsigned __int64[number_returned];
+ previous_100ns_timestamp_ = new unsigned __int64[number_returned];
+ if ((wbem_enum_access_ == NULL) || (cpu_usage_ == NULL) ||
+ (previous_processor_timestamp_ == NULL) ||
+ (previous_100ns_timestamp_ == NULL))
+ {
+ // Out of memory.
+ return false;
+ }
+
+ SecureZeroMemory(wbem_enum_access_, number_returned *
+ sizeof(IWbemObjectAccess*));
+ memset(cpu_usage_, 0, sizeof(int) * number_returned);
+ memset(previous_processor_timestamp_, 0, sizeof(unsigned __int64) *
+ number_returned);
+ memset(previous_100ns_timestamp_, 0, sizeof(unsigned __int64) *
+ number_returned);
+
+ number_of_objects_ = number_returned;
+ // Read should be successfull now that memory has been allocated.
+ hr = wbem_enum_->GetObjects(0L, number_of_objects_, wbem_enum_access_,
+ &number_returned);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // 0 enumerators should not be enough. Something has gone wrong here.
+ return false;
+ }
+
+ // Get the enumerator handles that are needed for calculating CPU usage.
+ CIMTYPE cpu_usage_type;
+ hr = wbem_enum_access_[0]->GetPropertyHandle(L"PercentProcessorTime",
+ &cpu_usage_type,
+ &cpu_usage_handle_);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+ CIMTYPE timestamp_sys_100_ns_type;
+ hr = wbem_enum_access_[0]->GetPropertyHandle(L"TimeStamp_Sys100NS",
+ ×tamp_sys_100_ns_type,
+ ×tamp_sys_100_ns_handle_);
+ return !FAILED(hr);
+}
+
+bool CpuWindows::Initialize()
+{
+ if (terminate_)
+ {
+ return false;
+ }
+ // Initialize COM library.
+ HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ if (!CreateWmiConnection())
+ {
+ return false;
+ }
+ if (!CreatePerfOsRefresher())
+ {
+ return false;
+ }
+ if (!CreatePerfOsCpuHandles())
+ {
+ return false;
+ }
+ has_initialized_ = true;
+ return true;
+}
+
+bool CpuWindows::Terminate()
+{
+ if (has_terminated_)
+ {
+ return false;
+ }
+ // Reverse order of Initialize().
+ // Some compilers complain about deleting NULL though it's well defined
+ if (previous_100ns_timestamp_ != NULL)
+ {
+ delete[] previous_100ns_timestamp_;
+ previous_100ns_timestamp_ = NULL;
+ }
+ if (previous_processor_timestamp_ != NULL)
+ {
+ delete[] previous_processor_timestamp_;
+ previous_processor_timestamp_ = NULL;
+ }
+ if (cpu_usage_ != NULL)
+ {
+ delete[] cpu_usage_;
+ cpu_usage_ = NULL;
+ }
+ if (wbem_enum_access_ != NULL)
+ {
+ for (DWORD i = 0; i < number_of_objects_; i++)
+ {
+ if(wbem_enum_access_[i] != NULL)
+ {
+ wbem_enum_access_[i]->Release();
+ }
+ }
+ delete[] wbem_enum_access_;
+ wbem_enum_access_ = NULL;
+ }
+ if (wbem_enum_ != NULL)
+ {
+ wbem_enum_->Release();
+ wbem_enum_ = NULL;
+ }
+ if (wbem_refresher_ != NULL)
+ {
+ wbem_refresher_->Release();
+ wbem_refresher_ = NULL;
+ }
+ if (wbem_service_proxy_ != NULL)
+ {
+ wbem_service_proxy_->Release();
+ wbem_service_proxy_ = NULL;
+ }
+ if (wbem_service_ != NULL)
+ {
+ wbem_service_->Release();
+ wbem_service_ = NULL;
+ }
+ // CoUninitialized should be called once for every CoInitializeEx.
+ // Regardless if it failed or not.
+ CoUninitialize();
+ has_terminated_ = true;
+ return true;
+}
+
+bool CpuWindows::UpdateCpuUsage()
+{
+ wbem_refresher_->Refresh(0L);
+ DWORD number_returned = 0;
+ HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
+ wbem_enum_access_,&number_returned);
+ if (FAILED(hr))
+ {
+ // wbem_enum_access_ has already been allocated. Unless the number of
+ // CPUs change runtime this should not happen.
+ return false;
+ }
+ unsigned __int64 cpu_usage = 0;
+ unsigned __int64 timestamp_100ns = 0;
+ bool returnValue = true;
+ for (DWORD i = 0; i < number_returned; i++)
+ {
+ hr = wbem_enum_access_[i]->ReadQWORD(cpu_usage_handle_,&cpu_usage);
+ if (FAILED(hr))
+ {
+ returnValue = false;
+ }
+ hr = wbem_enum_access_[i]->ReadQWORD(timestamp_sys_100_ns_handle_,
+ ×tamp_100ns);
+ if (FAILED(hr))
+ {
+ returnValue = false;
+ }
+ wbem_enum_access_[i]->Release();
+ wbem_enum_access_[i] = NULL;
+
+ const bool wrapparound =
+ (previous_processor_timestamp_[i] > cpu_usage) ||
+ (previous_100ns_timestamp_[i] > timestamp_100ns);
+ const bool first_time = (previous_processor_timestamp_[i] == 0) ||
+ (previous_100ns_timestamp_[i] == 0);
+ if (wrapparound || first_time)
+ {
+ previous_processor_timestamp_[i] = cpu_usage;
+ previous_100ns_timestamp_[i] = timestamp_100ns;
+ continue;
+ }
+ const unsigned __int64 processor_timestamp_delta =
+ cpu_usage - previous_processor_timestamp_[i];
+ const unsigned __int64 timestamp_100ns_delta =
+ timestamp_100ns - previous_100ns_timestamp_[i];
+
+ if (processor_timestamp_delta >= timestamp_100ns_delta)
+ {
+ cpu_usage_[i] = 0;
+ } else {
+ // Quotient must be float since the division is guaranteed to yield
+ // a value between 0 and 1 which is 0 in integer division.
+ const float delta_quotient =
+ static_cast<float>(processor_timestamp_delta) /
+ static_cast<float>(timestamp_100ns_delta);
+ cpu_usage_[i] = 100 - static_cast<WebRtc_UWord32>(delta_quotient *
+ 100);
+ }
+ previous_processor_timestamp_[i] = cpu_usage;
+ previous_100ns_timestamp_[i] = timestamp_100ns;
+ }
+ return returnValue;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/cpu_win.h b/src/system_wrappers/source/cpu_win.h
new file mode 100644
index 0000000..d15073c
--- /dev/null
+++ b/src/system_wrappers/source/cpu_win.h
@@ -0,0 +1,103 @@
+// This file contains a Windows implementation of CpuWrapper.
+// Note: Windows XP, Windows Server 2003 are the minimum requirements.
+// The requirements are due to the implementation being based on
+// WMI.
+/*
+ * 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_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
+
+#include "cpu_wrapper.h"
+
+#include <Wbemidl.h>
+
+namespace webrtc {
+class ConditionVariableWrapper;
+class CriticalSectionWrapper;
+class EventWrapper;
+class ThreadWrapper;
+
+class CpuWindows : public CpuWrapper
+{
+public:
+ virtual WebRtc_Word32 CpuUsage();
+ virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* /*pProcessName*/,
+ WebRtc_UWord32 /*length*/) {return -1;}
+ virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 /*dwProcessID*/) {return -1;}
+
+ virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
+ WebRtc_UWord32*& cpu_usage);
+
+ virtual void Reset() {}
+ virtual void Stop() {}
+
+ CpuWindows();
+ virtual ~CpuWindows();
+private:
+ bool AllocateComplexDataTypes();
+ void DeAllocateComplexDataTypes();
+
+ void StartPollingCpu();
+ bool StopPollingCpu();
+
+ static bool Process(void* thread_object);
+ bool ProcessImpl();
+
+ bool CreateWmiConnection();
+ bool CreatePerfOsRefresher();
+ bool CreatePerfOsCpuHandles();
+ bool Initialize();
+ bool Terminate();
+
+ bool UpdateCpuUsage();
+
+ ThreadWrapper* cpu_polling_thread;
+
+ bool initialize_;
+ bool has_initialized_;
+ CriticalSectionWrapper* init_crit_;
+ ConditionVariableWrapper* init_cond_;
+
+ bool terminate_;
+ bool has_terminated_;
+ CriticalSectionWrapper* terminate_crit_;
+ ConditionVariableWrapper* terminate_cond_;
+
+ // For sleep with wake-up functionality.
+ EventWrapper* sleep_event;
+
+ // Will be an array. Just care about CPU 0 for now.
+ WebRtc_UWord32* cpu_usage_;
+
+ // One IWbemObjectAccess for each processor and one for the total.
+ // 0-n-1 is the individual processors.
+ // n is the total.
+ IWbemObjectAccess** wbem_enum_access_;
+ DWORD number_of_objects_;
+
+ // Cpu timestamp
+ long cpu_usage_handle_;
+ unsigned __int64* previous_processor_timestamp_;
+
+ // Timestamp
+ long timestamp_sys_100_ns_handle_;
+ unsigned __int64* previous_100ns_timestamp_;
+
+ IWbemServices* wbem_service_;
+ IWbemServices* wbem_service_proxy_;
+
+ IWbemRefresher* wbem_refresher_;
+
+ IWbemHiPerfEnum* wbem_enum_;
+
+};
+} // namespace webrtc
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
diff --git a/src/system_wrappers/source/cpu_wrapper_unittest.cc b/src/system_wrappers/source/cpu_wrapper_unittest.cc
index dd49c3a..cd149dc 100644
--- a/src/system_wrappers/source/cpu_wrapper_unittest.cc
+++ b/src/system_wrappers/source/cpu_wrapper_unittest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -23,7 +23,14 @@
using webrtc::scoped_ptr;
using webrtc::Trace;
-TEST(CpuWrapperTest, Usage) {
+// This test is flaky on Windows/Release.
+// http://code.google.com/p/webrtc/issues/detail?id=290
+#ifdef _WIN32
+#define MAYBE_Usage DISABLED_Usage
+#else
+#define MAYBE_Usage Usage
+#endif
+TEST(CpuWrapperTest, MAYBE_Usage) {
Trace::CreateTrace();
std::string trace_file = webrtc::test::OutputPath() +
"cpu_wrapper_unittest.txt";
@@ -42,7 +49,7 @@
// Initializing the CPU measurements may take a couple of seconds on Windows.
// Since the initialization is lazy we need to wait until it is completed.
// Should not take more than 10000 ms.
- while (cpu_usage_available && (++num_iterations < 10000)) {
+ while (!cpu_usage_available && (++num_iterations < 10000)) {
if (cores != NULL) {
ASSERT_GT(num_cores, 0u);
break;
diff --git a/src/system_wrappers/source/critical_section_posix.cc b/src/system_wrappers/source/critical_section_posix.cc
index b499b9f..70f85f9 100644
--- a/src/system_wrappers/source/critical_section_posix.cc
+++ b/src/system_wrappers/source/critical_section_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -8,31 +8,39 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+// General note: return values for the various pthread synchronization APIs
+// are explicitly ignored here. In Chromium, the same thing is done for release.
+// However, in debugging, failure in these APIs are logged. There is currently
+// no equivalent to DCHECK_EQ in WebRTC code so this is the best we can do here.
+// TODO(henrike): add logging when pthread synchronization APIs are failing.
+
#include "critical_section_posix.h"
namespace webrtc {
+
CriticalSectionPosix::CriticalSectionPosix()
{
pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&_mutex, &attr);
+ (void) pthread_mutexattr_init(&attr);
+ (void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ (void) pthread_mutex_init(&_mutex, &attr);
}
CriticalSectionPosix::~CriticalSectionPosix()
{
- pthread_mutex_destroy(&_mutex);
+ (void) pthread_mutex_destroy(&_mutex);
}
void
CriticalSectionPosix::Enter()
{
- pthread_mutex_lock(&_mutex);
+ (void) pthread_mutex_lock(&_mutex);
}
void
CriticalSectionPosix::Leave()
{
- pthread_mutex_unlock(&_mutex);
+ (void) pthread_mutex_unlock(&_mutex);
}
+
} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_unittest.cc b/src/system_wrappers/source/critical_section_unittest.cc
new file mode 100644
index 0000000..c48b9f7
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_unittest.cc
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+// For Sleep()
+#include <windows.h>
+#else
+// For nanosleep()
+#include <time.h>
+#endif
+
+#include "system_wrappers/interface/critical_section_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/sleep.h"
+#include "system_wrappers/interface/thread_wrapper.h"
+#include "system_wrappers/interface/trace.h"
+#include "system_wrappers/source/unittest_utilities.h"
+
+namespace webrtc {
+
+namespace {
+
+const bool kLogTrace = false; // Set to true to enable debug logging to stdout.
+
+#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
+
+// Cause a process switch. Needed to avoid depending on
+// busy-wait in tests.
+static void SwitchProcess() {
+ // Note - sched_yield has been tried as process switch. This does
+ // not cause a process switch enough of the time for reliability.
+ SleepMs(1);
+}
+
+class ProtectedCount {
+ public:
+ explicit ProtectedCount(CriticalSectionWrapper* crit_sect)
+ : crit_sect_(crit_sect),
+ count_(0) {
+ }
+
+ void Increment() {
+ CriticalSectionScoped cs(crit_sect_);
+ ++count_;
+ LOG("Inc to %d", count_);
+ }
+
+ int Count() const {
+ CriticalSectionScoped cs(crit_sect_);
+ return count_;
+ }
+
+ private:
+ CriticalSectionWrapper* crit_sect_;
+ int count_;
+};
+
+class CritSectTest : public ::testing::Test {
+ public:
+ CritSectTest() : trace_(kLogTrace) {
+ }
+
+ // Waits a number of cycles for the count to reach a given value.
+ // Returns true if the target is reached or passed.
+ bool WaitForCount(int target, ProtectedCount* count) {
+ int loop_counter = 0;
+ // On Posix, this SwitchProcess() needs to be in a loop to make the
+ // test both fast and non-flaky.
+ // With 1 us wait as the switch, up to 7 rounds have been observed.
+ while (count->Count() < target && loop_counter < 100*target) {
+ ++loop_counter;
+ SwitchProcess();
+ }
+ LOG("Test looped %d times\n", loop_counter);
+ return (count->Count() >= target);
+ }
+
+ private:
+ ScopedTracing trace_;
+};
+
+bool LockUnlockThenStopRunFunction(void* obj) {
+ LOG("Wait starting");
+ ProtectedCount* the_count = static_cast<ProtectedCount*> (obj);
+ LOG("Wait incrementing");
+ the_count->Increment();
+ LOG("Wait returning");
+ return false;
+}
+
+TEST_F(CritSectTest, ThreadWakesOnce) {
+ CriticalSectionWrapper* crit_sect
+ = CriticalSectionWrapper::CreateCriticalSection();
+ ProtectedCount count(crit_sect);
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(
+ &LockUnlockThenStopRunFunction, &count);
+ unsigned int id = 42;
+ crit_sect->Enter();
+ ASSERT_TRUE(thread->Start(id));
+ SwitchProcess();
+ // The critical section is of reentrant mode, so this should not release
+ // the lock, even though count.Count() locks and unlocks the critical section
+ // again.
+ // Thus, the thread should not be able to increment the count
+ ASSERT_EQ(0, count.Count());
+ crit_sect->Leave(); // This frees the thread to act.
+ EXPECT_TRUE(WaitForCount(1, &count));
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+ delete crit_sect;
+}
+
+bool LockUnlockRunFunction(void* obj) {
+ LOG("Wait starting");
+ ProtectedCount* the_count = static_cast<ProtectedCount*> (obj);
+ LOG("Wait incrementing");
+ the_count->Increment();
+ SwitchProcess();
+ LOG("Wait returning");
+ return true;
+}
+
+TEST_F(CritSectTest, ThreadWakesTwice) {
+ CriticalSectionWrapper* crit_sect
+ = CriticalSectionWrapper::CreateCriticalSection();
+ ProtectedCount count(crit_sect);
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&LockUnlockRunFunction,
+ &count);
+ unsigned int id = 42;
+ crit_sect->Enter(); // Make sure counter stays 0 until we wait for it.
+ ASSERT_TRUE(thread->Start(id));
+ crit_sect->Leave();
+
+ // The thread is capable of grabbing the lock multiple times,
+ // incrementing counter once each time.
+ // It's possible for the count to be incremented by more than 2.
+ EXPECT_TRUE(WaitForCount(2, &count));
+ EXPECT_LE(2, count.Count());
+
+ // The thread does not increment while lock is held.
+ crit_sect->Enter();
+ int count_before = count.Count();
+ for (int i = 0; i < 10; i++) {
+ SwitchProcess();
+ }
+ EXPECT_EQ(count_before, count.Count());
+ crit_sect->Leave();
+
+ thread->SetNotAlive(); // Tell thread to exit once run function finishes.
+ SwitchProcess();
+ EXPECT_LT(count_before, count.Count());
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+ delete crit_sect;
+}
+
+} // anonymous namespace
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_win.cc b/src/system_wrappers/source/critical_section_win.cc
new file mode 100644
index 0000000..bbc66e5
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_win.cc
@@ -0,0 +1,35 @@
+/*
+ * 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 "critical_section_win.h"
+
+namespace webrtc {
+CriticalSectionWindows::CriticalSectionWindows()
+{
+ InitializeCriticalSection(&crit);
+}
+
+CriticalSectionWindows::~CriticalSectionWindows()
+{
+ DeleteCriticalSection(&crit);
+}
+
+void
+CriticalSectionWindows::Enter()
+{
+ EnterCriticalSection(&crit);
+}
+
+void
+CriticalSectionWindows::Leave()
+{
+ LeaveCriticalSection(&crit);
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_win.h b/src/system_wrappers/source/critical_section_win.h
new file mode 100644
index 0000000..9556fa9
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_win.h
@@ -0,0 +1,36 @@
+/*
+ * 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_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
+
+#include "typedefs.h"
+#include "critical_section_wrapper.h"
+#include <windows.h>
+
+namespace webrtc {
+class CriticalSectionWindows : public CriticalSectionWrapper
+{
+public:
+ CriticalSectionWindows();
+
+ virtual ~CriticalSectionWindows();
+
+ virtual void Enter();
+ virtual void Leave();
+
+private:
+ CRITICAL_SECTION crit;
+
+ friend class ConditionVariableWindows;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
diff --git a/src/system_wrappers/source/event_win.cc b/src/system_wrappers/source/event_win.cc
new file mode 100644
index 0000000..efcb5af
--- /dev/null
+++ b/src/system_wrappers/source/event_win.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 "event_win.h"
+
+#include "Mmsystem.h"
+
+namespace webrtc {
+EventWindows::EventWindows()
+ : _event(::CreateEvent(NULL /* security attributes */,
+ FALSE /* manual reset */,
+ FALSE /* initial state */,
+ NULL /* name of event */)),
+ _timerID(NULL)
+{
+}
+
+EventWindows::~EventWindows()
+{
+ CloseHandle(_event);
+}
+
+bool EventWindows::Set()
+{
+ // Note: setting an event that is already set has no effect.
+ return SetEvent(_event) == 1 ? true : false;
+}
+
+bool EventWindows::Reset()
+{
+ return ResetEvent(_event) == 1 ? true : false;
+}
+
+EventTypeWrapper EventWindows::Wait(unsigned long maxTime)
+{
+ unsigned long res = WaitForSingleObject(_event, maxTime);
+ switch(res)
+ {
+ case WAIT_OBJECT_0:
+ return kEventSignaled;
+ case WAIT_TIMEOUT:
+ return kEventTimeout;
+ default:
+ return kEventError;
+ }
+}
+
+bool EventWindows::StartTimer(bool periodic, unsigned long time)
+{
+ if (_timerID != NULL)
+ {
+ timeKillEvent(_timerID);
+ _timerID=NULL;
+ }
+ if (periodic)
+ {
+ _timerID=timeSetEvent(time, 0,(LPTIMECALLBACK)HANDLE(_event),0,
+ TIME_PERIODIC|TIME_CALLBACK_EVENT_PULSE);
+ } else {
+ _timerID=timeSetEvent(time, 0,(LPTIMECALLBACK)HANDLE(_event),0,
+ TIME_ONESHOT|TIME_CALLBACK_EVENT_SET);
+ }
+
+ if (_timerID == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool EventWindows::StopTimer()
+{
+ timeKillEvent(_timerID);
+ _timerID = NULL;
+ return true;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/event_win.h b/src/system_wrappers/source/event_win.h
new file mode 100644
index 0000000..8ca1360
--- /dev/null
+++ b/src/system_wrappers/source/event_win.h
@@ -0,0 +1,40 @@
+/*
+ * 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_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
+
+#include <windows.h>
+
+#include "event_wrapper.h"
+
+#include "typedefs.h"
+
+namespace webrtc {
+class EventWindows : public EventWrapper
+{
+public:
+ EventWindows();
+ virtual ~EventWindows();
+
+ virtual EventTypeWrapper Wait(unsigned long maxTime);
+ virtual bool Set();
+ virtual bool Reset();
+
+ virtual bool StartTimer(bool periodic, unsigned long time);
+ virtual bool StopTimer();
+
+private:
+ HANDLE _event;
+ WebRtc_UWord32 _timerID;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
diff --git a/src/system_wrappers/source/file_impl.cc b/src/system_wrappers/source/file_impl.cc
index d163bf6..4d06c54 100644
--- a/src/system_wrappers/source/file_impl.cc
+++ b/src/system_wrappers/source/file_impl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -118,7 +118,7 @@
bool loop, bool text)
{
size_t length = strlen(fileNameUTF8);
- if (length > kMaxFileNameSize)
+ if (length > kMaxFileNameSize - 1)
{
return -1;
}
diff --git a/src/system_wrappers/source/rw_lock.cc b/src/system_wrappers/source/rw_lock.cc
index b308358..16da0e3 100644
--- a/src/system_wrappers/source/rw_lock.cc
+++ b/src/system_wrappers/source/rw_lock.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -14,9 +14,6 @@
#if defined(_WIN32)
#include "rw_lock_win.h"
-#elif defined(WEBRTC_ANDROID)
- #include <stdlib.h>
- #include "rw_lock_generic.h"
#else
#include "rw_lock_posix.h"
#endif
@@ -26,8 +23,6 @@
{
#ifdef _WIN32
RWLockWrapper* lock = new RWLockWindows();
-#elif defined(WEBRTC_ANDROID)
- RWLockWrapper* lock = new RWLockWrapperGeneric();
#else
RWLockWrapper* lock = new RWLockPosix();
#endif
diff --git a/src/system_wrappers/source/rw_lock_win.cc b/src/system_wrappers/source/rw_lock_win.cc
new file mode 100644
index 0000000..82cd0ac
--- /dev/null
+++ b/src/system_wrappers/source/rw_lock_win.cc
@@ -0,0 +1,186 @@
+/*
+ * 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 "rw_lock_win.h"
+
+#include "critical_section_wrapper.h"
+#include "condition_variable_wrapper.h"
+#include "trace.h"
+
+// TODO (hellner) why not just use the rw_lock_generic.cc solution if
+// native is not supported? Unnecessary redundancy!
+
+namespace webrtc {
+bool RWLockWindows::_winSupportRWLockPrimitive = false;
+static HMODULE library = NULL;
+
+PInitializeSRWLock _PInitializeSRWLock;
+PAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
+PAcquireSRWLockShared _PAcquireSRWLockShared;
+PReleaseSRWLockShared _PReleaseSRWLockShared;
+PReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
+
+RWLockWindows::RWLockWindows()
+ : _critSectPtr(NULL),
+ _readCondPtr(NULL),
+ _writeCondPtr(NULL),
+ _readersActive(0),
+ _writerActive(false),
+ _readersWaiting(0),
+ _writersWaiting(0)
+{
+}
+
+RWLockWindows::~RWLockWindows()
+{
+ delete _writeCondPtr;
+ delete _readCondPtr;
+ delete _critSectPtr;
+}
+
+int RWLockWindows::Init()
+{
+ if(!library)
+ {
+ // Use native implementation if supported (i.e Vista+)
+ library = LoadLibrary(TEXT("Kernel32.dll"));
+ if(library)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Kernel.dll");
+
+ _PInitializeSRWLock =
+ (PInitializeSRWLock)GetProcAddress(
+ library,
+ "InitializeSRWLock");
+
+ _PAcquireSRWLockExclusive =
+ (PAcquireSRWLockExclusive)GetProcAddress(
+ library,
+ "AcquireSRWLockExclusive");
+ _PReleaseSRWLockExclusive =
+ (PReleaseSRWLockExclusive)GetProcAddress(
+ library,
+ "ReleaseSRWLockExclusive");
+ _PAcquireSRWLockShared =
+ (PAcquireSRWLockShared)GetProcAddress(
+ library,
+ "AcquireSRWLockShared");
+ _PReleaseSRWLockShared =
+ (PReleaseSRWLockShared)GetProcAddress(
+ library,
+ "ReleaseSRWLockShared");
+
+ if( _PInitializeSRWLock &&
+ _PAcquireSRWLockExclusive &&
+ _PReleaseSRWLockExclusive &&
+ _PAcquireSRWLockShared &&
+ _PReleaseSRWLockShared )
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Simple RW Lock");
+ _winSupportRWLockPrimitive = true;
+ }
+ }
+ }
+ if(_winSupportRWLockPrimitive)
+ {
+ _PInitializeSRWLock(&_lock);
+ } else {
+ _critSectPtr = CriticalSectionWrapper::CreateCriticalSection();
+ _readCondPtr = ConditionVariableWrapper::CreateConditionVariable();
+ _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
+ }
+ return 0;
+}
+
+void RWLockWindows::AcquireLockExclusive()
+{
+ if (_winSupportRWLockPrimitive)
+ {
+ _PAcquireSRWLockExclusive(&_lock);
+ } else {
+ _critSectPtr->Enter();
+
+ if (_writerActive || _readersActive > 0)
+ {
+ ++_writersWaiting;
+ while (_writerActive || _readersActive > 0)
+ {
+ _writeCondPtr->SleepCS(*_critSectPtr);
+ }
+ --_writersWaiting;
+ }
+ _writerActive = true;
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::ReleaseLockExclusive()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PReleaseSRWLockExclusive(&_lock);
+ } else {
+ _critSectPtr->Enter();
+ _writerActive = false;
+ if (_writersWaiting > 0)
+ {
+ _writeCondPtr->Wake();
+
+ }else if (_readersWaiting > 0) {
+ _readCondPtr->WakeAll();
+ }
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::AcquireLockShared()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PAcquireSRWLockShared(&_lock);
+ } else
+ {
+ _critSectPtr->Enter();
+ if (_writerActive || _writersWaiting > 0)
+ {
+ ++_readersWaiting;
+
+ while (_writerActive || _writersWaiting > 0)
+ {
+ _readCondPtr->SleepCS(*_critSectPtr);
+ }
+ --_readersWaiting;
+ }
+ ++_readersActive;
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::ReleaseLockShared()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PReleaseSRWLockShared(&_lock);
+ } else
+ {
+ _critSectPtr->Enter();
+
+ --_readersActive;
+
+ if (_readersActive == 0 && _writersWaiting > 0)
+ {
+ _writeCondPtr->Wake();
+ }
+ _critSectPtr->Leave();
+ }
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/rw_lock_win.h b/src/system_wrappers/source/rw_lock_win.h
new file mode 100644
index 0000000..dc5355e
--- /dev/null
+++ b/src/system_wrappers/source/rw_lock_win.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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
+
+#include "rw_lock_wrapper.h"
+
+#include <Windows.h>
+
+#if !defined(RTL_SRWLOCK_INIT)
+ typedef struct _RTL_SRWLOCK
+ {
+ void* Ptr;
+ } RTL_SRWLOCK, *PRTL_SRWLOCK;
+ typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
+#endif
+
+namespace webrtc {
+class CriticalSectionWrapper;
+class ConditionVariableWrapper;
+
+typedef void (WINAPI *PInitializeSRWLock)(PSRWLOCK);
+
+typedef void (WINAPI *PAcquireSRWLockExclusive)(PSRWLOCK);
+typedef void (WINAPI *PReleaseSRWLockExclusive)(PSRWLOCK);
+
+typedef void (WINAPI *PAcquireSRWLockShared)(PSRWLOCK);
+typedef void (WINAPI *PReleaseSRWLockShared)(PSRWLOCK);
+
+
+class RWLockWindows :public RWLockWrapper
+{
+public:
+ RWLockWindows();
+ virtual ~RWLockWindows();
+
+ virtual void AcquireLockExclusive();
+ virtual void ReleaseLockExclusive();
+
+ virtual void AcquireLockShared();
+ virtual void ReleaseLockShared();
+
+protected:
+ virtual int Init();
+
+private:
+ // For native implementation.
+ static bool _winSupportRWLockPrimitive;
+ SRWLOCK _lock;
+
+ // Genric implementation, fallback if native is not supported.
+ CriticalSectionWrapper* _critSectPtr;
+ ConditionVariableWrapper* _readCondPtr;
+ ConditionVariableWrapper* _writeCondPtr;
+
+ int _readersActive;
+ bool _writerActive;
+ int _readersWaiting;
+ int _writersWaiting;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
diff --git a/src/system_wrappers/source/set_thread_name_win.h b/src/system_wrappers/source/set_thread_name_win.h
new file mode 100644
index 0000000..a46f4d6
--- /dev/null
+++ b/src/system_wrappers/source/set_thread_name_win.h
@@ -0,0 +1,43 @@
+/*
+ * Use of this source code is governed by the MICROSOFT LIMITED PUBLIC LICENSE
+ * copyright license which can be found in the LICENSE file in the
+ * third_party_mods/mslpl directory of the source tree or at
+ * http://msdn.microsoft.com/en-us/cc300389.aspx#P.
+ */
+/*
+ * The original code can be found here:
+ * http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
+
+namespace webrtc {
+
+struct THREADNAME_INFO
+{
+ DWORD dwType; // must be 0x1000
+ LPCSTR szName; // pointer to name (in user addr space)
+ DWORD dwThreadID; // thread ID (-1 = caller thread)
+ DWORD dwFlags; // reserved for future use, must be zero
+};
+
+void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try
+ {
+ RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
+ (ULONG_PTR*)&info);
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+} // namespace webrtc
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
diff --git a/src/system_wrappers/source/sleep.cc b/src/system_wrappers/source/sleep.cc
new file mode 100644
index 0000000..be85238
--- /dev/null
+++ b/src/system_wrappers/source/sleep.cc
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+// An OS-independent sleep function.
+
+#include "system_wrappers/interface/sleep.h"
+
+#ifdef _WIN32
+// For Sleep()
+#include <windows.h>
+#else
+// For nanosleep()
+#include <time.h>
+#endif
+
+namespace webrtc {
+
+void SleepMs(int msecs) {
+#ifdef _WIN32
+ Sleep(msecs);
+#else
+ struct timespec short_wait;
+ struct timespec remainder;
+ short_wait.tv_sec = msecs / 1000;
+ short_wait.tv_nsec = (msecs % 1000) * 1000 * 1000;
+ nanosleep(&short_wait, &remainder);
+#endif
+}
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/sort.cc b/src/system_wrappers/source/sort.cc
index f44b644..34aa437 100644
--- a/src/system_wrappers/source/sort.cc
+++ b/src/system_wrappers/source/sort.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -412,8 +412,6 @@
case TYPE_Float64:
StdSort<double>(data, numOfElements);
break;
- default:
- return -1;
}
#endif
return 0;
@@ -543,9 +541,9 @@
return StdKeySort<float>(data, key, numOfElements, sizeOfElement);
case TYPE_Float64:
return StdKeySort<double>(data, key, numOfElements, sizeOfElement);
- default:
- return -1;
}
+ assert(false);
+ return -1;
#endif
}
} // namespace webrtc
diff --git a/src/system_wrappers/source/system_wrappers.gyp b/src/system_wrappers/source/system_wrappers.gyp
index ce2438f..b530d6f 100644
--- a/src/system_wrappers/source/system_wrappers.gyp
+++ b/src/system_wrappers/source/system_wrappers.gyp
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+# 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
@@ -23,7 +23,8 @@
},
'sources': [
'../interface/aligned_malloc.h',
- '../interface/atomic32_wrapper.h',
+ '../interface/atomic32.h',
+ '../interface/compile_assert.h',
'../interface/condition_variable_wrapper.h',
'../interface/cpu_info.h',
'../interface/cpu_wrapper.h',
@@ -41,16 +42,16 @@
'../interface/rw_lock_wrapper.h',
'../interface/scoped_ptr.h',
'../interface/scoped_refptr.h',
+ '../interface/sleep.h',
'../interface/sort.h',
'../interface/static_instance.h',
'../interface/thread_wrapper.h',
'../interface/tick_util.h',
'../interface/trace.h',
'aligned_malloc.cc',
- 'atomic32.cc',
- 'atomic32_linux.h',
- 'atomic32_mac.h',
- 'atomic32_win.h',
+ 'atomic32_mac.cc',
+ 'atomic32_posix.cc',
+ 'atomic32_win.cc',
'condition_variable.cc',
'condition_variable_posix.cc',
'condition_variable_posix.h',
@@ -88,6 +89,7 @@
'rw_lock_posix.h',
'rw_lock_win.cc',
'rw_lock_win.h',
+ 'sleep.cc',
'sort.cc',
'thread.cc',
'thread_posix.cc',
@@ -109,6 +111,9 @@
},{
'sources!': [ 'data_log.cc', ],
},],
+ ['OS=="android"', {
+ 'dependencies': [ 'cpu_features_android', ],
+ }],
['OS=="linux"', {
'link_settings': {
'libraries': [ '-lrt', ],
@@ -118,6 +123,9 @@
'link_settings': {
'libraries': [ '$(SDKROOT)/System/Library/Frameworks/ApplicationServices.framework', ],
},
+ 'sources!': [
+ 'atomic32_posix.cc',
+ ],
}],
['OS=="win"', {
'link_settings': {
@@ -147,18 +155,41 @@
},
], # targets
'conditions': [
- ['build_with_chromium==0', {
+ ['OS=="android"', {
+ 'targets': [
+ {
+ 'variables': {
+ # Treat this as third-party code.
+ 'chromium_code': 0,
+ },
+ 'target_name': 'cpu_features_android',
+ 'type': '<(library)',
+ 'sources': [
+ 'android/cpu-features.c',
+ 'android/cpu-features.h',
+ # TODO(leozwang): Ideally we want to audomatically exclude .c files
+ # as with .cc files, gyp currently only excludes .cc files.
+ 'cpu_features_android.c',
+ ],
+ },
+ ],
+ }],
+ ['include_tests==1', {
'targets': [
{
'target_name': 'system_wrappers_unittests',
'type': 'executable',
'dependencies': [
'system_wrappers',
- '<(webrtc_root)/../testing/gtest.gyp:gtest',
- '<(webrtc_root)/../test/test.gyp:test_support_main',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(webrtc_root)/test/test.gyp:test_support_main',
],
'sources': [
+ 'condition_variable_unittest.cc',
'cpu_wrapper_unittest.cc',
+ 'cpu_measurement_harness.h',
+ 'cpu_measurement_harness.cc',
+ 'critical_section_unittest.cc',
'list_unittest.cc',
'map_unittest.cc',
'data_log_unittest.cc',
@@ -166,6 +197,9 @@
'data_log_helpers_unittest.cc',
'data_log_c_helpers_unittest.c',
'data_log_c_helpers_unittest.h',
+ 'thread_unittest.cc',
+ 'trace_unittest.cc',
+ 'unittest_utilities_unittest.cc',
],
'conditions': [
['enable_data_logging==1', {
@@ -176,7 +210,7 @@
],
},
], # targets
- }], # build_with_chromium
+ }], # include_tests
], # conditions
}
diff --git a/src/system_wrappers/source/thread_posix.cc b/src/system_wrappers/source/thread_posix.cc
index eb0e8f4..6334490 100644
--- a/src/system_wrappers/source/thread_posix.cc
+++ b/src/system_wrappers/source/thread_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -8,6 +8,40 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+// The state of a thread is controlled by the two member variables
+// _alive and _dead.
+// _alive represents the state the thread has been ordered to achieve.
+// It is set to true by the thread at startup, and is set to false by
+// other threads, using SetNotAlive() and Stop().
+// _dead represents the state the thread has achieved.
+// It is written by the thread encapsulated by this class only
+// (except at init). It is read only by the Stop() method.
+// The Run() method fires _event when it's started; this ensures that the
+// Start() method does not continue until after _dead is false.
+// This protects against premature Stop() calls from the creator thread, but
+// not from other threads.
+
+// Their transitions and states:
+// _alive _dead Set by
+// false true Constructor
+// true false Run() method entry
+// false any Run() method runFunction failure
+// any false Run() method exit (happens only with _alive false)
+// false any SetNotAlive
+// false any Stop Stop waits for _dead to become true.
+//
+// Summarized a different way:
+// Variable Writer Reader
+// _alive Constructor(false) Run.loop
+// Run.start(true)
+// Run.fail(false)
+// SetNotAlive(false)
+// Stop(false)
+//
+// _dead Constructor(true) Stop.loop
+// Run.start(false)
+// Run.exit(true)
+
#include "thread_posix.h"
#include <errno.h>
@@ -22,8 +56,13 @@
#include <sys/prctl.h>
#endif
-#include "event_wrapper.h"
-#include "trace.h"
+#if defined(WEBRTC_MAC)
+#include <mach/mach.h>
+#endif
+
+#include "system_wrappers/interface/critical_section_wrapper.h"
+#include "system_wrappers/interface/event_wrapper.h"
+#include "system_wrappers/interface/trace.h"
namespace webrtc {
extern "C"
@@ -35,17 +74,6 @@
}
}
-#if (defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID))
-static pid_t gettid()
-{
-#if defined(__NR_gettid)
- return syscall(__NR_gettid);
-#else
- return -1;
-#endif
-}
-#endif
-
ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
ThreadPriority prio, const char* threadName)
{
@@ -67,22 +95,37 @@
ThreadPriority prio, const char* threadName)
: _runFunction(func),
_obj(obj),
+ _crit_state(CriticalSectionWrapper::CreateCriticalSection()),
_alive(false),
_dead(true),
_prio(prio),
_event(EventWrapper::Create()),
- _setThreadName(false)
-{
-#ifdef WEBRTC_LINUX
- _linuxPid = -1;
+ _name(),
+ _setThreadName(false),
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ _pid(-1),
#endif
+ _attr(),
+ _thread(0)
+{
if (threadName != NULL)
{
_setThreadName = true;
strncpy(_name, threadName, kThreadMaxNameLength);
+ _name[kThreadMaxNameLength - 1] = '\0';
}
}
+uint32_t ThreadWrapper::GetThreadId() {
+#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
+ return static_cast<uint32_t>(syscall(__NR_gettid));
+#elif defined(WEBRTC_MAC)
+ return static_cast<uint32_t>(mach_thread_self());
+#else
+ return reinterpret_cast<uint32_t>(pthread_self());
+#endif
+}
+
int ThreadPosix::Construct()
{
int result = 0;
@@ -104,7 +147,6 @@
{
return -1;
}
-
return 0;
}
@@ -112,6 +154,7 @@
{
pthread_attr_destroy(&_attr);
delete _event;
+ delete _crit_state;
}
#define HAS_THREAD_ID !defined(MAC_IPHONE) && !defined(MAC_IPHONE_SIM) && \
@@ -180,8 +223,6 @@
case kRealtimePriority:
param.sched_priority = maxPrio - 1;
break;
- default:
- return false;
}
result = pthread_setschedparam(_thread, policy, ¶m);
if (result == EINVAL)
@@ -191,33 +232,40 @@
return true;
}
-#if (defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID))
+// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
+// SetAffinity on Android for now.
+#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processorNumbers,
- const unsigned int amountOfProcessors)
-{
- if (!processorNumbers || (amountOfProcessors == 0))
- {
- return false;
- }
+ const unsigned int amountOfProcessors) {
+ if (!processorNumbers || (amountOfProcessors == 0)) {
+ return false;
+ }
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
- cpu_set_t mask;
- CPU_ZERO(&mask);
-
- for(unsigned int processor = 0;
- processor < amountOfProcessors;
- processor++)
- {
- CPU_SET(processorNumbers[processor], &mask);
- }
- const int result = sched_setaffinity(_linuxPid, (unsigned int)sizeof(mask),
- &mask);
- if (result != 0)
- {
- return false;
-
- }
- return true;
+ for (unsigned int processor = 0;
+ processor < amountOfProcessors;
+ processor++) {
+ CPU_SET(processorNumbers[processor], &mask);
+ }
+#if defined(WEBRTC_ANDROID)
+ // Android.
+ const int result = syscall(__NR_sched_setaffinity,
+ _pid,
+ sizeof(mask),
+ &mask);
+#else
+ // "Normal" Linux.
+ const int result = sched_setaffinity(_pid,
+ sizeof(mask),
+ &mask);
+#endif
+ if (result != 0) {
+ return false;
+ }
+ return true;
}
+
#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
@@ -230,6 +278,7 @@
void ThreadPosix::SetNotAlive()
{
+ CriticalSectionScoped cs(_crit_state);
_alive = false;
}
@@ -249,18 +298,27 @@
bool ThreadPosix::Stop()
{
- _alive = false;
+ bool dead = false;
+ {
+ CriticalSectionScoped cs(_crit_state);
+ _alive = false;
+ dead = _dead;
+ }
// TODO (hellner) why not use an event here?
// Wait up to 10 seconds for the thread to terminate
- for (int i = 0; i < 1000 && !_dead; i++)
+ for (int i = 0; i < 1000 && !dead; i++)
{
timespec t;
t.tv_sec = 0;
t.tv_nsec = 10*1000*1000;
nanosleep(&t, NULL);
+ {
+ CriticalSectionScoped cs(_crit_state);
+ dead = _dead;
+ }
}
- if (_dead)
+ if (dead)
{
return true;
}
@@ -272,13 +330,13 @@
void ThreadPosix::Run()
{
- _alive = true;
- _dead = false;
-#ifdef WEBRTC_LINUX
- if(_linuxPid == -1)
{
- _linuxPid = gettid();
+ CriticalSectionScoped cs(_crit_state);
+ _alive = true;
+ _dead = false;
}
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ _pid = GetThreadId();
#endif
// The event the Start() is waiting for.
_event->Set();
@@ -286,38 +344,38 @@
if (_setThreadName)
{
#ifdef WEBRTC_LINUX
- WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
- "Thread with id:%d name:%s started ", _linuxPid, _name);
prctl(PR_SET_NAME, (unsigned long)_name, 0, 0, 0);
-#else
+#endif
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
"Thread with name:%s started ", _name);
-#endif
- }else
+ } else
{
-#ifdef WEBRTC_LINUX
- WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
- "Thread with id:%d without name started", _linuxPid);
-#else
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
"Thread without name started");
-#endif
}
+ bool alive = true;
do
{
if (_runFunction)
{
if (!_runFunction(_obj))
{
- _alive = false;
+ alive = false;
}
}
else
{
- _alive = false;
+ alive = false;
+ }
+ {
+ CriticalSectionScoped cs(_crit_state);
+ if (!alive) {
+ _alive = false;
+ }
+ alive = _alive;
}
}
- while (_alive);
+ while (alive);
if (_setThreadName)
{
@@ -335,6 +393,9 @@
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
"Thread without name stopped");
}
- _dead = true;
+ {
+ CriticalSectionScoped cs(_crit_state);
+ _dead = true;
+ }
}
} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_posix.h b/src/system_wrappers/source/thread_posix.h
index f664a52..45489a8 100644
--- a/src/system_wrappers/source/thread_posix.h
+++ b/src/system_wrappers/source/thread_posix.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -15,6 +15,8 @@
#include <pthread.h>
namespace webrtc {
+
+class CriticalSectionWrapper;
class EventWrapper;
class ThreadPosix : public ThreadWrapper
@@ -47,6 +49,7 @@
ThreadObj _obj;
// internal state
+ CriticalSectionWrapper* _crit_state; // Protects _alive and _dead
bool _alive;
bool _dead;
ThreadPriority _prio;
@@ -57,12 +60,11 @@
bool _setThreadName;
// handle to thread
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ pid_t _pid;
+#endif
pthread_attr_t _attr;
pthread_t _thread;
-#ifdef WEBRTC_LINUX
- pid_t _linuxPid;
-#endif
-
};
} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_unittest.cc b/src/system_wrappers/source/thread_unittest.cc
new file mode 100644
index 0000000..361424a
--- /dev/null
+++ b/src/system_wrappers/source/thread_unittest.cc
@@ -0,0 +1,96 @@
+/*
+ * 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 "system_wrappers/interface/thread_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+const int kLogTrace = 0;
+
+class TestTraceCallback : public TraceCallback {
+ public:
+ virtual void Print(const TraceLevel level,
+ const char* traceString,
+ const int length) {
+ if (traceString) {
+ char* cmd_print = new char[length+1];
+ memcpy(cmd_print, traceString, length);
+ cmd_print[length] = '\0';
+ printf("%s\n", cmd_print);
+ fflush(stdout);
+ delete[] cmd_print;
+ }
+ }
+};
+
+class ThreadTest : public ::testing::Test {
+ public:
+ ThreadTest() {
+ StartTrace();
+ }
+ ~ThreadTest() {
+ StopTrace();
+ }
+
+ private:
+ void StartTrace() {
+ if (kLogTrace) {
+ Trace::CreateTrace();
+ Trace::SetLevelFilter(webrtc::kTraceAll);
+ Trace::SetTraceCallback(&trace_);
+ }
+ }
+
+ void StopTrace() {
+ if (kLogTrace) {
+ Trace::ReturnTrace();
+ }
+ }
+
+ TestTraceCallback trace_;
+};
+
+// Function that does nothing, and reports success.
+bool NullRunFunction(void* /* obj */) {
+ return true;
+}
+
+TEST_F(ThreadTest, StartStop) {
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&NullRunFunction);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread->Start(id));
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+}
+
+// Function that sets a boolean.
+bool SetFlagRunFunction(void* obj) {
+ bool* obj_as_bool = static_cast<bool*> (obj);
+ *obj_as_bool = true;
+ return true;
+}
+
+TEST_F(ThreadTest, RunFunctionIsCalled) {
+ bool flag = false;
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&SetFlagRunFunction,
+ &flag);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread->Start(id));
+ // At this point, the flag may be either true or false.
+ EXPECT_TRUE(thread->Stop());
+ // We expect the thread to have run at least once.
+ EXPECT_TRUE(flag);
+ delete thread;
+}
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_win.cc b/src/system_wrappers/source/thread_win.cc
new file mode 100644
index 0000000..07c586a
--- /dev/null
+++ b/src/system_wrappers/source/thread_win.cc
@@ -0,0 +1,233 @@
+/*
+ * 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 "thread_win.h"
+
+#include <assert.h>
+#include <process.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include "set_thread_name_win.h"
+#include "trace.h"
+
+namespace webrtc {
+ThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
+ ThreadPriority prio, const char* threadName)
+ : ThreadWrapper(),
+ _runFunction(func),
+ _obj(obj),
+ _alive(false),
+ _dead(true),
+ _doNotCloseHandle(false),
+ _prio(prio),
+ _event(NULL),
+ _thread(NULL),
+ _id(0),
+ _name(),
+ _setThreadName(false)
+{
+ _event = EventWrapper::Create();
+ _critsectStop = CriticalSectionWrapper::CreateCriticalSection();
+ if (threadName != NULL)
+ {
+ // Set the thread name to appear in the VS debugger.
+ _setThreadName = true;
+ strncpy(_name, threadName, kThreadMaxNameLength);
+ }
+}
+
+ThreadWindows::~ThreadWindows()
+{
+#ifdef _DEBUG
+ assert(!_alive);
+#endif
+ if (_thread)
+ {
+ CloseHandle(_thread);
+ }
+ if(_event)
+ {
+ delete _event;
+ }
+ if(_critsectStop)
+ {
+ delete _critsectStop;
+ }
+}
+
+uint32_t ThreadWrapper::GetThreadId() {
+ return GetCurrentThreadId();
+}
+
+unsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter)
+{
+ static_cast<ThreadWindows*>(lpParameter)->Run();
+ return 0;
+}
+
+bool ThreadWindows::Start(unsigned int& threadID)
+{
+ _doNotCloseHandle = false;
+
+ // Set stack size to 1M
+ _thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0,
+ &threadID);
+ if(_thread == NULL)
+ {
+ return false;
+ }
+ _id = threadID;
+ _event->Wait(INFINITE);
+
+ switch(_prio)
+ {
+ case kLowPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
+ break;
+ case kNormalPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
+ break;
+ case kHighPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ break;
+ case kHighestPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
+ break;
+ case kRealtimePriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL);
+ break;
+ };
+ return true;
+}
+
+bool ThreadWindows::SetAffinity(const int* processorNumbers,
+ const unsigned int amountOfProcessors)
+{
+ DWORD_PTR processorBitMask = 0;
+ for(unsigned int processorIndex = 0;
+ processorIndex < amountOfProcessors;
+ processorIndex++)
+ {
+ // Convert from an array with processor numbers to a bitmask
+ // Processor numbers start at zero.
+ // TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='?
+ // Or even better |=
+ processorBitMask = 1 << processorNumbers[processorIndex];
+ }
+ return SetThreadAffinityMask(_thread,processorBitMask) != 0;
+}
+
+void ThreadWindows::SetNotAlive()
+{
+ _alive = false;
+}
+
+bool ThreadWindows::Shutdown()
+{
+ DWORD exitCode = 0;
+ BOOL ret = TRUE;
+ if (_thread)
+ {
+ ret = TerminateThread(_thread, exitCode);
+ _alive = false;
+ _dead = true;
+ _thread = NULL;
+ }
+ return ret == TRUE;
+}
+
+bool ThreadWindows::Stop()
+{
+ _critsectStop->Enter();
+ // Prevents the handle from being closed in ThreadWindows::Run()
+ _doNotCloseHandle = true;
+ _alive = false;
+ bool signaled = false;
+ if (_thread && !_dead)
+ {
+ _critsectStop->Leave();
+ // Wait up to 2 seconds for the thread to complete.
+ if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000))
+ {
+ signaled = true;
+ }
+ _critsectStop->Enter();
+ }
+ if (_thread)
+ {
+ CloseHandle(_thread);
+ _thread = NULL;
+ }
+ _critsectStop->Leave();
+
+ if (_dead || signaled)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void ThreadWindows::Run()
+{
+ _alive = true;
+ _dead = false;
+ _event->Set();
+
+ // All tracing must be after _event->Set to avoid deadlock in Trace.
+ if (_setThreadName)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread with name:%s started ", _name);
+ SetThreadName(-1, _name); // -1, set thread name for the calling thread.
+ }else
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread without name started");
+ }
+
+ do
+ {
+ if (_runFunction)
+ {
+ if (!_runFunction(_obj))
+ {
+ _alive = false;
+ }
+ } else {
+ _alive = false;
+ }
+ } while(_alive);
+
+ if (_setThreadName)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread with name:%s stopped", _name);
+ } else {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id,
+ "Thread without name stopped");
+ }
+
+ _critsectStop->Enter();
+
+ if (_thread && !_doNotCloseHandle)
+ {
+ HANDLE thread = _thread;
+ _thread = NULL;
+ CloseHandle(thread);
+ }
+ _dead = true;
+
+ _critsectStop->Leave();
+};
+} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_win.h b/src/system_wrappers/source/thread_win.h
new file mode 100644
index 0000000..4fd7523
--- /dev/null
+++ b/src/system_wrappers/source/thread_win.h
@@ -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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
+
+#include "thread_wrapper.h"
+#include "event_wrapper.h"
+#include "critical_section_wrapper.h"
+
+#include <windows.h>
+
+namespace webrtc {
+
+class ThreadWindows : public ThreadWrapper
+{
+public:
+ ThreadWindows(ThreadRunFunction func, ThreadObj obj, ThreadPriority prio,
+ const char* threadName);
+ virtual ~ThreadWindows();
+
+ virtual bool Start(unsigned int& id);
+ bool SetAffinity(const int* processorNumbers,
+ const unsigned int amountOfProcessors);
+ virtual bool Stop();
+ virtual void SetNotAlive();
+
+ static unsigned int WINAPI StartThread(LPVOID lpParameter);
+
+ virtual bool Shutdown();
+
+protected:
+ virtual void Run();
+
+private:
+ ThreadRunFunction _runFunction;
+ ThreadObj _obj;
+
+ bool _alive;
+ bool _dead;
+
+ // TODO (hellner)
+ // _doNotCloseHandle member seem pretty redundant. Should be able to remove
+ // it. Basically it should be fine to reclaim the handle when calling stop
+ // and in the destructor.
+ bool _doNotCloseHandle;
+ ThreadPriority _prio;
+ EventWrapper* _event;
+ CriticalSectionWrapper* _critsectStop;
+
+ HANDLE _thread;
+ unsigned int _id;
+ char _name[kThreadMaxNameLength];
+ bool _setThreadName;
+
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
diff --git a/src/system_wrappers/source/trace_impl.cc b/src/system_wrappers/source/trace_impl.cc
index 1156519..c6d9296 100644
--- a/src/system_wrappers/source/trace_impl.cc
+++ b/src/system_wrappers/source/trace_impl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -17,17 +17,16 @@
#include "trace_win.h"
#else
#include <stdio.h>
-#include <time.h>
#include <stdarg.h>
#include "trace_posix.h"
#endif // _WIN32
+#include "system_wrappers/interface/sleep.h"
+
#define KEY_LEN_CHARS 31
#ifdef _WIN32
- #pragma warning(disable:4355)
-// VS 2005: Disable warnings for default initialized arrays.
- #pragma warning(disable:4351)
+#pragma warning(disable:4355)
#endif // _WIN32
namespace webrtc {
@@ -94,7 +93,7 @@
for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
{
_messageQueue[m][n] = new
- WebRtc_Word8[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
+ char[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
}
}
}
@@ -108,14 +107,7 @@
// TODO (hellner): why not use condition variables to do this? Or let the
// worker thread die and let this thread flush remaining
// messages?
-#ifdef _WIN32
- Sleep(10);
-#else
- timespec t;
- t.tv_sec = 0;
- t.tv_nsec = 10*1000000;
- nanosleep(&t,NULL);
-#endif
+ SleepMs(10);
_thread.SetNotAlive();
// Make sure the thread finishes as quickly as possible (instead of having
@@ -147,6 +139,12 @@
}
}
+WebRtc_Word32 TraceImpl::AddThreadId(char* traceMessage) const {
+ WebRtc_UWord32 threadId = ThreadWrapper::GetThreadId();
+ // Messages is 12 characters.
+ return sprintf(traceMessage, "%10u; ", threadId);
+}
+
WebRtc_Word32 TraceImpl::AddLevel(char* szMessage, const TraceLevel level) const
{
switch (level)
@@ -277,9 +275,6 @@
sprintf(traceMessage, " VIDEO PROC:%5ld %5ld;", idEngine,
idChannel);
break;
- default:
- assert(false);
- return 0;
}
} else {
switch (module)
@@ -335,16 +330,13 @@
case kTraceVideoPreocessing:
sprintf (traceMessage, " VIDEO PROC:%11ld;", idl);
break;
- default:
- assert(false);
- return 0;
}
}
// All messages are 25 characters.
return 25;
}
-WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
+WebRtc_Word32 TraceImpl::SetTraceFileImpl(const char* fileNameUTF8,
const bool addFileCounter)
{
CriticalSectionScoped lock(_critsectInterface);
@@ -358,7 +350,7 @@
{
_fileCountText = 1;
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
CreateFileName(fileNameUTF8, fileNameWithCounterUTF8,
_fileCountText);
if(_traceFile.OpenFile(fileNameWithCounterUTF8, false, false,
@@ -379,7 +371,7 @@
}
WebRtc_Word32 TraceImpl::TraceFileImpl(
- WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])
+ char fileNameUTF8[FileWrapper::kMaxFileNameSize])
{
CriticalSectionScoped lock(_critsectInterface);
return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize);
@@ -429,8 +421,14 @@
void TraceImpl::AddMessageToList(
const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
const WebRtc_UWord16 length,
- const TraceLevel level)
-{
+ const TraceLevel level) {
+#ifdef WEBRTC_DIRECT_TRACE
+ if (_callback) {
+ _callback->Print(level, traceMessage, length);
+ }
+ return;
+#endif
+
CriticalSectionScoped lock(_critsectArray);
if(_nextFreeIdx[_activeQueue] >= WEBRTC_TRACE_MAX_QUEUE)
@@ -550,8 +548,8 @@
_traceFile.Rewind();
} else
{
- WebRtc_Word8 oldFileName[FileWrapper::kMaxFileNameSize];
- WebRtc_Word8 newFileName[FileWrapper::kMaxFileNameSize];
+ char oldFileName[FileWrapper::kMaxFileNameSize];
+ char newFileName[FileWrapper::kMaxFileNameSize];
// get current name
_traceFile.FileName(oldFileName,
@@ -571,7 +569,7 @@
}
if(_rowCountText == 0)
{
- WebRtc_Word8 message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
+ char message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
WebRtc_Word32 length = AddDateTimeInfo(message);
if(length != -1)
{
@@ -637,7 +635,7 @@
ackLen += len;
len = AddThreadId(meassagePtr);
- if(len == -1)
+ if(len < 0)
{
return;
}
@@ -663,8 +661,8 @@
}
bool TraceImpl::UpdateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const
{
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
@@ -706,8 +704,8 @@
}
bool TraceImpl::CreateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const
{
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
@@ -760,7 +758,7 @@
return 0;
}
-WebRtc_Word32 Trace::TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize])
+WebRtc_Word32 Trace::TraceFile(char fileName[FileWrapper::kMaxFileNameSize])
{
TraceImpl* trace = TraceImpl::GetTrace();
if(trace)
@@ -772,7 +770,7 @@
return -1;
}
-WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* fileName,
+WebRtc_Word32 Trace::SetTraceFile(const char* fileName,
const bool addFileCounter)
{
TraceImpl* trace = TraceImpl::GetTrace();
diff --git a/src/system_wrappers/source/trace_impl.h b/src/system_wrappers/source/trace_impl.h
index 455a3d5..2b85813 100644
--- a/src/system_wrappers/source/trace_impl.h
+++ b/src/system_wrappers/source/trace_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -49,10 +49,10 @@
static TraceImpl* CreateInstance();
static TraceImpl* GetTrace(const TraceLevel level = kTraceAll);
- WebRtc_Word32 SetTraceFileImpl(const WebRtc_Word8* fileName,
+ WebRtc_Word32 SetTraceFileImpl(const char* fileName,
const bool addFileCounter);
WebRtc_Word32 TraceFileImpl(
- WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize]);
+ char fileName[FileWrapper::kMaxFileNameSize]);
WebRtc_Word32 SetTraceCallbackImpl(TraceCallback* callback);
@@ -69,8 +69,9 @@
static TraceImpl* StaticInstance(CountOperation count_operation,
const TraceLevel level = kTraceAll);
+ WebRtc_Word32 AddThreadId(char* traceMessage) const;
+
// OS specific implementations
- virtual WebRtc_Word32 AddThreadId(char* traceMessage) const = 0;
virtual WebRtc_Word32 AddTime(char* traceMessage,
const TraceLevel level) const = 0;
@@ -98,13 +99,13 @@
const TraceLevel level);
bool UpdateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const;
bool CreateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const;
void WriteToFile();
@@ -123,7 +124,7 @@
WebRtc_UWord16 _nextFreeIdx[WEBRTC_TRACE_NUM_ARRAY];
TraceLevel _level[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
WebRtc_UWord16 _length[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
- WebRtc_Word8* _messageQueue[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
+ char* _messageQueue[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
WebRtc_UWord8 _activeQueue;
};
} // namespace webrtc
diff --git a/src/system_wrappers/source/trace_impl_no_op.cc b/src/system_wrappers/source/trace_impl_no_op.cc
index 1752871..e74d901 100644
--- a/src/system_wrappers/source/trace_impl_no_op.cc
+++ b/src/system_wrappers/source/trace_impl_no_op.cc
@@ -31,12 +31,12 @@
}
WebRtc_Word32 Trace::TraceFile(
- WebRtc_Word8 /*fileName*/[1024])
+ char/*fileName*/[1024])
{
return -1;
}
-WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* /*fileName*/,
+WebRtc_Word32 Trace::SetTraceFile(const char* /*fileName*/,
const bool /*addFileCounter*/)
{
return -1;
diff --git a/src/system_wrappers/source/trace_posix.cc b/src/system_wrappers/source/trace_posix.cc
index 198c434..1b8dd93 100644
--- a/src/system_wrappers/source/trace_posix.cc
+++ b/src/system_wrappers/source/trace_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -14,10 +14,8 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <sys/time.h>
#include <time.h>
-#ifdef __linux__
- #include <sys/syscall.h>
-#endif
#ifdef WEBRTC_ANDROID
#include <pthread.h>
#else
@@ -41,8 +39,9 @@
namespace webrtc {
TracePosix::TracePosix()
{
- _prevAPITickCount = time(NULL);
- _prevTickCount = _prevAPITickCount;
+ struct timeval systemTimeHighRes;
+ gettimeofday(&systemTimeHighRes, 0);
+ _prevAPITickCount = _prevTickCount = systemTimeHighRes.tv_sec;
}
TracePosix::~TracePosix()
@@ -50,69 +49,47 @@
StopThread();
}
-WebRtc_Word32 TracePosix::AddThreadId(char* traceMessage) const {
-#ifdef __linux__
- pid_t threadId = (pid_t) syscall(__NR_gettid);
- sprintf(traceMessage, "%10d; ", threadId);
-#else
- WebRtc_UWord64 threadId = (WebRtc_UWord64)pthread_self();
- sprintf(traceMessage, "%10llu; ",
- static_cast<long long unsigned int>(threadId));
-#endif
- // 12 bytes are written.
- return 12;
-}
-
WebRtc_Word32 TracePosix::AddTime(char* traceMessage,
const TraceLevel level) const
{
- time_t dwCurrentTimeInSeconds = time(NULL);
- struct tm systemTime;
- gmtime_r(&dwCurrentTimeInSeconds, &systemTime);
-
- if(level == kTraceApiCall)
+ struct timeval systemTimeHighRes;
+ if (gettimeofday(&systemTimeHighRes, 0) == -1)
{
- WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevTickCount;
- _prevTickCount = dwCurrentTimeInSeconds;
-
- if(_prevTickCount == 0)
- {
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 0x0fffffff)
- {
- // Either wraparound or data race.
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 99999)
- {
- dwDeltaTime = 99999;
- }
-
- sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
- systemTime.tm_min, systemTime.tm_sec, 0,
- static_cast<unsigned long>(dwDeltaTime));
- } else {
- WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevAPITickCount;
- _prevAPITickCount = dwCurrentTimeInSeconds;
- if(_prevAPITickCount == 0)
- {
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 0x0fffffff)
- {
- // Either wraparound or data race.
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 99999)
- {
- dwDeltaTime = 99999;
- }
- sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
- systemTime.tm_min, systemTime.tm_sec, 0,
- static_cast<unsigned long>(dwDeltaTime));
+ return -1;
}
- // Messages is 22 characters.
+ struct tm buffer;
+ const struct tm* systemTime =
+ localtime_r(&systemTimeHighRes.tv_sec, &buffer);
+
+ const WebRtc_UWord32 ms_time = systemTimeHighRes.tv_usec / 1000;
+ WebRtc_UWord32 prevTickCount = 0;
+ if (level == kTraceApiCall)
+ {
+ prevTickCount = _prevTickCount;
+ _prevTickCount = ms_time;
+ } else {
+ prevTickCount = _prevAPITickCount;
+ _prevAPITickCount = ms_time;
+ }
+ WebRtc_UWord32 dwDeltaTime = ms_time - prevTickCount;
+ if (prevTickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if (dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
+ }
+
+ sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime->tm_hour,
+ systemTime->tm_min, systemTime->tm_sec, ms_time,
+ static_cast<unsigned long>(dwDeltaTime));
+ // Messages are 22 characters.
return 22;
}
@@ -127,7 +104,8 @@
{
time_t t;
time(&t);
- sprintf(traceMessage, "Local Date: %s", ctime(&t));
+ char buffer[26]; // man ctime says buffer should have room for >=26 bytes.
+ sprintf(traceMessage, "Local Date: %s", ctime_r(&t, buffer));
WebRtc_Word32 len = static_cast<WebRtc_Word32>(strlen(traceMessage));
if ('\n' == traceMessage[len - 1])
diff --git a/src/system_wrappers/source/trace_posix.h b/src/system_wrappers/source/trace_posix.h
index 099bcc8..8c37cd2 100644
--- a/src/system_wrappers/source/trace_posix.h
+++ b/src/system_wrappers/source/trace_posix.h
@@ -21,7 +21,6 @@
TracePosix();
virtual ~TracePosix();
- virtual WebRtc_Word32 AddThreadId(char *traceMessage) const;
virtual WebRtc_Word32 AddTime(char* traceMessage,
const TraceLevel level) const;
diff --git a/src/system_wrappers/source/trace_unittest.cc b/src/system_wrappers/source/trace_unittest.cc
new file mode 100644
index 0000000..982e715
--- /dev/null
+++ b/src/system_wrappers/source/trace_unittest.cc
@@ -0,0 +1,57 @@
+/*
+ * 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 "system_wrappers/interface/trace.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/source/cpu_measurement_harness.h"
+#include "testsupport/fileutils.h"
+
+using webrtc::CpuMeasurementHarness;
+using webrtc::Trace;
+using webrtc::kTraceWarning;
+using webrtc::kTraceUtility;
+
+class Logger : public webrtc::CpuTarget {
+ public:
+ Logger() {
+ Trace::CreateTrace();
+ std::string trace_file = webrtc::test::OutputPath() +
+ "trace_unittest.txt";
+ Trace::SetTraceFile(trace_file.c_str());
+ Trace::SetLevelFilter(webrtc::kTraceAll);
+ }
+ virtual ~Logger() {
+ Trace::ReturnTrace();
+ }
+
+ virtual bool DoWork() {
+ // Use input paremeters to WEBRTC_TRACE that are not likely to be removed
+ // in future code. E.g. warnings will likely be kept and this file is in
+ // utility so it should use kTraceUtility.
+ WEBRTC_TRACE(kTraceWarning, kTraceUtility, 0, "Log line");
+ return true;
+ }
+};
+
+// This test is disabled because it measures CPU usage. This is flaky because
+// the CPU usage for a machine may spike due to OS or other application.
+TEST(TraceTest, DISABLED_CpuUsage) {
+ Logger logger;
+ const int periodicity_ms = 1;
+ const int iterations_per_period = 10;
+ const int duration_ms = 1000;
+ CpuMeasurementHarness* cpu_harness =
+ CpuMeasurementHarness::Create(&logger, periodicity_ms,
+ iterations_per_period, duration_ms);
+ cpu_harness->Run();
+ const int average_cpu = cpu_harness->AverageCpu();
+ EXPECT_GE(5, average_cpu);
+}
diff --git a/src/system_wrappers/source/trace_win.cc b/src/system_wrappers/source/trace_win.cc
new file mode 100644
index 0000000..f81ed8b
--- /dev/null
+++ b/src/system_wrappers/source/trace_win.cc
@@ -0,0 +1,131 @@
+/*
+ * 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 "trace_win.h"
+
+#include <cassert>
+#include <stdarg.h>
+
+#include "Mmsystem.h"
+
+#if defined(_DEBUG)
+ #define BUILDMODE "d"
+#elif defined(DEBUG)
+ #define BUILDMODE "d"
+#elif defined(NDEBUG)
+ #define BUILDMODE "r"
+#else
+ #define BUILDMODE "?"
+#endif
+#define BUILDTIME __TIME__
+#define BUILDDATE __DATE__
+// Example: "Oct 10 2002 12:05:30 r"
+#define BUILDINFO BUILDDATE " " BUILDTIME " " BUILDMODE
+
+namespace webrtc {
+TraceWindows::TraceWindows()
+ : _prevAPITickCount(0),
+ _prevTickCount(0)
+{
+}
+
+TraceWindows::~TraceWindows()
+{
+ StopThread();
+}
+
+WebRtc_Word32 TraceWindows::AddTime(char* traceMessage,
+ const TraceLevel level) const
+{
+ WebRtc_UWord32 dwCurrentTime = timeGetTime();
+ SYSTEMTIME systemTime;
+ GetSystemTime(&systemTime);
+
+ if(level == kTraceApiCall)
+ {
+ WebRtc_UWord32 dwDeltaTime = dwCurrentTime- _prevTickCount;
+ _prevTickCount = dwCurrentTime;
+
+ if(_prevTickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
+ }
+
+ sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
+ systemTime.wMinute, systemTime.wSecond,
+ systemTime.wMilliseconds, dwDeltaTime);
+ } else {
+ WebRtc_UWord32 dwDeltaTime = dwCurrentTime - _prevAPITickCount;
+ _prevAPITickCount = dwCurrentTime;
+
+ if(_prevAPITickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
+ }
+ sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
+ systemTime.wMinute, systemTime.wSecond,
+ systemTime.wMilliseconds, dwDeltaTime);
+ }
+ // Messages is 12 characters.
+ return 22;
+}
+
+WebRtc_Word32 TraceWindows::AddBuildInfo(char* traceMessage) const
+{
+ // write data and time to text file
+ sprintf(traceMessage, "Build info: %s", BUILDINFO);
+ // Include NULL termination (hence + 1).
+ return static_cast<WebRtc_Word32>(strlen(traceMessage)+1);
+}
+
+WebRtc_Word32 TraceWindows::AddDateTimeInfo(char* traceMessage) const
+{
+ _prevAPITickCount = timeGetTime();
+ _prevTickCount = _prevAPITickCount;
+
+ SYSTEMTIME sysTime;
+ GetLocalTime (&sysTime);
+
+ TCHAR szDateStr[20];
+ TCHAR szTimeStr[20];
+
+ // Create date string (e.g. Apr 04 2002)
+ GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("MMM dd yyyy"),
+ szDateStr, 20);
+
+ // Create time string (e.g. 15:32:08)
+ GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("HH':'mm':'ss"),
+ szTimeStr, 20);
+
+ sprintf(traceMessage, "Local Date: %s Local Time: %s", szDateStr,
+ szTimeStr);
+
+ // Include NULL termination (hence + 1).
+ return static_cast<WebRtc_Word32>(strlen(traceMessage)+ 1);
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/trace_win.h b/src/system_wrappers/source/trace_win.h
new file mode 100644
index 0000000..803198e
--- /dev/null
+++ b/src/system_wrappers/source/trace_win.h
@@ -0,0 +1,36 @@
+/*
+ * 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_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
+
+#include "trace_impl.h"
+#include <stdio.h>
+#include <windows.h>
+
+namespace webrtc {
+class TraceWindows : public TraceImpl
+{
+public:
+ TraceWindows();
+ virtual ~TraceWindows();
+
+ virtual WebRtc_Word32 AddTime(char* traceMessage,
+ const TraceLevel level) const;
+
+ virtual WebRtc_Word32 AddBuildInfo(char* traceMessage) const;
+ virtual WebRtc_Word32 AddDateTimeInfo(char* traceMessage) const;
+private:
+ volatile mutable WebRtc_UWord32 _prevAPITickCount;
+ volatile mutable WebRtc_UWord32 _prevTickCount;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
diff --git a/src/system_wrappers/source/unittest_utilities.h b/src/system_wrappers/source/unittest_utilities.h
new file mode 100644
index 0000000..771d798
--- /dev/null
+++ b/src/system_wrappers/source/unittest_utilities.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
+
+// This file contains utilities that make it simpler to write unittests
+// that are appropriate for the system_wrappers classes.
+
+#include <stdio.h>
+#include <string.h>
+
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+class TestTraceCallback : public TraceCallback {
+ public:
+ virtual void Print(const TraceLevel level,
+ const char* traceString,
+ const int length) {
+ if (traceString) {
+ char* cmd_print = new char[length+1];
+ memcpy(cmd_print, traceString, length);
+ cmd_print[length] = '\0';
+ printf("%s\n", cmd_print);
+ fflush(stdout);
+ delete[] cmd_print;
+ }
+ }
+};
+
+// A class that turns on tracing to stdout at the beginning of the test,
+// and turns it off once the test is finished.
+// Intended usage:
+// class SomeTest : public ::testing::Test {
+// protected:
+// SomeTest()
+// : trace_(false) {} // Change to true to turn on tracing.
+// private:
+// ScopedTracing trace_;
+// }
+class ScopedTracing {
+ public:
+ explicit ScopedTracing(bool logOn) {
+ logging_ = logOn;
+ StartTrace();
+ }
+
+ ~ScopedTracing() {
+ StopTrace();
+ }
+
+ private:
+ void StartTrace() {
+ if (logging_) {
+ Trace::CreateTrace();
+ Trace::SetLevelFilter(webrtc::kTraceAll);
+ Trace::SetTraceCallback(&trace_);
+ }
+ }
+
+ void StopTrace() {
+ if (logging_) {
+ Trace::ReturnTrace();
+ }
+ }
+
+ private:
+ bool logging_;
+ TestTraceCallback trace_;
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
diff --git a/src/system_wrappers/source/unittest_utilities_unittest.cc b/src/system_wrappers/source/unittest_utilities_unittest.cc
new file mode 100644
index 0000000..6e9a0c6
--- /dev/null
+++ b/src/system_wrappers/source/unittest_utilities_unittest.cc
@@ -0,0 +1,34 @@
+/*
+ * 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 "system_wrappers/source/unittest_utilities.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+// These tests merely check that the code compiles and that no
+// fatal accidents happen when logging.
+TEST(UnittestUtilities, TraceOn) {
+ ScopedTracing trace(true);
+ WEBRTC_TRACE(kTraceInfo, kTraceUtility, 0, "Log line that should appear");
+ // TODO(hta): Verify that output appears.
+ // Note - output is written on another thread, so can take time to appear.
+}
+
+TEST(UnittestUtilities, TraceOff) {
+ ScopedTracing trace(false);
+ WEBRTC_TRACE(kTraceInfo, kTraceUtility, 0,
+ "Log line that should not appear");
+ // TODO(hta): Verify that no output appears.
+}
+
+} // namespace webrtc