Support for Signal calls.

Merge in RedPhone

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-09-09 13:54:29 -07:00
parent 3d4ae60d81
commit d83a3d71bc
2585 changed files with 803492 additions and 45 deletions

View File

@@ -0,0 +1,5 @@
# These are for the common case of adding or renaming files. If you're doing
# structural changes, please get a review from a reviewer in this file.
per-file *.gyp=*
per-file *.gypi=*

View File

@@ -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.
*
*/
int16_t 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
*/
int16_t 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
*/
int16_t 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
*/
int16_t 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
*/
int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
int16_t 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
*/
int16_t WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
const int16_t *speechIn,
int16_t *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
int16_t WebRtcIsacfix_EncodeNb(ISACFIX_MainStruct *ISAC_main_inst,
const int16_t *speechIn,
int16_t *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
*/
int16_t 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
*/
int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
const uint16_t *encoded,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t 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
*/
int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
const uint16_t *encoded,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t 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
*/
int16_t WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
const uint16_t *encoded,
int16_t len,
int16_t *decoded,
int16_t *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
int16_t WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
const uint16_t *encoded,
int16_t len,
int16_t *decoded,
int16_t *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
int16_t WebRtcIsacfix_DecodePlcNb(ISACFIX_MainStruct *ISAC_main_inst,
int16_t *decoded,
int16_t 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
*/
int16_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct *ISAC_main_inst,
int16_t *decoded,
int16_t 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)
*
*/
int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
int16_t* 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
*/
int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst,
int16_t rate,
int16_t 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
*/
int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst,
int16_t rateBPS,
int16_t frameSizeMs,
int16_t 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
*/
int16_t 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
*/
int32_t 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
*/
int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst,
int16_t 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
*/
int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst,
int32_t 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
*/
int16_t 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
*/
int16_t 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
*/
int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst,
int16_t bweIndex,
float scale,
int16_t *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.
*
*/
int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
int16_t* 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.
*
*/
int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
int16_t 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
*
*/
int16_t WebRtcIsacfix_ReadBwIndex(const int16_t* encoded,
int16_t* 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
*/
int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst);
#if defined(__cplusplus)
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_ISACFIX_H_ */

View File

@@ -0,0 +1,5 @@
# These are for the common case of adding or renaming files. If you're doing
# structural changes, please get a review from a reviewer in this file.
per-file *.gyp=*
per-file *.gypi=*

View File

@@ -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
*/
int16_t WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData)
{
uint16_t *streamPtr;
uint16_t 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++ += (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
streamData->full = 1;
} else {
*streamPtr = (uint16_t) 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++ = (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 16);
} else {
*streamPtr++ |= (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
*streamPtr = (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 8)
& 0xFF00;
}
}
/* calculate stream length in bytes */
return (((streamPtr - streamData->stream)<<1) + !(streamData->full));
}

View File

@@ -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 int16_t *data,
const uint16_t **cdf,
const int16_t lenData)
{
uint32_t W_lower;
uint32_t W_upper;
uint32_t W_upper_LSB;
uint32_t W_upper_MSB;
uint16_t *streamPtr;
uint16_t negCarry;
uint16_t *maxStreamPtr;
uint16_t *streamPtrCarry;
uint32_t cdfLo;
uint32_t 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 = (uint32_t) *(*cdf + (uint32_t)*data);
cdfHi = (uint32_t) *(*cdf++ + (uint32_t)*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 += ((W_upper_LSB * cdfLo) >> 16);
W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
W_upper += ((W_upper_LSB * cdfHi) >> 16);
/* shift interval such that it begins at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamData->streamval += W_lower;
/* handle carry */
if (streamData->streamval < W_lower)
{
/* propagate carry */
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++ += (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
streamData->full = 1;
} else {
*streamPtr = (uint16_t) 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
*/
int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
Bitstr_dec *streamData,
const uint16_t **cdf,
const uint16_t *cdfSize,
const int16_t lenData)
{
uint32_t W_lower = 0;
uint32_t W_upper;
uint32_t W_tmp;
uint32_t W_upper_LSB;
uint32_t W_upper_MSB;
uint32_t streamval;
const uint16_t *streamPtr;
const uint16_t *cdfPtr;
int16_t 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((uint32_t)*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 += (W_upper_LSB * (*cdfPtr)) >> 16;
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
*/
int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
Bitstr_dec *streamData,
const uint16_t **cdf,
const uint16_t *initIndex,
const int16_t lenData)
{
uint32_t W_lower;
uint32_t W_upper;
uint32_t W_tmp;
uint32_t W_upper_LSB;
uint32_t W_upper_MSB;
uint32_t streamval;
const uint16_t *streamPtr;
const uint16_t *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 += (W_upper_LSB * (*cdfPtr)) >> 16;
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 += (W_upper_LSB * (*cdfPtr)) >> 16;
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 += (W_upper_LSB * (*cdfPtr)) >> 16;
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);
}
}

View File

@@ -0,0 +1,416 @@
/*
* 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 int32_t 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 uint16_t 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 uint16_t 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 uint16_t WebRtcIsacfix_Piecewise(int32_t xinQ15) {
int32_t ind;
int32_t qtmp1;
uint16_t 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 = (uint16_t)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,
int16_t *dataQ7,
const uint16_t *envQ8,
const int16_t lenData)
{
uint32_t W_lower;
uint32_t W_upper;
uint16_t W_upper_LSB;
uint16_t W_upper_MSB;
uint16_t *streamPtr;
uint16_t *maxStreamPtr;
uint16_t *streamPtrCarry;
uint16_t negcarry;
uint32_t cdfLo;
uint32_t 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 = (uint16_t)W_upper;
W_upper_MSB = (uint16_t)WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
W_lower = WEBRTC_SPL_UMUL_32_16(cdfLo, W_upper_MSB);
W_lower += (cdfLo * W_upper_LSB) >> 16;
W_upper = WEBRTC_SPL_UMUL_32_16(cdfHi, W_upper_MSB);
W_upper += (cdfHi * W_upper_LSB) >> 16;
/* shift interval such that it begins at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamData->streamval += W_lower;
/* handle carry */
if (streamData->streamval < W_lower)
{
/* propagate carry */
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++ += (uint16_t) WEBRTC_SPL_RSHIFT_U32(
streamData->streamval, 24);
streamData->full = 1;
} else {
*streamPtr = (uint16_t) 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
*/
int16_t WebRtcIsacfix_DecLogisticMulti2(int16_t *dataQ7,
Bitstr_dec *streamData,
const int32_t *envQ8,
const int16_t lenData)
{
uint32_t W_lower;
uint32_t W_upper;
uint32_t W_tmp;
uint16_t W_upper_LSB;
uint16_t W_upper_MSB;
uint32_t streamVal;
uint16_t cdfTmp;
int32_t res;
int32_t inSqrt;
int32_t newRes;
const uint16_t *streamPtr;
int16_t candQ7;
int16_t envCount;
uint16_t tmpARSpecQ8 = 0;
int k, i;
int offset = 0;
/* 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((int32_t)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 = (uint16_t)newRes;
for(k4 = 0; k4 < 4; k4++)
{
/* find the integer *data for which streamVal lies in [W_lower+1, W_upper] */
W_upper_LSB = (uint16_t) (W_upper & 0x0000FFFF);
W_upper_MSB = (uint16_t) 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 += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
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 += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
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 += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
/* 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 += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
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 += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
/* 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) )
{
if (streamPtr < streamData->stream + streamData->stream_size) {
/* 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;
}
} else {
/* Intending to read outside the stream. This can happen for the last
* two or three bytes. It is how the algorithm is implemented. Do
* not read from the bit stream and insert zeros instead. */
streamVal = WEBRTC_SPL_LSHIFT_W32(streamVal, 8);
if (streamData->full == 0) {
offset++; // We would have incremented the pointer in this case.
streamData->full = 1;
} else {
streamData->full = 0;
}
}
W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
}
}
envCount++;
}
streamData->stream_index = streamPtr + offset - 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);
}

View File

@@ -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,
int16_t *dataQ7,
const uint16_t *env,
const int16_t 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
*/
int16_t 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
*/
int16_t WebRtcIsacfix_DecLogisticMulti2(
int16_t *data,
Bitstr_dec *streamData,
const int32_t *env,
const int16_t 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 int16_t *data,
const uint16_t **cdf,
const int16_t 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
*/
int16_t WebRtcIsacfix_DecHistBisectMulti(
int16_t *data,
Bitstr_dec *streamData,
const uint16_t **cdf,
const uint16_t *cdfSize,
const int16_t 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
*/
int16_t WebRtcIsacfix_DecHistOneStepMulti(
int16_t *data,
Bitstr_dec *streamData,
const uint16_t **cdf,
const uint16_t *initIndex,
const int16_t lenData);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -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
*/
int32_t 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
*/
int32_t WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bwest_str,
const uint16_t rtp_number,
const int16_t frameSize,
const uint32_t send_ts,
const uint32_t arr_ts,
const int16_t pksize,
const uint16_t Index);
/* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
int16_t WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bwest_str,
const int16_t 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)
*/
uint16_t WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bwest_str);
/* Returns the bandwidth estimation (in bps) */
uint16_t WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bwest_str);
/* Returns the bandwidth that iSAC should send with in bps */
int16_t WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr *bwest_str);
/* Returns the max delay (in ms) */
int16_t WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str);
/* Returns the max delay value from the other side in ms */
int16_t WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr *bwest_str);
/*
* update amount of data in bottle neck buffer and burst handling
* returns minimum payload size (bytes)
*/
uint16_t WebRtcIsacfix_GetMinBytes(RateModel *State,
int16_t StreamSize, /* bytes in bitstream */
const int16_t FrameLen, /* ms per frame */
const int16_t BottleNeck, /* bottle neck rate; excl headers (bps) */
const int16_t DelayBuildUp); /* max delay from bottle neck buffering (ms) */
/*
* update long-term average bitrate and amount of data in buffer
*/
void WebRtcIsacfix_UpdateRateModel(RateModel *State,
int16_t StreamSize, /* bytes in bitstream */
const int16_t FrameSamples, /* samples per frame */
const int16_t BottleNeck); /* bottle neck rate; excl headers (bps) */
void WebRtcIsacfix_InitRateModel(RateModel *State);
/* Returns the new framelength value (input argument: bottle_neck) */
int16_t WebRtcIsacfix_GetNewFrameLength(int16_t bottle_neck, int16_t current_framelength);
/* Returns the new SNR value (input argument: bottle_neck) */
//returns snr in Q10
int16_t WebRtcIsacfix_GetSnr(int16_t bottle_neck, int16_t framesamples);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_ */

View File

@@ -0,0 +1,228 @@
/*
* 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"
#ifdef __cplusplus
extern "C" {
#endif
int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr* bwest_str,
Bitstr_dec* streamdata,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts);
int16_t WebRtcIsacfix_DecodeImpl(int16_t* signal_out16,
ISACFIX_DecInst_t* ISACdec_obj,
int16_t* current_framesamples);
int16_t WebRtcIsacfix_DecodePlcImpl(int16_t* decoded,
ISACFIX_DecInst_t* ISACdec_obj,
int16_t* current_framesample );
int WebRtcIsacfix_EncodeImpl(int16_t* in,
ISACFIX_EncInst_t* ISACenc_obj,
BwEstimatorstr* bw_estimatordata,
int16_t 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();
typedef void (*Time2Spec)(int16_t* inre1Q9,
int16_t* inre2Q9,
int16_t* outre,
int16_t* outim);
typedef void (*Spec2Time)(int16_t* inreQ7,
int16_t* inimQ7,
int32_t* outre1Q16,
int32_t* outre2Q16);
extern Time2Spec WebRtcIsacfix_Time2Spec;
extern Spec2Time WebRtcIsacfix_Spec2Time;
void WebRtcIsacfix_Time2SpecC(int16_t* inre1Q9,
int16_t* inre2Q9,
int16_t* outre,
int16_t* outim);
void WebRtcIsacfix_Spec2TimeC(int16_t* inreQ7,
int16_t* inimQ7,
int32_t* outre1Q16,
int32_t* outre2Q16);
#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
int16_t* inre2Q9,
int16_t* outre,
int16_t* outim);
void WebRtcIsacfix_Spec2TimeNeon(int16_t* inreQ7,
int16_t* inimQ7,
int32_t* outre1Q16,
int32_t* outre2Q16);
#endif
#if defined(MIPS32_LE)
void WebRtcIsacfix_Time2SpecMIPS(int16_t* inre1Q9,
int16_t* inre2Q9,
int16_t* outre,
int16_t* outim);
void WebRtcIsacfix_Spec2TimeMIPS(int16_t* inreQ7,
int16_t* inimQ7,
int32_t* outre1Q16,
int32_t* outre2Q16);
#endif
/* filterbank functions */
void WebRtcIsacfix_SplitAndFilter1(int16_t* in,
int16_t* LP16,
int16_t* HP16,
PreFiltBankstr* prefiltdata);
void WebRtcIsacfix_FilterAndCombine1(int16_t* tempin_ch1,
int16_t* tempin_ch2,
int16_t* out16,
PostFiltBankstr* postfiltdata);
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
void WebRtcIsacfix_SplitAndFilter2(int16_t* in,
int16_t* LP16,
int16_t* HP16,
PreFiltBankstr* prefiltdata);
void WebRtcIsacfix_FilterAndCombine2(int16_t* tempin_ch1,
int16_t* tempin_ch2,
int16_t* out16,
PostFiltBankstr* postfiltdata,
int16_t len);
#endif
/* normalized lattice filters */
void WebRtcIsacfix_NormLatticeFilterMa(int16_t orderCoef,
int32_t* stateGQ15,
int16_t* lat_inQ0,
int16_t* filt_coefQ15,
int32_t* gain_lo_hiQ17,
int16_t lo_hi,
int16_t* lat_outQ9);
void WebRtcIsacfix_NormLatticeFilterAr(int16_t orderCoef,
int16_t* stateGQ0,
int32_t* lat_inQ25,
int16_t* filt_coefQ15,
int32_t* gain_lo_hiQ17,
int16_t lo_hi,
int16_t* lat_outQ0);
/* TODO(kma): Remove the following functions into individual header files. */
/* Internal functions in both C and ARM Neon versions */
int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __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(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __restrict scale);
void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
int16_t input1,
int32_t input2,
int32_t* ptr0,
int32_t* ptr1,
int32_t* ptr2);
#endif
#if defined(MIPS32_LE)
int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __restrict scale);
void WebRtcIsacfix_FilterMaLoopMIPS(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)(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __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;
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_ */

View File

@@ -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"
int16_t WebRtcIsacfix_DecodeImpl(int16_t *signal_out16,
ISACFIX_DecInst_t *ISACdec_obj,
int16_t *current_framesamples)
{
int k;
int err;
int16_t BWno;
int16_t len = 0;
int16_t model;
int16_t Vector_Word16_1[FRAMESAMPLES/2];
int16_t Vector_Word16_2[FRAMESAMPLES/2];
int32_t Vector_Word32_1[FRAMESAMPLES/2];
int32_t Vector_Word32_2[FRAMESAMPLES/2];
int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
int32_t gain_lo_hiQ17[2*SUBFRAMES];
int16_t PitchLags_Q7[PITCH_SUBFRAMES];
int16_t PitchGains_Q12[PITCH_SUBFRAMES];
int16_t AvgPitchGain_Q12;
int16_t tmp_1, tmp_2;
int32_t tmp32a, tmp32b;
int16_t gainQ13;
int16_t frame_nb; /* counter */
int16_t frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */
int16_t processed_samples;
/* PLC */
int16_t 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 = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, MAX_FRAMESAMPLES); /* 0, or 1 */
processed_samples = (int16_t)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 = (int16_t)(((int32_t)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] = (int16_t)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] = (int16_t)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] = WebRtcSpl_AddSatW16(
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (ISACdec_obj->plcstr_obj).overlapLP[k], overlapWin[RECOVERY_OVERLAP - k - 1], 14),
(int16_t)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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q13
for (k = 0; k < FRAMESAMPLES/2; k++)
{
Vector_Word32_1[k] = (int32_t) 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 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/
tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)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;
}

View File

@@ -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,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts)
{
int16_t index;
int16_t 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,
frame_samples * 1000 / FS,
send_ts,
arr_ts,
(int16_t) packet_size, /* in bytes */
index);
/* error check */
if (err<0) {
return err;
}
/* Succesful */
return 0;
}

View File

@@ -0,0 +1,828 @@
/*
* 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 int16_t plc_filterma_Fast(
int16_t *In, /* (i) Vector to be filtered. InOut[-orderCoef+1]
to InOut[-1] contains state */
int16_t *Out, /* (o) Filtered vector */
int16_t *B, /* (i) The filter coefficients (in Q0) */
int16_t Blen, /* (i) Number of B coefficients */
int16_t len, /* (i) Number of samples to be filtered */
int16_t reduceDecay,
int16_t decay,
int16_t rshift )
{
int i, j;
int32_t o;
int32_t lim;
lim = WEBRTC_SPL_LSHIFT_W32( (int32_t)1, 15 + rshift )-1;
for (i = 0; i < len; i++)
{
const int16_t *b_ptr = &B[0];
const int16_t *x_ptr = &In[i];
o = (int32_t)0;
for (j = 0;j < Blen; j++)
{
o = WebRtcSpl_AddSatW32(o, WEBRTC_SPL_MUL_16_16(*b_ptr, *x_ptr));
b_ptr++;
x_ptr--;
}
/* to round off correctly */
o = WebRtcSpl_AddSatW32(o, 1 << (rshift - 1));
/* saturate according to the domain of the filter coefficients */
o = WEBRTC_SPL_SAT((int32_t)lim, o, (int32_t)-lim);
/* o should be in the range of int16_t */
o = WEBRTC_SPL_RSHIFT_W32( o, rshift );
/* decay the output signal; this is specific to plc */
*Out++ = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (int16_t)o, decay, 15); // ((o + (int32_t)2048) >> 12);
/* change the decay */
decay -= reduceDecay;
if( decay < 0 )
decay = 0;
}
return( decay );
}
static __inline int32_t log2_Q8_T( uint32_t x ) {
int32_t zeros, lg2;
int16_t frac;
zeros=WebRtcSpl_NormU32(x);
frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
/* log2(magn(i)) */
lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
return lg2;
}
static __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10
int16_t tmp16_1, tmp16_2;
tmp16_2=(int16_t)(0x0400|(x&0x03FF));
tmp16_1=-(int16_t)WEBRTC_SPL_RSHIFT_W16(x,10);
if(tmp16_1>0)
return (int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
else
return (int16_t) 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( int16_t in, int16_t *A, int16_t *B )
{
int16_t 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 int16_t */
x = (int16_t)( 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 = (int16_t)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 = (int16_t)( 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 = (int16_t)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( int16_t *in, int16_t *out, int16_t lenIn, int16_t lenOut )
{
int32_t n;
int16_t resOut, i, j, relativePos, diff; /* */
uint16_t udiff;
if( lenIn == lenOut )
{
WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
return;
}
n = WEBRTC_SPL_MUL_16_16( (int16_t)(lenIn-1), RESAMP_RES );
resOut = WebRtcSpl_DivW32W16ResW16( n, (int16_t)(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 = (uint16_t)(in[ j ] - in[j + 1]);
out[ i ] = in[ j ] - (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
}
else
{
if( (in[j] < 0) && (in[j+1] > 0) )
{
udiff = (uint16_t)( in[j + 1] - in[ j ] );
out[ i ] = in[ j ] + (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
}
else
{
diff = in[ j + 1 ] - in[ j ];
out[ i ] = in[ j ] + (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( diff, relativePos, RESAMP_RES_BIT );
}
}
}
}
int16_t WebRtcIsacfix_DecodePlcImpl(int16_t *signal_out16,
ISACFIX_DecInst_t *ISACdec_obj,
int16_t *current_framesamples )
{
int subframecnt;
int16_t len = 0;
int16_t* Vector_Word16_1;
int16_t Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
int16_t* Vector_Word16_2;
int16_t Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
int32_t Vector_Word32_1[FRAMESAMPLES_HALF];
int32_t Vector_Word32_2[FRAMESAMPLES_HALF];
int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
int16_t pitchLags_Q7[PITCH_SUBFRAMES];
int16_t pitchGains_Q12[PITCH_SUBFRAMES];
int16_t tmp_1, tmp_2;
int32_t tmp32a, tmp32b;
int16_t gainQ13;
int16_t myDecayRate;
/* ---------- PLC variables ------------ */
int16_t lag0, i, k, noiseIndex;
int16_t stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
int32_t gain_lo_hiQ17[2*SUBFRAMES];
int16_t nLP, pLP, wNoisyLP, wPriodicLP, tmp16, minIdx;
int32_t nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
int16_t noise1, rshift;
int16_t ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
int32_t 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 = WebRtcSpl_AddSatW32(corr, WEBRTC_SPL_ABS_W32(
WebRtcSpl_SubSatW16(
(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( (uint32_t)( varIn ) ) +
(int32_t)(rightShiftIn << 8);
logVarOut = log2_Q8_T( (uint32_t)( varOut ) ) +
(int32_t)(rightShiftOut << 8);
logMaxAbs = log2_Q8_T( (uint32_t)( maxAbs ) );
ltpGain = (int16_t)(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( (uint32_t)( lag0 ) );
tmp16 = (int16_t)((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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
pitchGains_Q12[3], 1010, 10 );
pitchGains_Q12[1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
pitchGains_Q12[2], 1010, 10 );
pitchGains_Q12[0] = (int16_t)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], (int16_t) NOISE_FILTER_LEN,
(int16_t) FRAMESAMPLES_HALF, (int16_t)(5),
(ISACdec_obj->plcstr_obj).decayCoeffNoise, (int16_t)(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] =
(int16_t)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],
(int16_t) NOISE_FILTER_LEN,
(int16_t) FRAMESAMPLES_HALF,
(int16_t) (5),
(ISACdec_obj->plcstr_obj).decayCoeffNoise,
(int16_t) (7) );
for( i = 0; i < FRAMESAMPLES_HALF; i++ )
Vector_Word32_2[i] = WEBRTC_SPL_LSHIFT_W32(
(int32_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
(ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
/* --- Highpass */
pHP = (int32_t)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] = (int16_t)((
(int32_t)stretchPitchLP[k]* 3 +
(int32_t)stretchPitchLP1[k])>>2);
}
break;
}
case 2:
{
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
{
stretchPitchLP[k] = (int16_t)((
(int32_t)stretchPitchLP[k] +
(int32_t)stretchPitchLP1[k] )>>1);
}
break;
}
case 3:
{
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
{
stretchPitchLP[k] = (int16_t)((stretchPitchLP[k] +
(int32_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
(int16_t)((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 = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
(ISACdec_obj->plcstr_obj).decayCoeffNoise,
(int32_t)(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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
(ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
/* --- Highpass */
pHP = (int32_t)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 = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT(
(ISACdec_obj->plcstr_obj).A, nLP, 15 ) );
wNoisyHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
(ISACdec_obj->plcstr_obj).A, (nHP) ) );
wPriodicLP = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT(
(ISACdec_obj->plcstr_obj).B, pLP, 15));
wPriodicHP = (int32_t)(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] = (int16_t)((
(int32_t)stretchPitchLP[k]* 3 +
(int32_t)stretchPitchLP1[k] )>>2);
}
break;
}
case 2:
{
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
{
stretchPitchLP[k] = (int16_t)((
(int32_t)stretchPitchLP[k] +
(int32_t)stretchPitchLP1[k])>>1);
}
break;
}
case 3:
{
for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
{
stretchPitchLP[k] = (int16_t)(
(stretchPitchLP[k] +
(int32_t)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] = WebRtcSpl_AddSatW16(wNoisyLP, wPriodicLP);
Vector_Word32_2[i] = WebRtcSpl_AddSatW32(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] = (int16_t)(
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 = (int16_t) (tmp32b >> 5); // Q13
/* perceptual post-filtering (using normalized lattice filter) */
for (k = 0; k < FRAMESAMPLES_HALF; k++)
Vector_Word32_1[k] = (int32_t) 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 = (int16_t)WebRtcSpl_SatW32ToW16(
((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
/* Construct a new lower channel signal*/
tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(
((int32_t)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;
}

View File

@@ -0,0 +1,632 @@
/*
* 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
#include <assert.h>
#include <stdio.h>
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/structs.h"
int WebRtcIsacfix_EncodeImpl(int16_t *in,
ISACFIX_EncInst_t *ISACenc_obj,
BwEstimatorstr *bw_estimatordata,
int16_t CodingMode)
{
int16_t stream_length = 0;
int16_t usefulstr_len = 0;
int k;
int16_t BWno;
int16_t lofilt_coefQ15[(ORDERLO)*SUBFRAMES];
int16_t hifilt_coefQ15[(ORDERHI)*SUBFRAMES];
int32_t gain_lo_hiQ17[2*SUBFRAMES];
int16_t LPandHP[FRAMESAMPLES/2 + QLOOKAHEAD];
int16_t LP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
int16_t HP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
int16_t PitchLags_Q7[PITCH_SUBFRAMES];
int16_t PitchGains_Q12[PITCH_SUBFRAMES];
int16_t AvgPitchGain_Q12;
int16_t frame_mode; /* 0 for 30ms, 1 for 60ms */
int16_t processed_samples;
int status;
int32_t bits_gainsQ11;
int16_t MinBytes;
int16_t bmodel;
transcode_obj transcodingParam;
int16_t payloadLimitBytes;
int16_t arithLenBeforeEncodingDFT;
int16_t 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((int16_t)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))
{
int16_t arithLenDFTByte;
int16_t bytesLeftQ5;
int16_t 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
// int16_t 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
//
int16_t scaleQ14[8] = {0, 348, 828, 1408, 2015, 3195, 3500, 3500};
int16_t 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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(LP16a[k], scaleQ14[idx], 14);
LPandHP[k] = (int16_t)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, (int16_t) 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)
{
assert(stream_length >= 0);
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) ] |= (uint16_t)(ISACenc_obj->bitstr_seed & 0xFF);
} else {
ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
ISACenc_obj->bitstr_obj.stream[stream_length / 2] =
((uint16_t)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] +=
((uint16_t)((MinBytes - usefulstr_len) & 0x00FF) << 8);
}
}
else
{
/* update rate model */
WebRtcIsacfix_UpdateRateModel(&ISACenc_obj->rate_data_obj, (int16_t) 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;
int16_t BWno = BWnumber;
int stream_length = 0;
int16_t model;
const uint16_t *Q_PitchGain_cdf_ptr[1];
const uint16_t **cdf;
const ISAC_SaveEncData_t *SaveEnc_str;
int32_t tmpLPCcoeffs_g[KLT_ORDER_GAIN<<1];
int16_t tmpLPCindex_g[KLT_ORDER_GAIN<<1];
int16_t tmp_fre[FRAMESAMPLES];
int16_t 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] = (int32_t) ((scale) * (float) SaveEnc_str->LPCcoeffs_g[ii]);
}
/* Scale DFT */
for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
tmp_fre[ii] = (int16_t) ((scale) * (float) SaveEnc_str->fre[ii]) ;
tmp_fim[ii] = (int16_t) ((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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,189 @@
/*
* 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) */
int16_t WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
int16_t *frQ7,
int16_t *fiQ7,
int16_t AvgPitchGain_Q12);
/* encode complex spectrum */
int WebRtcIsacfix_EncodeSpec(const int16_t *fr,
const int16_t *fi,
Bitstr_enc *streamdata,
int16_t AvgPitchGain_Q12);
/* decode & dequantize LPC Coef */
int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
int32_t *LPCCoefQ17,
int32_t *gain_lo_hiQ17,
int16_t *outmodel);
int WebRtcIsacfix_DecodeLpc(int32_t *gain_lo_hiQ17,
int16_t *LPCCoef_loQ15,
int16_t *LPCCoef_hiQ15,
Bitstr_dec *streamdata,
int16_t *outmodel);
/* quantize & code LPC Coef */
int WebRtcIsacfix_EncodeLpc(int32_t *gain_lo_hiQ17,
int16_t *LPCCoef_loQ15,
int16_t *LPCCoef_hiQ15,
int16_t *model,
int32_t *sizeQ11,
Bitstr_enc *streamdata,
ISAC_SaveEncData_t* encData,
transcode_obj *transcodeParam);
int WebRtcIsacfix_EstCodeLpcGain(int32_t *gain_lo_hiQ17,
Bitstr_enc *streamdata,
ISAC_SaveEncData_t* encData);
/* decode & dequantize RC */
int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata,
int16_t *RCQ15);
/* quantize & code RC */
int WebRtcIsacfix_EncodeRcCoef(int16_t *RCQ15,
Bitstr_enc *streamdata);
/* decode & dequantize squared Gain */
int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata,
int32_t *Gain2);
/* quantize & code squared Gain (input is squared gain) */
int WebRtcIsacfix_EncodeGain2(int32_t *gain2,
Bitstr_enc *streamdata);
int WebRtcIsacfix_EncodePitchGain(int16_t *PitchGains_Q12,
Bitstr_enc *streamdata,
ISAC_SaveEncData_t* encData);
int WebRtcIsacfix_EncodePitchLag(int16_t *PitchLagQ7,
int16_t *PitchGain_Q12,
Bitstr_enc *streamdata,
ISAC_SaveEncData_t* encData);
int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata,
int16_t *PitchGain_Q12);
int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
int16_t *PitchGain_Q12,
int16_t *PitchLagQ7);
int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
int16_t *framelength);
int WebRtcIsacfix_EncodeFrameLen(int16_t framelength,
Bitstr_enc *streamdata);
int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata,
int16_t *BWno);
int WebRtcIsacfix_EncodeReceiveBandwidth(int16_t *BWno,
Bitstr_enc *streamdata);
void WebRtcIsacfix_TranscodeLpcCoef(int32_t *tmpcoeffs_gQ6,
int16_t *index_gQQ);
// Pointer functions for LPC transforms.
typedef void (*MatrixProduct1)(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift);
typedef void (*MatrixProduct2)(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step);
extern MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
extern MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
void WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift);
void WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step);
#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift);
void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step);
#endif
#if defined(MIPS32_LE)
void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift);
void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step);
#endif
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_

View File

@@ -0,0 +1,249 @@
/*
* Copyright (c) 2014 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 "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
// MIPS optimization of the function WebRtcIsacfix_MatrixProduct1.
// Bit-exact with the function WebRtcIsacfix_MatrixProduct1C from
// entropy_coding.c file.
void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift) {
if (matrix1_index_init_case != 0) {
int j = SUBFRAMES, k = 0, n = 0;
int32_t r0, r1, r2, sum32;
int32_t* product_start = matrix_product;
int32_t* product_ptr;
const uint32_t product_step = 4 * mid_loop_count;
const uint32_t matrix0_step = 2 * matrix0_index_step;
const uint32_t matrix1_step = 4 * matrix1_index_step;
const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
const int16_t* matrix0_start = matrix0;
const int32_t* matrix1_start = matrix1;
int16_t* matrix0_ptr;
int32_t* matrix1_ptr;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"1: \n\t"
"addu %[product_ptr], %[product_start], $0 \n\t"
"addu %[k], %[product_step], $0 \n\t"
"addiu %[j], %[j], -1 \n\t"
"addu %[matrix1_start], %[matrix1], $0 \n\t"
"2: \n\t"
"addu %[matrix1_ptr], %[matrix1_start], $0 \n\t"
"addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
"addu %[n], %[inner_loop_count], $0 \n\t"
"mul %[sum32], $0, $0 \n\t"
"3: \n\t"
"lw %[r0], 0(%[matrix1_ptr]) \n\t"
"lh %[r1], 0(%[matrix0_ptr]) \n\t"
"addu %[matrix1_ptr], %[matrix1_ptr], %[matrix1_step] \n\t"
"sllv %[r0], %[r0], %[shift] \n\t"
"andi %[r2], %[r0], 0xffff \n\t"
"sra %[r2], %[r2], 1 \n\t"
"mul %[r2], %[r2], %[r1] \n\t"
"sra %[r0], %[r0], 16 \n\t"
"mul %[r0], %[r0], %[r1] \n\t"
"addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
"addiu %[n], %[n], -1 \n\t"
#if defined(MIPS_DSP_R1_LE)
"shra_r.w %[r2], %[r2], 15 \n\t"
#else
"addiu %[r2], %[r2], 0x4000 \n\t"
"sra %[r2], %[r2], 15 \n\t"
#endif
"addu %[sum32], %[sum32], %[r2] \n\t"
"bgtz %[n], 3b \n\t"
" addu %[sum32], %[sum32], %[r0] \n\t"
"addiu %[k], %[k], -4 \n\t"
"addu %[matrix1_start], %[matrix1_start], %[matrix1_step2] \n\t"
"sw %[sum32], 0(%[product_ptr]) \n\t"
"bgtz %[k], 2b \n\t"
" addiu %[product_ptr], %[product_ptr], 4 \n\t"
"addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
"bgtz %[j], 1b \n\t"
" addu %[product_start], %[product_start], %[product_step] \n\t"
".set pop \n\t"
: [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
[k] "=&r" (k), [j] "+r" (j), [matrix1_start] "=&r"(matrix1_start),
[matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
[matrix0_start] "+r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
[sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
: [product_step] "r" (product_step), [matrix1] "r" (matrix1),
[inner_loop_count] "r" (inner_loop_count),
[matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
[matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
[matrix0_step2] "r" (matrix0_step2)
: "hi", "lo", "memory"
);
} else {
int j = SUBFRAMES, k = 0, n = 0;
int32_t r0, r1, r2, sum32;
int32_t* product_start = matrix_product;
int32_t* product_ptr;
const uint32_t product_step = 4 * mid_loop_count;
const uint32_t matrix0_step = 2 * matrix0_index_step;
const uint32_t matrix1_step = 4 * matrix1_index_step;
const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
const int16_t* matrix0_start = matrix0;
const int32_t* matrix1_start = matrix1;
int16_t* matrix0_ptr;
int32_t* matrix1_ptr;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"1: \n\t"
"addu %[product_ptr], %[product_start], $0 \n\t"
"addu %[k], %[product_step], $0 \n\t"
"addiu %[j], %[j], -1 \n\t"
"addu %[matrix0_start], %[matrix0], $0 \n\t"
"2: \n\t"
"addu %[matrix1_ptr], %[matrix1_start], $0 \n\t"
"addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
"addu %[n], %[inner_loop_count], $0 \n\t"
"mul %[sum32], $0, $0 \n\t"
"3: \n\t"
"lw %[r0], 0(%[matrix1_ptr]) \n\t"
"lh %[r1], 0(%[matrix0_ptr]) \n\t"
"addu %[matrix1_ptr], %[matrix1_ptr], %[matrix1_step] \n\t"
"sllv %[r0], %[r0], %[shift] \n\t"
"andi %[r2], %[r0], 0xffff \n\t"
"sra %[r2], %[r2], 1 \n\t"
"mul %[r2], %[r2], %[r1] \n\t"
"sra %[r0], %[r0], 16 \n\t"
"mul %[r0], %[r0], %[r1] \n\t"
"addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
"addiu %[n], %[n], -1 \n\t"
#if defined(MIPS_DSP_R1_LE)
"shra_r.w %[r2], %[r2], 15 \n\t"
#else
"addiu %[r2], %[r2], 0x4000 \n\t"
"sra %[r2], %[r2], 15 \n\t"
#endif
"addu %[sum32], %[sum32], %[r2] \n\t"
"bgtz %[n], 3b \n\t"
" addu %[sum32], %[sum32], %[r0] \n\t"
"addiu %[k], %[k], -4 \n\t"
"addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
"sw %[sum32], 0(%[product_ptr]) \n\t"
"bgtz %[k], 2b \n\t"
" addiu %[product_ptr], %[product_ptr], 4 \n\t"
"addu %[matrix1_start], %[matrix1_start], %[matrix1_step2] \n\t"
"bgtz %[j], 1b \n\t"
" addu %[product_start], %[product_start], %[product_step] \n\t"
".set pop \n\t"
: [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
[k] "=&r" (k), [j] "+r" (j), [matrix1_start] "+r"(matrix1_start),
[matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
[matrix0_start] "=&r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
[sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
: [product_step] "r" (product_step), [matrix0] "r" (matrix0),
[inner_loop_count] "r" (inner_loop_count),
[matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
[matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
[matrix0_step2] "r" (matrix0_step2)
: "hi", "lo", "memory"
);
}
}
// MIPS optimization of the function WebRtcIsacfix_MatrixProduct2.
// Bit-exact with the function WebRtcIsacfix_MatrixProduct2C from
// entropy_coding.c file.
void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step) {
int j = 0, n = 0;
int loop_count = SUBFRAMES;
const int16_t* matrix0_ptr;
const int32_t* matrix1_ptr;
const int16_t* matrix0_start = matrix0;
const int matrix0_step = 2 * matrix0_index_step;
const int matrix0_step2 = 2 * matrix0_index_factor;
int32_t r0, r1, r2, r3, r4, sum32, sum32_2;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addu %[j], %[loop_count], $0 \n\t"
"addu %[matrix0_start], %[matrix0], $0 \n\t"
"1: \n\t"
"addu %[matrix1_ptr], %[matrix1], $0 \n\t"
"addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
"addu %[n], %[loop_count], $0 \n\t"
"mul %[sum32], $0, $0 \n\t"
"mul %[sum32_2], $0, $0 \n\t"
"2: \n\t"
"lw %[r0], 0(%[matrix1_ptr]) \n\t"
"lw %[r1], 4(%[matrix1_ptr]) \n\t"
"lh %[r2], 0(%[matrix0_ptr]) \n\t"
"andi %[r3], %[r0], 0xffff \n\t"
"sra %[r3], %[r3], 1 \n\t"
"mul %[r3], %[r3], %[r2] \n\t"
"andi %[r4], %[r1], 0xffff \n\t"
"sra %[r4], %[r4], 1 \n\t"
"mul %[r4], %[r4], %[r2] \n\t"
"sra %[r0], %[r0], 16 \n\t"
"mul %[r0], %[r0], %[r2] \n\t"
"sra %[r1], %[r1], 16 \n\t"
"mul %[r1], %[r1], %[r2] \n\t"
#if defined(MIPS_DSP_R1_LE)
"shra_r.w %[r3], %[r3], 15 \n\t"
"shra_r.w %[r4], %[r4], 15 \n\t"
#else
"addiu %[r3], %[r3], 0x4000 \n\t"
"sra %[r3], %[r3], 15 \n\t"
"addiu %[r4], %[r4], 0x4000 \n\t"
"sra %[r4], %[r4], 15 \n\t"
#endif
"addiu %[matrix1_ptr], %[matrix1_ptr], 8 \n\t"
"addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
"addiu %[n], %[n], -1 \n\t"
"addu %[sum32], %[sum32], %[r3] \n\t"
"addu %[sum32_2], %[sum32_2], %[r4] \n\t"
"addu %[sum32], %[sum32], %[r0] \n\t"
"bgtz %[n], 2b \n\t"
" addu %[sum32_2], %[sum32_2], %[r1] \n\t"
"sra %[sum32], %[sum32], 3 \n\t"
"sra %[sum32_2], %[sum32_2], 3 \n\t"
"addiu %[j], %[j], -1 \n\t"
"addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
"sw %[sum32], 0(%[matrix_product]) \n\t"
"sw %[sum32_2], 4(%[matrix_product]) \n\t"
"bgtz %[j], 1b \n\t"
" addiu %[matrix_product], %[matrix_product], 8 \n\t"
".set pop \n\t"
: [j] "=&r" (j), [matrix0_start] "=&r" (matrix0_start),
[matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
[n] "=&r" (n), [sum32] "=&r" (sum32), [sum32_2] "=&r" (sum32_2),
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
[r4] "=&r" (r4), [matrix_product] "+r" (matrix_product)
: [loop_count] "r" (loop_count), [matrix0] "r" (matrix0),
[matrix1] "r" (matrix1), [matrix0_step] "r" (matrix0_step),
[matrix0_step2] "r" (matrix0_step2)
: "hi", "lo", "memory"
);
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2013 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 contains WebRtcIsacfix_MatrixProduct1Neon() and
* WebRtcIsacfix_MatrixProduct2Neon() for ARM Neon platform. API's are in
* entropy_coding.c. Results are bit exact with the c code for
* generic platforms.
*/
#include "entropy_coding.h"
#include <arm_neon.h>
#include <assert.h>
#include <stddef.h>
#include "signal_processing_library.h"
void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix1_index_factor1,
const int matrix0_index_factor1,
const int matrix1_index_init_case,
const int matrix1_index_step,
const int matrix0_index_step,
const int inner_loop_count,
const int mid_loop_count,
const int shift) {
int j = 0, k = 0, n = 0;
int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
int* matrix1_index_factor2 = &j;
int* matrix0_index_factor2 = &k;
if (matrix1_index_init_case != 0) {
matrix1_index_factor2 = &k;
matrix0_index_factor2 = &j;
}
int32x4_t shift32x4 = vdupq_n_s32(shift);
int32x2_t shift32x2 = vdup_n_s32(shift);
int32x4_t sum_32x4 = vdupq_n_s32(0);
int32x2_t sum_32x2 = vdup_n_s32(0);
assert(inner_loop_count % 2 == 0);
assert(mid_loop_count % 2 == 0);
if (matrix1_index_init_case != 0 && matrix1_index_factor1 == 1) {
for (j = 0; j < SUBFRAMES; j++) {
matrix_prod_index = mid_loop_count * j;
for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
matrix1_index = k;
matrix0_index = matrix0_index_factor1 * j;
for (n = 0; n < inner_loop_count; n++) {
int32x4_t matrix0_32x4 =
vdupq_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
int32x4_t matrix1_32x4 =
vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
matrix1_index += matrix1_index_step;
matrix0_index += matrix0_index_step;
}
vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
matrix_prod_index += 4;
}
if (mid_loop_count % 4 > 1) {
sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
matrix1_index = k;
k += 2;
matrix0_index = matrix0_index_factor1 * j;
for (n = 0; n < inner_loop_count; n++) {
int32x2_t matrix0_32x2 =
vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
int32x2_t matrix1_32x2 =
vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
matrix1_index += matrix1_index_step;
matrix0_index += matrix0_index_step;
}
vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
matrix_prod_index += 2;
}
}
}
else if (matrix1_index_init_case == 0 && matrix0_index_factor1 == 1) {
int32x2_t multi_32x2 = vdup_n_s32(0);
int32x2_t matrix0_32x2 = vdup_n_s32(0);
for (j = 0; j < SUBFRAMES; j++) {
matrix_prod_index = mid_loop_count * j;
for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
matrix1_index = matrix1_index_factor1 * j;
matrix0_index = k;
for (n = 0; n < inner_loop_count; n++) {
int32x4_t matrix1_32x4 = vdupq_n_s32(matrix1[matrix1_index] << shift);
int32x4_t matrix0_32x4 =
vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
matrix1_index += matrix1_index_step;
matrix0_index += matrix0_index_step;
}
vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
matrix_prod_index += 4;
}
if (mid_loop_count % 4 > 1) {
sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
matrix1_index = matrix1_index_factor1 * j;
matrix0_index = k;
for (n = 0; n < inner_loop_count; n++) {
int32x2_t matrix1_32x2 = vdup_n_s32(matrix1[matrix1_index] << shift);
matrix0_32x2 =
vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
matrix0_32x2, 1);
matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
matrix1_index += matrix1_index_step;
matrix0_index += matrix0_index_step;
}
vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
matrix_prod_index += 2;
}
}
}
else if (matrix1_index_init_case == 0 &&
matrix1_index_step == 1 &&
matrix0_index_step == 1) {
int32x2_t multi_32x2 = vdup_n_s32(0);
int32x2_t matrix0_32x2 = vdup_n_s32(0);
for (j = 0; j < SUBFRAMES; j++) {
matrix_prod_index = mid_loop_count * j;
for (k = 0; k < mid_loop_count; k++) {
sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
matrix1_index = matrix1_index_factor1 * j;
matrix0_index = matrix0_index_factor1 * k;
for (n = 0; n < (inner_loop_count >> 2) << 2; n += 4) {
int32x4_t matrix1_32x4 =
vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
int32x4_t matrix0_32x4 =
vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
matrix1_index += 4;
matrix0_index += 4;
}
sum_32x2 = vqadd_s32(vget_low_s32(sum_32x4), vget_high_s32(sum_32x4));
if (inner_loop_count % 4 > 1) {
int32x2_t matrix1_32x2 =
vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
matrix0_32x2 =
vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
matrix0_32x2, 1);
matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
}
sum_32x2 = vpadd_s32(sum_32x2, sum_32x2);
vst1_lane_s32(&matrix_product[matrix_prod_index], sum_32x2, 0);
matrix_prod_index++;
}
}
}
else {
for (j = 0; j < SUBFRAMES; j++) {
matrix_prod_index = mid_loop_count * j;
for (k=0; k < mid_loop_count; k++) {
int32_t sum32 = 0;
matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
for (n = 0; n < inner_loop_count; n++) {
sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
matrix1[matrix1_index] << shift));
matrix1_index += matrix1_index_step;
matrix0_index += matrix0_index_step;
}
matrix_product[matrix_prod_index] = sum32;
matrix_prod_index++;
}
}
}
}
void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
const int32_t matrix1[],
int32_t matrix_product[],
const int matrix0_index_factor,
const int matrix0_index_step) {
int j = 0, n = 0;
int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
int32x2_t sum_32x2 = vdup_n_s32(0);
for (j = 0; j < SUBFRAMES; j++) {
sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
matrix1_index = 0;
matrix0_index = matrix0_index_factor * j;
for (n = SUBFRAMES; n > 0; n--) {
int32x2_t matrix0_32x2 =
vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
int32x2_t matrix1_32x2 = vld1_s32(&matrix1[matrix1_index]);
int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
matrix1_index += 2;
matrix0_index += matrix0_index_step;
}
sum_32x2 = vshr_n_s32(sum_32x2, 3);
vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
matrix_prod_index += 2;
}
}

View File

@@ -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 int16_t 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 int16_t 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 */
int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[], int16_t ImxQx[], int16_t iSign) {
int16_t dd, ee, ff, gg, hh, ii;
int16_t k0, k1, k2, k3, k4, kk;
int16_t tmp116, tmp216;
int16_t ccc1Q14, ccc2Q14, ccc3Q14, sss1Q14, sss2Q14, sss3Q14;
int16_t sss60Q14, ccc72Q14, sss72Q14;
int16_t aaQx, ajQx, akQx, ajmQx, ajpQx, akmQx, akpQx;
int16_t bbQx, bjQx, bkQx, bjmQx, bjpQx, bkmQx, bkpQx;
int16_t 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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, akpQx, 14) -
(int16_t)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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) -
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjpQx, 14);
RexQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, akmQx, 14) -
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, bkmQx, 14);
ImxQx[k1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, akpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, bkpQx, 14);
ImxQx[k2] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14);
ImxQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, akmQx, 14) +
(int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp116, 14); // Q14*Qx>>14 = Qx
bjQx = (int16_t)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 + (int16_t)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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) - // Q14*Qx>>14 = Qx
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) + // Q14*Qx>>14 = Qx
(int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, akpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) + aaQx;
bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bkpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14) + bbQx;
ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, akmQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajmQx, 14);
bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bkmQx, 14) +
(int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, ajpQx, 14) + aaQx;
bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkpQx, 14) +
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bjpQx, 14) + bbQx;
ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akmQx, 14) -
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, ajmQx, 14);
bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkmQx, 14) -
(int16_t)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 + (int16_t)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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) -
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) +
(int16_t)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;
}

View File

@@ -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"
int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[], int16_t ImxQx[], int16_t iSign);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_ */

View File

@@ -0,0 +1,90 @@
/*
* 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.
*/
typedef void (*HighpassFilterFixDec32)(int16_t* io,
int16_t len,
const int16_t* coefficient,
int32_t* state);
extern HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t* io,
int16_t len,
const int16_t* coefficient,
int32_t* state);
#if defined(MIPS_DSP_R1_LE)
void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
int16_t len,
const int16_t* coefficient,
int32_t* state);
#endif
typedef void (*AllpassFilter2FixDec16)(
int16_t *data_ch1, // Input and output in channel 1, in Q0
int16_t *data_ch2, // Input and output in channel 2, in Q0
const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
const int length, // Length of the data buffers
int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
int32_t *filter_state_ch2); // Filter state for channel 2, in Q16
extern AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
void WebRtcIsacfix_AllpassFilter2FixDec16C(
int16_t *data_ch1,
int16_t *data_ch2,
const int16_t *factor_ch1,
const int16_t *factor_ch2,
const int length,
int32_t *filter_state_ch1,
int32_t *filter_state_ch2);
#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
void WebRtcIsacfix_AllpassFilter2FixDec16Neon(
int16_t *data_ch1,
int16_t *data_ch2,
const int16_t *factor_ch1,
const int16_t *factor_ch2,
const int length,
int32_t *filter_state_ch1,
int32_t *filter_state_ch2);
#endif
#if defined(MIPS_DSP_R1_LE)
void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(
int16_t *data_ch1,
int16_t *data_ch2,
const int16_t *factor_ch1,
const int16_t *factor_ch2,
const int length,
int32_t *filter_state_ch1,
int32_t *filter_state_ch2);
#endif
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif
/* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_ */

View File

@@ -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
};

View File

@@ -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_ */

View File

@@ -0,0 +1,418 @@
/*
* 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 "filterbank_internal.h"
#include <assert.h>
#include "codec.h"
#include "filterbank_tables.h"
#include "settings.h"
// Declare a function pointer.
AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
void WebRtcIsacfix_AllpassFilter2FixDec16C(
int16_t *data_ch1, // Input and output in channel 1, in Q0
int16_t *data_ch2, // Input and output in channel 2, in Q0
const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
const int length, // Length of the data buffers
int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
int32_t *filter_state_ch2) { // Filter state for channel 2, in Q16
int n = 0;
int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
int16_t in_out = 0;
int32_t a = 0, b = 0;
// Assembly file assumption.
assert(length % 2 == 0);
for (n = 0; n < length; n++) {
// Process channel 1:
in_out = data_ch1[n];
a = WEBRTC_SPL_MUL_16_16(factor_ch1[0], in_out); // Q15 * Q0 = Q15
a <<= 1; // Q15 -> Q16
b = WebRtcSpl_AddSatW32(a, state0_ch1);
a = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b >> 16)); // Q15
state0_ch1 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16); // Q16
in_out = (int16_t) (b >> 16); // Save as Q0
a = WEBRTC_SPL_MUL_16_16(factor_ch1[1], in_out); // Q15 * Q0 = Q15
a <<= 1; // Q15 -> Q16
b = WebRtcSpl_AddSatW32(a, state1_ch1); // Q16
a = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b >> 16)); // Q15
state1_ch1 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16); // Q16
data_ch1[n] = (int16_t) (b >> 16); // Save as Q0
// Process channel 2:
in_out = data_ch2[n];
a = WEBRTC_SPL_MUL_16_16(factor_ch2[0], in_out); // Q15 * Q0 = Q15
a <<= 1; // Q15 -> Q16
b = WebRtcSpl_AddSatW32(a, state0_ch2); // Q16
a = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b >> 16)); // Q15
state0_ch2 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16); // Q16
in_out = (int16_t) (b >> 16); // Save as Q0
a = WEBRTC_SPL_MUL_16_16(factor_ch2[1], in_out); // Q15 * Q0 = Q15
a <<= 1; // Q15 -> Q16
b = WebRtcSpl_AddSatW32(a, state1_ch2); // Q16
a = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b >> 16)); // Q15
state1_ch2 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16); // Q16
data_ch2[n] = (int16_t) (b >> 16); // Save as Q0
}
filter_state_ch1[0] = state0_ch1;
filter_state_ch1[1] = state1_ch1;
filter_state_ch2[0] = state0_ch2;
filter_state_ch2[1] = state1_ch2;
}
// Declare a function pointer.
HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t *io,
int16_t len,
const int16_t *coefficient,
int32_t *state)
{
int k;
int32_t a1 = 0, b1 = 0, c = 0, in = 0;
int32_t a2 = 0, b2 = 0;
int32_t state0 = state[0];
int32_t state1 = state[1];
for (k=0; k<len; k++) {
in = (int32_t)io[k];
#ifdef WEBRTC_ARCH_ARM_V7
{
register int tmp_coeff0;
register int tmp_coeff1;
__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_16_32_RSFT16(coefficient[5], state0) +
(WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[4], state0) >> 16);
b1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[7], state1) +
(WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[6], state1) >> 16);
/* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
a2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[1], state0) +
(WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[0], state0) >> 16);
b2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[3], state1) +
(WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[2], state1) >> 16);
#endif
c = ((int32_t)in) + WEBRTC_SPL_RSHIFT_W32(a1+b1, 7); // Q0
io[k] = (int16_t)WebRtcSpl_SatW32ToW16(c); // Write output as Q0.
c = WEBRTC_SPL_LSHIFT_W32((int32_t)in, 2) - a2 - b2; // In Q2.
c = (int32_t)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(int16_t *pin,
int16_t *LP16,
int16_t *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;
int16_t tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD];
int16_t tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD];
int32_t tmpState_ch1[2 * (QORDER-1)]; /* 4 */
int32_t tmpState_ch2[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 */
WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
tempin_ch2,
WebRtcIsacfix_kUpperApFactorsQ15,
WebRtcIsacfix_kLowerApFactorsQ15,
FRAMESAMPLES/2,
prefiltdata->INSTAT1_fix,
prefiltdata->INSTAT2_fix);
for (k=0;k<WEBRTC_SPL_MUL_16_16(2, (QORDER-1));k++) {
tmpState_ch1[k] = prefiltdata->INSTAT1_fix[k];
tmpState_ch2[k] = prefiltdata->INSTAT2_fix[k];
}
WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2,
tempin_ch2 + FRAMESAMPLES/2,
WebRtcIsacfix_kUpperApFactorsQ15,
WebRtcIsacfix_kLowerApFactorsQ15,
QLOOKAHEAD,
tmpState_ch1,
tmpState_ch2);
/* Now Construct low-pass and high-pass signals as combinations of polyphase components */
for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) {
int32_t tmp1, tmp2, tmp3;
tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
}
}/*end of WebRtcIsacfix_SplitAndFilter */
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
/* Without lookahead */
void WebRtcIsacfix_SplitAndFilter2(int16_t *pin,
int16_t *LP16,
int16_t *HP16,
PreFiltBankstr *prefiltdata)
{
/* Function WebRtcIsacfix_SplitAndFilter2 */
/* This function creates low-pass and high-pass decimated versions of part of
the input signal. */
int k;
int16_t tempin_ch1[FRAMESAMPLES/2];
int16_t 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 */
WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
tempin_ch2,
WebRtcIsacfix_kUpperApFactorsQ15,
WebRtcIsacfix_kLowerApFactorsQ15,
FRAMESAMPLES/2,
prefiltdata->INSTAT1_fix,
prefiltdata->INSTAT2_fix);
/* Now Construct low-pass and high-pass signals as combinations of polyphase components */
for (k=0; k<FRAMESAMPLES/2; k++) {
int32_t tmp1, tmp2, tmp3;
tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
HP16[k] = (int16_t)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(int16_t *tempin_ch1,
int16_t *tempin_ch2,
int16_t *out16,
PostFiltBankstr *postfiltdata)
{
int k;
int16_t in[FRAMESAMPLES];
/* all-pass filter the new upper and lower channel signal.
For upper channel, 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.
For lower channel signal, 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.
*/
WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
tempin_ch2,
WebRtcIsacfix_kLowerApFactorsQ15,
WebRtcIsacfix_kUpperApFactorsQ15,
FRAMESAMPLES/2,
postfiltdata->STATE_0_UPPER_fix,
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(int16_t *tempin_ch1,
int16_t *tempin_ch2,
int16_t *out16,
PostFiltBankstr *postfiltdata,
int16_t len)
{
int k;
int16_t in[FRAMESAMPLES];
/* all-pass filter the new upper and lower channel signal.
For upper channel, 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.
For lower channel signal, 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.
*/
WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
tempin_ch2,
WebRtcIsacfix_kLowerApFactorsQ15,
WebRtcIsacfix_kUpperApFactorsQ15,
len / 2,
postfiltdata->STATE_0_UPPER_fix,
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

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
// WebRtcIsacfix_AllpassFilter2FixDec16 function optimized for MIPSDSP platform.
// Bit-exact with WebRtcIsacfix_AllpassFilter2FixDec16C from filterbanks.c.
void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(
int16_t* data_ch1, // Input and output in channel 1, in Q0.
int16_t* data_ch2, // Input and output in channel 2, in Q0.
const int16_t* factor_ch1, // Scaling factor for channel 1, in Q15.
const int16_t* factor_ch2, // Scaling factor for channel 2, in Q15.
const int length, // Length of the data buffers.
int32_t* filter_state_ch1, // Filter state for channel 1, in Q16.
int32_t* filter_state_ch2) { // Filter state for channel 2, in Q16.
int32_t st0_ch1, st1_ch1; // channel1 state variables.
int32_t st0_ch2, st1_ch2; // channel2 state variables.
int32_t f_ch10, f_ch11, f_ch20, f_ch21; // factor variables.
int32_t r0, r1, r2, r3, r4, r5; // temporary register variables.
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
// Load all the state and factor variables.
"lh %[f_ch10], 0(%[factor_ch1]) \n\t"
"lh %[f_ch20], 0(%[factor_ch2]) \n\t"
"lh %[f_ch11], 2(%[factor_ch1]) \n\t"
"lh %[f_ch21], 2(%[factor_ch2]) \n\t"
"lw %[st0_ch1], 0(%[filter_state_ch1]) \n\t"
"lw %[st1_ch1], 4(%[filter_state_ch1]) \n\t"
"lw %[st0_ch2], 0(%[filter_state_ch2]) \n\t"
"lw %[st1_ch2], 4(%[filter_state_ch2]) \n\t"
// Allpass filtering loop.
"1: \n\t"
"lh %[r0], 0(%[data_ch1]) \n\t"
"lh %[r1], 0(%[data_ch2]) \n\t"
"addiu %[length], %[length], -1 \n\t"
"mul %[r2], %[r0], %[f_ch10] \n\t"
"mul %[r3], %[r1], %[f_ch20] \n\t"
"sll %[r0], %[r0], 16 \n\t"
"sll %[r1], %[r1], 16 \n\t"
"sll %[r2], %[r2], 1 \n\t"
"addq_s.w %[r2], %[r2], %[st0_ch1] \n\t"
"sll %[r3], %[r3], 1 \n\t"
"addq_s.w %[r3], %[r3], %[st0_ch2] \n\t"
"sra %[r2], %[r2], 16 \n\t"
"mul %[st0_ch1], %[f_ch10], %[r2] \n\t"
"sra %[r3], %[r3], 16 \n\t"
"mul %[st0_ch2], %[f_ch20], %[r3] \n\t"
"mul %[r4], %[r2], %[f_ch11] \n\t"
"mul %[r5], %[r3], %[f_ch21] \n\t"
"sll %[st0_ch1], %[st0_ch1], 1 \n\t"
"subq_s.w %[st0_ch1], %[r0], %[st0_ch1] \n\t"
"sll %[st0_ch2], %[st0_ch2], 1 \n\t"
"subq_s.w %[st0_ch2], %[r1], %[st0_ch2] \n\t"
"sll %[r4], %[r4], 1 \n\t"
"addq_s.w %[r4], %[r4], %[st1_ch1] \n\t"
"sll %[r5], %[r5], 1 \n\t"
"addq_s.w %[r5], %[r5], %[st1_ch2] \n\t"
"sra %[r4], %[r4], 16 \n\t"
"mul %[r0], %[r4], %[f_ch11] \n\t"
"sra %[r5], %[r5], 16 \n\t"
"mul %[r1], %[r5], %[f_ch21] \n\t"
"sh %[r4], 0(%[data_ch1]) \n\t"
"sh %[r5], 0(%[data_ch2]) \n\t"
"addiu %[data_ch1], %[data_ch1], 2 \n\t"
"sll %[r2], %[r2], 16 \n\t"
"sll %[r0], %[r0], 1 \n\t"
"subq_s.w %[st1_ch1], %[r2], %[r0] \n\t"
"sll %[r3], %[r3], 16 \n\t"
"sll %[r1], %[r1], 1 \n\t"
"subq_s.w %[st1_ch2], %[r3], %[r1] \n\t"
"bgtz %[length], 1b \n\t"
" addiu %[data_ch2], %[data_ch2], 2 \n\t"
// Store channel states.
"sw %[st0_ch1], 0(%[filter_state_ch1]) \n\t"
"sw %[st1_ch1], 4(%[filter_state_ch1]) \n\t"
"sw %[st0_ch2], 0(%[filter_state_ch2]) \n\t"
"sw %[st1_ch2], 4(%[filter_state_ch2]) \n\t"
".set pop \n\t"
: [f_ch10] "=&r" (f_ch10), [f_ch20] "=&r" (f_ch20),
[f_ch11] "=&r" (f_ch11), [f_ch21] "=&r" (f_ch21),
[st0_ch1] "=&r" (st0_ch1), [st1_ch1] "=&r" (st1_ch1),
[st0_ch2] "=&r" (st0_ch2), [st1_ch2] "=&r" (st1_ch2),
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
[r3] "=&r" (r3), [r4] "=&r" (r4), [r5] "=&r" (r5)
: [factor_ch1] "r" (factor_ch1), [factor_ch2] "r" (factor_ch2),
[filter_state_ch1] "r" (filter_state_ch1),
[filter_state_ch2] "r" (filter_state_ch2),
[data_ch1] "r" (data_ch1), [data_ch2] "r" (data_ch2),
[length] "r" (length)
: "memory", "hi", "lo"
);
}
// WebRtcIsacfix_HighpassFilterFixDec32 function optimized for MIPSDSP platform.
// Bit-exact with WebRtcIsacfix_HighpassFilterFixDec32C from filterbanks.c.
void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
int16_t len,
const int16_t* coefficient,
int32_t* state) {
int k;
int32_t a1, a2, b1, b2, in;
int32_t state0 = state[0];
int32_t state1 = state[1];
int32_t c0, c1, c2, c3;
int32_t c4, c5, c6, c7;
int32_t state0_lo, state0_hi;
int32_t state1_lo, state1_hi;
int32_t t0, t1, t2, t3, t4, t5;
__asm __volatile (
"lh %[c0], 0(%[coeff_ptr]) \n\t"
"lh %[c1], 2(%[coeff_ptr]) \n\t"
"lh %[c2], 4(%[coeff_ptr]) \n\t"
"lh %[c3], 6(%[coeff_ptr]) \n\t"
"sra %[state0_hi], %[state0], 16 \n\t"
"sra %[state1_hi], %[state1], 16 \n\t"
"andi %[state0_lo], %[state0], 0xFFFF \n\t"
"andi %[state1_lo], %[state1], 0xFFFF \n\t"
"lh %[c4], 8(%[coeff_ptr]) \n\t"
"lh %[c5], 10(%[coeff_ptr]) \n\t"
"lh %[c6], 12(%[coeff_ptr]) \n\t"
"lh %[c7], 14(%[coeff_ptr]) \n\t"
"sra %[state0_lo], %[state0_lo], 1 \n\t"
"sra %[state1_lo], %[state1_lo], 1 \n\t"
: [c0] "=&r" (c0), [c1] "=&r" (c1), [c2] "=&r" (c2), [c3] "=&r" (c3),
[c4] "=&r" (c4), [c5] "=&r" (c5), [c6] "=&r" (c6), [c7] "=&r" (c7),
[state0_hi] "=&r" (state0_hi), [state0_lo] "=&r" (state0_lo),
[state1_hi] "=&r" (state1_hi), [state1_lo] "=&r" (state1_lo)
: [coeff_ptr] "r" (coefficient), [state0] "r" (state0),
[state1] "r" (state1)
: "memory"
);
for (k = 0; k < len; k++) {
in = (int32_t)io[k];
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"mul %[t2], %[c4], %[state0_lo] \n\t"
"mul %[t0], %[c5], %[state0_lo] \n\t"
"mul %[t1], %[c4], %[state0_hi] \n\t"
"mul %[a1], %[c5], %[state0_hi] \n\t"
"mul %[t5], %[c6], %[state1_lo] \n\t"
"mul %[t3], %[c7], %[state1_lo] \n\t"
"mul %[t4], %[c6], %[state1_hi] \n\t"
"mul %[b1], %[c7], %[state1_hi] \n\t"
"shra_r.w %[t2], %[t2], 15 \n\t"
"shra_r.w %[t0], %[t0], 15 \n\t"
"addu %[t1], %[t1], %[t2] \n\t"
"addu %[a1], %[a1], %[t0] \n\t"
"sra %[t1], %[t1], 16 \n\t"
"addu %[a1], %[a1], %[t1] \n\t"
"shra_r.w %[t5], %[t5], 15 \n\t"
"shra_r.w %[t3], %[t3], 15 \n\t"
"addu %[t4], %[t4], %[t5] \n\t"
"addu %[b1], %[b1], %[t3] \n\t"
"sra %[t4], %[t4], 16 \n\t"
"addu %[b1], %[b1], %[t4] \n\t"
"mul %[t2], %[c0], %[state0_lo] \n\t"
"mul %[t0], %[c1], %[state0_lo] \n\t"
"mul %[t1], %[c0], %[state0_hi] \n\t"
"mul %[a2], %[c1], %[state0_hi] \n\t"
"mul %[t5], %[c2], %[state1_lo] \n\t"
"mul %[t3], %[c3], %[state1_lo] \n\t"
"mul %[t4], %[c2], %[state1_hi] \n\t"
"mul %[b2], %[c3], %[state1_hi] \n\t"
"shra_r.w %[t2], %[t2], 15 \n\t"
"shra_r.w %[t0], %[t0], 15 \n\t"
"addu %[t1], %[t1], %[t2] \n\t"
"addu %[a2], %[a2], %[t0] \n\t"
"sra %[t1], %[t1], 16 \n\t"
"addu %[a2], %[a2], %[t1] \n\t"
"shra_r.w %[t5], %[t5], 15 \n\t"
"shra_r.w %[t3], %[t3], 15 \n\t"
"addu %[t4], %[t4], %[t5] \n\t"
"addu %[b2], %[b2], %[t3] \n\t"
"sra %[t4], %[t4], 16 \n\t"
"addu %[b2], %[b2], %[t4] \n\t"
"addu %[a1], %[a1], %[b1] \n\t"
"sra %[a1], %[a1], 7 \n\t"
"addu %[a1], %[a1], %[in] \n\t"
"sll %[t0], %[in], 2 \n\t"
"addu %[a2], %[a2], %[b2] \n\t"
"subu %[t0], %[t0], %[a2] \n\t"
"shll_s.w %[a1], %[a1], 16 \n\t"
"shll_s.w %[t0], %[t0], 2 \n\t"
"sra %[a1], %[a1], 16 \n\t"
"addu %[state1_hi], %[state0_hi], $0 \n\t"
"addu %[state1_lo], %[state0_lo], $0 \n\t"
"sra %[state0_hi], %[t0], 16 \n\t"
"andi %[state0_lo], %[t0], 0xFFFF \n\t"
"sra %[state0_lo], %[state0_lo], 1 \n\t"
".set pop \n\t"
: [a1] "=&r" (a1), [b1] "=&r" (b1), [a2] "=&r" (a2), [b2] "=&r" (b2),
[state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
[state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo),
[t0] "=&r" (t0), [t1] "=&r" (t1), [t2] "=&r" (t2),
[t3] "=&r" (t3), [t4] "=&r" (t4), [t5] "=&r" (t5)
: [c0] "r" (c0), [c1] "r" (c1), [c2] "r" (c2), [c3] "r" (c3),
[c4] "r" (c4), [c5] "r" (c5), [c6] "r" (c6), [c7] "r" (c7),
[in] "r" (in)
: "hi", "lo"
);
io[k] = (int16_t)a1;
}
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
#if !defined(MIPS_DSP_R2_LE)
"sll %[state0_hi], %[state0_hi], 16 \n\t"
"sll %[state0_lo], %[state0_lo], 1 \n\t"
"sll %[state1_hi], %[state1_hi], 16 \n\t"
"sll %[state1_lo], %[state1_lo], 1 \n\t"
"or %[state0_hi], %[state0_hi], %[state0_lo] \n\t"
"or %[state1_hi], %[state1_hi], %[state1_lo] \n\t"
#else
"sll %[state0_lo], %[state0_lo], 1 \n\t"
"sll %[state1_lo], %[state1_lo], 1 \n\t"
"precr_sra.ph.w %[state0_hi], %[state0_lo], 0 \n\t"
"precr_sra.ph.w %[state1_hi], %[state1_lo], 0 \n\t"
#endif
"sw %[state0_hi], 0(%[state]) \n\t"
"sw %[state1_hi], 4(%[state]) \n\t"
".set pop \n\t"
: [state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
[state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo)
: [state] "r" (state)
: "memory"
);
}

View File

@@ -0,0 +1,270 @@
@
@ 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_AllpassFilter2FixDec16Neon()
@ in iSAC codec, optimized for ARM Neon platform. Bit exact with function
@ WebRtcIsacfix_AllpassFilter2FixDec16Neon() in filterbanks.c. Prototype
@ C code is at end of this file.
#include "webrtc/system_wrappers/interface/asm_defines.h"
GLOBAL_FUNCTION WebRtcIsacfix_AllpassFilter2FixDec16Neon
.align 2
@void WebRtcIsacfix_AllpassFilter2FixDec16Neon(
@ int16_t *data_ch1, // Input and output in channel 1, in Q0
@ int16_t *data_ch2, // Input and output in channel 2, in Q0
@ const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
@ const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
@ const int length, // Length of the data buffers
@ int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
@ int32_t *filter_state_ch2); // Filter state for channel 2, in Q16
DEFINE_FUNCTION WebRtcIsacfix_AllpassFilter2FixDec16Neon
push {r4 - r7}
ldr r5, [sp, #24] @ filter_state_ch2
ldr r6, [sp, #20] @ filter_state_ch1
@ Initialize the Neon registers.
vld1.16 d0[0], [r0]! @ data_ch1[0]
vld1.16 d0[2], [r1]! @ data_ch2[0]
vld1.32 d30[0], [r2] @ factor_ch1[0], factor_ch1[1]
vld1.32 d30[1], [r3] @ factor_ch2[0], factor_ch2[1]
vld1.32 d16[0], [r6]! @ filter_state_ch1[0]
vld1.32 d17[0], [r5]! @ filter_state_ch2[0]
vneg.s16 d31, d30
ldr r3, [sp, #16] @ length
mov r4, #4 @ Post offset value for the loop
mov r2, #-2 @ Post offset value for the loop
sub r3, #2 @ Loop counter
@ Loop unrolling pre-processing.
vqdmull.s16 q1, d30, d0
vshll.s16 q0, d0, #16
vqadd.s32 q2, q1, q8
vshrn.i32 d6, q2, #16
vmull.s16 q1, d31, d6
vshl.s32 q1, #1
vqadd.s32 q8, q1, q0
vld1.32 d16[1], [r6] @ filter_state_ch1[1]
vld1.32 d17[1], [r5] @ filter_state_ch2[1]
sub r6, #4 @ &filter_state_ch1[0]
sub r5, #4 @ &filter_state_ch2[0]
vld1.16 d6[1], [r0], r2 @ data_ch1[1]
vld1.16 d6[3], [r1], r2 @ data_ch2[1]
vrev32.16 d0, d6
FOR_LOOP:
vqdmull.s16 q1, d30, d0
vshll.s16 q0, d0, #16
vqadd.s32 q2, q1, q8
vshrn.i32 d4, q2, #16
vmull.s16 q1, d31, d4
vst1.16 d4[1], [r0], r4 @ Store data_ch1[n]
vst1.16 d4[3], [r1], r4 @ Store data_ch2[n]
vshl.s32 q1, #1
vld1.16 d4[1], [r0], r2 @ Load data_ch1[n + 2]
vld1.16 d4[3], [r1], r2 @ Load data_ch2[n + 2]
vqadd.s32 q8, q1, q0
vrev32.16 d0, d4
vqdmull.s16 q1, d30, d0
subs r3, #2
vqadd.s32 q2, q1, q8
vshrn.i32 d6, q2, #16
vmull.s16 q1, d31, d6
vshll.s16 q0, d0, #16
vst1.16 d6[1], [r0], r4 @ Store data_ch1[n + 1]
vst1.16 d6[3], [r1], r4 @ Store data_ch2[n + 1]
vshl.s32 q1, #1
vld1.16 d6[1], [r0], r2 @ Load data_ch1[n + 3]
vld1.16 d6[3], [r1], r2 @ Load data_ch2[n + 3]
vqadd.s32 q8, q1, q0
vrev32.16 d0, d6
bgt FOR_LOOP
@ Loop unrolling post-processing.
vqdmull.s16 q1, d30, d0
vshll.s16 q0, d0, #16
vqadd.s32 q2, q1, q8
vshrn.i32 d4, q2, #16
vmull.s16 q1, d31, d4
vst1.16 d4[1], [r0]! @ Store data_ch1[n]
vst1.16 d4[3], [r1]! @ Store data_ch2[n]
vshl.s32 q1, #1
vqadd.s32 q8, q1, q0
vrev32.16 d0, d4
vqdmull.s16 q1, d30, d0
vshll.s16 q0, d0, #16
vqadd.s32 q2, q1, q8
vshrn.i32 d6, q2, #16
vmull.s16 q1, d31, d6
vst1.16 d6[1], [r0] @ Store data_ch1[n + 1]
vst1.16 d6[3], [r1] @ Store data_ch2[n + 1]
vshl.s32 q1, #1
vst1.32 d16[0], [r6]! @ Store filter_state_ch1[0]
vqadd.s32 q9, q1, q0
vst1.32 d17[0], [r5]! @ Store filter_state_ch1[1]
vst1.32 d18[1], [r6] @ Store filter_state_ch2[0]
vst1.32 d19[1], [r5] @ Store filter_state_ch2[1]
pop {r4 - r7}
bx lr
@void AllpassFilter2FixDec16BothChannels(
@ int16_t *data_ch1, // Input and output in channel 1, in Q0
@ int16_t *data_ch2, // Input and output in channel 2, in Q0
@ const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
@ const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
@ const int length, // Length of the data buffers
@ int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
@ int32_t *filter_state_ch2) { // Filter state for channel 2, in Q16
@ int n = 0;
@ int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
@ int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
@ int16_t sample0_ch1 = 0, sample0_ch2 = 0;
@ int16_t sample1_ch1 = 0, sample1_ch2 = 0;
@ int32_t a0_ch1 = 0, a0_ch2 = 0;
@ int32_t b0_ch1 = 0, b0_ch2 = 0;
@
@ int32_t a1_ch1 = 0, a1_ch2 = 0;
@ int32_t b1_ch1 = 0, b1_ch2 = 0;
@ int32_t b2_ch1 = 0, b2_ch2 = 0;
@
@ // Loop unrolling preprocessing.
@
@ sample0_ch1 = data_ch1[n];
@ sample0_ch2 = data_ch2[n];
@
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[0], sample0_ch1) << 1;
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[0], sample0_ch2) << 1;
@
@ b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
@ b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
@
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b0_ch1 >> 16));
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b0_ch2 >> 16));
@
@ state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1 <<1, (uint32_t)sample0_ch1 << 16);
@ state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2 <<1, (uint32_t)sample0_ch2 << 16);
@
@ sample1_ch1 = data_ch1[n + 1];
@ sample0_ch1 = (int16_t) (b0_ch1 >> 16); //Save as Q0
@ sample1_ch2 = data_ch2[n + 1];
@ sample0_ch2 = (int16_t) (b0_ch2 >> 16); //Save as Q0
@
@
@ for (n = 0; n < length - 2; n += 2) {
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[0], sample1_ch1) << 1;
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[1], sample0_ch1) << 1;
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[0], sample1_ch2 ) << 1;
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[1], sample0_ch2) << 1;
@
@ b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
@ b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1); //Q16+Q16=Q16
@ b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2); //Q16+Q16=Q16
@ b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2); //Q16+Q16=Q16
@
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b1_ch1 >> 16));
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b0_ch1 >> 16));
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b1_ch2 >> 16));
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b0_ch2 >> 16));
@
@ state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 <<16);
@ state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 <<16);
@ state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 <<16);
@ state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 <<16);
@
@ sample0_ch1 = data_ch1[n + 2];
@ sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
@ sample0_ch2 = data_ch2[n + 2];
@ sample1_ch2 = (int16_t) (b1_ch2 >> 16); //Save as Q0
@
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[0], sample0_ch1) << 1;
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[1], sample1_ch1) << 1;
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[0], sample0_ch2) << 1;
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[1], sample1_ch2 ) << 1;
@
@ b2_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
@ b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
@ b2_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
@ b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
@
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b2_ch1 >> 16));
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b1_ch1 >> 16));
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b2_ch2 >> 16));
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b1_ch2 >> 16));
@
@ state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1<<16);
@ state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
@ state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2<<16);
@ state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
@
@
@ sample1_ch1 = data_ch1[n + 3];
@ sample0_ch1 = (int16_t) (b2_ch1 >> 16); //Save as Q0
@ sample1_ch2 = data_ch2[n + 3];
@ sample0_ch2 = (int16_t) (b2_ch2 >> 16); //Save as Q0
@
@ data_ch1[n] = (int16_t) (b0_ch1 >> 16); //Save as Q0
@ data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
@ data_ch2[n] = (int16_t) (b0_ch2 >> 16);
@ data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
@ }
@
@ // Loop unrolling post-processing.
@
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[0], sample1_ch1) << 1;
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[1], sample0_ch1) << 1;
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[0], sample1_ch2 ) << 1;
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[1], sample0_ch2) << 1;
@
@ b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
@ b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1);
@ b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2);
@ b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2);
@
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b1_ch1 >> 16));
@ a0_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b0_ch1 >> 16));
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b1_ch2 >> 16));
@ a0_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b0_ch2 >> 16));
@
@ state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 << 16);
@ state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 << 16);
@ state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 << 16);
@ state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 << 16);
@
@ data_ch1[n] = (int16_t) (b0_ch1 >> 16); //Save as Q0
@ data_ch2[n] = (int16_t) (b0_ch2 >> 16);
@
@ sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
@ sample1_ch2 = (int16_t) (b1_ch2 >> 16); //Save as Q0
@
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(factor_ch1[1], sample1_ch1) << 1;
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(factor_ch2[1], sample1_ch2 ) << 1;
@
@ b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
@ b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
@
@ a1_ch1 = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b1_ch1 >> 16));
@ a1_ch2 = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b1_ch2 >> 16));
@
@ state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
@ state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
@
@ data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
@ data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
@
@ filter_state_ch1[0] = state0_ch1;
@ filter_state_ch1[1] = state1_ch1;
@ filter_state_ch2[0] = state0_ch2;
@ filter_state_ch2[1] = state1_ch2;
@}

View File

@@ -0,0 +1,107 @@
/*
* 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 "gtest/gtest.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
#include "webrtc/typedefs.h"
class FilterBanksTest : public testing::Test {
protected:
// Pass a function pointer to the Tester function.
void CalculateResidualEnergyTester(AllpassFilter2FixDec16
AllpassFilter2FixDec16Function) {
const int kSamples = QLOOKAHEAD;
const int kState = 2;
int16_t data_ch1[kSamples] = {0};
int16_t data_ch2[kSamples] = {0};
int32_t state_ch1[kState] = {0};
int32_t state_ch2[kState] = {0};
const int32_t out_state_ch1[kState] = {-809122714, 1645972152};
const int32_t out_state_ch2[kState] = {428019288, 1057309936};
const int32_t out_data_ch1[kSamples] = {0, 0, 347, 10618, 16718, -7089,
32767, 16913, 27042, 8377, -22973, -28372, -27603, -14804, 398, -25332,
-11200, 18044, 25223, -6839, 1116, -23984, 32717, 7364};
const int32_t out_data_ch2[kSamples] = {0, 0, 3010, 22351, 21106, 16969,
-2095, -664, 3513, -30980, 32767, -23839, 13335, 20289, -6831, 339,
-17207, 32767, 4959, 6177, 32767, 16599, -4747, 20504};
int sign = 1;
for (int i = 0; i < kSamples; i++) {
sign *= -1;
data_ch1[i] = sign * WEBRTC_SPL_WORD32_MAX / (i * i + 1);
data_ch2[i] = sign * WEBRTC_SPL_WORD32_MIN / (i * i + 1);
};
AllpassFilter2FixDec16Function(data_ch1,
data_ch2,
WebRtcIsacfix_kUpperApFactorsQ15,
WebRtcIsacfix_kLowerApFactorsQ15,
kSamples,
state_ch1,
state_ch2);
for (int i = 0; i < kSamples; i++) {
EXPECT_EQ(out_data_ch1[i], data_ch1[i]);
EXPECT_EQ(out_data_ch2[i], data_ch2[i]);
}
for (int i = 0; i < kState; i++) {
EXPECT_EQ(out_state_ch1[i], state_ch1[i]);
EXPECT_EQ(out_state_ch2[i], state_ch2[i]);
}
}
};
TEST_F(FilterBanksTest, AllpassFilter2FixDec16Test) {
CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16C);
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16Neon);
}
#elif defined(WEBRTC_ARCH_ARM_NEON)
CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16Neon);
#endif
}
TEST_F(FilterBanksTest, 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
HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
#if defined(MIPS_DSP_R1_LE)
WebRtcIsacfix_HighpassFilterFixDec32 =
WebRtcIsacfix_HighpassFilterFixDec32MIPS;
#else
WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
#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]);
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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 <assert.h>
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
// Autocorrelation function in fixed point.
// NOTE! Different from SPLIB-version in how it scales the signal.
int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __restrict scale) {
int i = 0;
int j = 0;
int16_t scaling = 0;
int32_t sum = 0;
uint32_t temp = 0;
int64_t prod = 0;
// The ARM assembly code assumptoins.
assert(N % 4 == 0);
assert(N >= 8);
// 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 int32_t kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
static const int32_t kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
static void AllpassFilterForDec32(int16_t *InOut16, //Q0
const int32_t *APSectionFactors, //Q15
int16_t lengthInOut,
int32_t *FilterState) //Q16
{
int n, j;
int32_t 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 = WebRtcSpl_AddSatW32(a, FilterState[j]); //Q16+Q16=Q16
a = WEBRTC_SPL_MUL_16_32_RSFT16(
(int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16),
-APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
FilterState[j] = WebRtcSpl_AddSatW32(
WEBRTC_SPL_LSHIFT_W32(a,1),
WEBRTC_SPL_LSHIFT_W32((uint32_t)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
InOut16[n] = (int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0
}
}
}
void WebRtcIsacfix_DecimateAllpass32(const int16_t *in,
int32_t *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
int16_t N, /* number of input samples */
int16_t *out) /* array of size N/2 */
{
int n;
int16_t data_vec[PITCH_FRAME_LEN];
/* copy input */
memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(int16_t), (N-1)));
data_vec[0] = (int16_t) 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((uint32_t)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] = WebRtcSpl_AddSatW16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)],
data_vec[WEBRTC_SPL_MUL_16_16(2, n) + 1]);
}
}

View File

@@ -0,0 +1,365 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
// MIPS optimized implementation of the Autocorrelation function in fixed point.
// NOTE! Different from SPLIB-version in how it scales the signal.
int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
const int16_t* __restrict x,
int16_t N,
int16_t order,
int16_t* __restrict scale) {
int i = 0;
int16_t scaling = 0;
int16_t* in = (int16_t*)x;
int loop_size = (int)(N >> 3);
int count = (int)(N & 7);
// Declare temporary variables used as registry values.
int32_t r0, r1, r2, r3;
#if !defined(MIPS_DSP_R2_LE)
// For non-DSPR2 optimizations 4 more registers are used.
int32_t r4, r5, r6, r7;
#endif
// Calculate r[0] and scaling needed.
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"mult $0, $0 \n\t"
// Loop is unrolled 8 times, set accumulator to zero in branch delay slot.
"beqz %[loop_size], 2f \n\t"
" mult $0, $0 \n\t"
"1: \n\t"
// Load 8 samples per loop iteration.
#if defined(MIPS_DSP_R2_LE)
"ulw %[r0], 0(%[in]) \n\t"
"ulw %[r1], 4(%[in]) \n\t"
"ulw %[r2], 8(%[in]) \n\t"
"ulw %[r3], 12(%[in]) \n\t"
#else
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 2(%[in]) \n\t"
"lh %[r2], 4(%[in]) \n\t"
"lh %[r3], 6(%[in]) \n\t"
"lh %[r4], 8(%[in]) \n\t"
"lh %[r5], 10(%[in]) \n\t"
"lh %[r6], 12(%[in]) \n\t"
"lh %[r7], 14(%[in]) \n\t"
#endif
"addiu %[loop_size], %[loop_size], -1 \n\t"
// Multiply and accumulate.
#if defined(MIPS_DSP_R2_LE)
"dpa.w.ph $ac0, %[r0], %[r0] \n\t"
"dpa.w.ph $ac0, %[r1], %[r1] \n\t"
"dpa.w.ph $ac0, %[r2], %[r2] \n\t"
"dpa.w.ph $ac0, %[r3], %[r3] \n\t"
#else
"madd %[r0], %[r0] \n\t"
"madd %[r1], %[r1] \n\t"
"madd %[r2], %[r2] \n\t"
"madd %[r3], %[r3] \n\t"
"madd %[r4], %[r4] \n\t"
"madd %[r5], %[r5] \n\t"
"madd %[r6], %[r6] \n\t"
"madd %[r7], %[r7] \n\t"
#endif
"bnez %[loop_size], 1b \n\t"
" addiu %[in], %[in], 16 \n\t"
"2: \n\t"
"beqz %[count], 4f \n\t"
#if defined(MIPS_DSP_R1_LE)
" extr.w %[r0], $ac0, 31 \n\t"
#else
" mfhi %[r2] \n\t"
#endif
// Process remaining samples (if any).
"3: \n\t"
"lh %[r0], 0(%[in]) \n\t"
"addiu %[count], %[count], -1 \n\t"
"madd %[r0], %[r0] \n\t"
"bnez %[count], 3b \n\t"
" addiu %[in], %[in], 2 \n\t"
#if defined(MIPS_DSP_R1_LE)
"extr.w %[r0], $ac0, 31 \n\t"
#else
"mfhi %[r2] \n\t"
#endif
"4: \n\t"
#if !defined(MIPS_DSP_R1_LE)
"mflo %[r3] \n\t"
"sll %[r0], %[r2], 1 \n\t"
"srl %[r1], %[r3], 31 \n\t"
"addu %[r0], %[r0], %[r1] \n\t"
#endif
// Calculate scaling (the value of shifting).
"clz %[r1], %[r0] \n\t"
"addiu %[r1], %[r1], -32 \n\t"
"subu %[scaling], $0, %[r1] \n\t"
"slti %[r1], %[r0], 0x1 \n\t"
"movn %[scaling], $0, %[r1] \n\t"
#if defined(MIPS_DSP_R1_LE)
"extrv.w %[r0], $ac0, %[scaling] \n\t"
"mfhi %[r2], $ac0 \n\t"
#else
"addiu %[r1], %[scaling], -32 \n\t"
"subu %[r1], $0, %[r1] \n\t"
"sllv %[r1], %[r2], %[r1] \n\t"
"srlv %[r0], %[r3], %[scaling] \n\t"
"addu %[r0], %[r0], %[r1] \n\t"
#endif
"slti %[r1], %[scaling], 32 \n\t"
"movz %[r0], %[r2], %[r1] \n\t"
".set pop \n\t"
: [loop_size] "+r" (loop_size), [in] "+r" (in), [r0] "=&r" (r0),
[r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
#if !defined(MIPS_DSP_R2_LE)
[r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
#endif
[count] "+r" (count), [scaling] "=r" (scaling)
: [N] "r" (N)
: "memory", "hi", "lo"
);
r[0] = r0;
// Correlation calculation is divided in 3 cases depending on the scaling
// value (different accumulator manipulation needed). Three slightly different
// loops are written in order to avoid branches inside the loop.
if (scaling == 0) {
// In this case, the result will be in low part of the accumulator.
for (i = 1; i < order + 1; i++) {
in = (int16_t*)x;
int16_t* in1 = (int16_t*)x + i;
count = N - i;
loop_size = (count) >> 2;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"mult $0, $0 \n\t"
"beqz %[loop_size], 2f \n\t"
" andi %[count], %[count], 0x3 \n\t"
// Loop processing 4 pairs of samples per iteration.
"1: \n\t"
#if defined(MIPS_DSP_R2_LE)
"ulw %[r0], 0(%[in]) \n\t"
"ulw %[r1], 0(%[in1]) \n\t"
"ulw %[r2], 4(%[in]) \n\t"
"ulw %[r3], 4(%[in1]) \n\t"
#else
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"lh %[r2], 2(%[in]) \n\t"
"lh %[r3], 2(%[in1]) \n\t"
"lh %[r4], 4(%[in]) \n\t"
"lh %[r5], 4(%[in1]) \n\t"
"lh %[r6], 6(%[in]) \n\t"
"lh %[r7], 6(%[in1]) \n\t"
#endif
"addiu %[loop_size], %[loop_size], -1 \n\t"
#if defined(MIPS_DSP_R2_LE)
"dpa.w.ph $ac0, %[r0], %[r1] \n\t"
"dpa.w.ph $ac0, %[r2], %[r3] \n\t"
#else
"madd %[r0], %[r1] \n\t"
"madd %[r2], %[r3] \n\t"
"madd %[r4], %[r5] \n\t"
"madd %[r6], %[r7] \n\t"
#endif
"addiu %[in], %[in], 8 \n\t"
"bnez %[loop_size], 1b \n\t"
" addiu %[in1], %[in1], 8 \n\t"
"2: \n\t"
"beqz %[count], 4f \n\t"
" mflo %[r0] \n\t"
// Process remaining samples (if any).
"3: \n\t"
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"addiu %[count], %[count], -1 \n\t"
"addiu %[in], %[in], 2 \n\t"
"madd %[r0], %[r1] \n\t"
"bnez %[count], 3b \n\t"
" addiu %[in1], %[in1], 2 \n\t"
"mflo %[r0] \n\t"
"4: \n\t"
".set pop \n\t"
: [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
#if !defined(MIPS_DSP_R2_LE)
[r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
#endif
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
[count] "+r" (count)
:
: "memory", "hi", "lo"
);
r[i] = r0;
}
} else if (scaling == 32) {
// In this case, the result will be high part of the accumulator.
for (i = 1; i < order + 1; i++) {
in = (int16_t*)x;
int16_t* in1 = (int16_t*)x + i;
count = N - i;
loop_size = (count) >> 2;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"mult $0, $0 \n\t"
"beqz %[loop_size], 2f \n\t"
" andi %[count], %[count], 0x3 \n\t"
// Loop processing 4 pairs of samples per iteration.
"1: \n\t"
#if defined(MIPS_DSP_R2_LE)
"ulw %[r0], 0(%[in]) \n\t"
"ulw %[r1], 0(%[in1]) \n\t"
"ulw %[r2], 4(%[in]) \n\t"
"ulw %[r3], 4(%[in1]) \n\t"
#else
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"lh %[r2], 2(%[in]) \n\t"
"lh %[r3], 2(%[in1]) \n\t"
"lh %[r4], 4(%[in]) \n\t"
"lh %[r5], 4(%[in1]) \n\t"
"lh %[r6], 6(%[in]) \n\t"
"lh %[r7], 6(%[in1]) \n\t"
#endif
"addiu %[loop_size], %[loop_size], -1 \n\t"
#if defined(MIPS_DSP_R2_LE)
"dpa.w.ph $ac0, %[r0], %[r1] \n\t"
"dpa.w.ph $ac0, %[r2], %[r3] \n\t"
#else
"madd %[r0], %[r1] \n\t"
"madd %[r2], %[r3] \n\t"
"madd %[r4], %[r5] \n\t"
"madd %[r6], %[r7] \n\t"
#endif
"addiu %[in], %[in], 8 \n\t"
"bnez %[loop_size], 1b \n\t"
" addiu %[in1], %[in1], 8 \n\t"
"2: \n\t"
"beqz %[count], 4f \n\t"
" mfhi %[r0] \n\t"
// Process remaining samples (if any).
"3: \n\t"
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"addiu %[count], %[count], -1 \n\t"
"addiu %[in], %[in], 2 \n\t"
"madd %[r0], %[r1] \n\t"
"bnez %[count], 3b \n\t"
" addiu %[in1], %[in1], 2 \n\t"
"mfhi %[r0] \n\t"
"4: \n\t"
".set pop \n\t"
: [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
#if !defined(MIPS_DSP_R2_LE)
[r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
#endif
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
[count] "+r" (count)
:
: "memory", "hi", "lo"
);
r[i] = r0;
}
} else {
// In this case, the result is obtained by combining low and high parts
// of the accumulator.
#if !defined(MIPS_DSP_R1_LE)
int32_t tmp_shift = 32 - scaling;
#endif
for (i = 1; i < order + 1; i++) {
in = (int16_t*)x;
int16_t* in1 = (int16_t*)x + i;
count = N - i;
loop_size = (count) >> 2;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"mult $0, $0 \n\t"
"beqz %[loop_size], 2f \n\t"
" andi %[count], %[count], 0x3 \n\t"
"1: \n\t"
#if defined(MIPS_DSP_R2_LE)
"ulw %[r0], 0(%[in]) \n\t"
"ulw %[r1], 0(%[in1]) \n\t"
"ulw %[r2], 4(%[in]) \n\t"
"ulw %[r3], 4(%[in1]) \n\t"
#else
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"lh %[r2], 2(%[in]) \n\t"
"lh %[r3], 2(%[in1]) \n\t"
"lh %[r4], 4(%[in]) \n\t"
"lh %[r5], 4(%[in1]) \n\t"
"lh %[r6], 6(%[in]) \n\t"
"lh %[r7], 6(%[in1]) \n\t"
#endif
"addiu %[loop_size], %[loop_size], -1 \n\t"
#if defined(MIPS_DSP_R2_LE)
"dpa.w.ph $ac0, %[r0], %[r1] \n\t"
"dpa.w.ph $ac0, %[r2], %[r3] \n\t"
#else
"madd %[r0], %[r1] \n\t"
"madd %[r2], %[r3] \n\t"
"madd %[r4], %[r5] \n\t"
"madd %[r6], %[r7] \n\t"
#endif
"addiu %[in], %[in], 8 \n\t"
"bnez %[loop_size], 1b \n\t"
" addiu %[in1], %[in1], 8 \n\t"
"2: \n\t"
"beqz %[count], 4f \n\t"
#if defined(MIPS_DSP_R1_LE)
" extrv.w %[r0], $ac0, %[scaling] \n\t"
#else
" mfhi %[r0] \n\t"
#endif
"3: \n\t"
"lh %[r0], 0(%[in]) \n\t"
"lh %[r1], 0(%[in1]) \n\t"
"addiu %[count], %[count], -1 \n\t"
"addiu %[in], %[in], 2 \n\t"
"madd %[r0], %[r1] \n\t"
"bnez %[count], 3b \n\t"
" addiu %[in1], %[in1], 2 \n\t"
#if defined(MIPS_DSP_R1_LE)
"extrv.w %[r0], $ac0, %[scaling] \n\t"
#else
"mfhi %[r0] \n\t"
#endif
"4: \n\t"
#if !defined(MIPS_DSP_R1_LE)
"mflo %[r1] \n\t"
"sllv %[r0], %[r0], %[tmp_shift] \n\t"
"srlv %[r1], %[r1], %[scaling] \n\t"
"addu %[r0], %[r0], %[r1] \n\t"
#endif
".set pop \n\t"
: [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
#if !defined(MIPS_DSP_R2_LE)
[r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
#endif
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
[count] "+r" (count)
: [scaling] "r" (scaling)
#if !defined(MIPS_DSP_R1_LE)
, [tmp_shift] "r" (tmp_shift)
#endif
: "memory", "hi", "lo"
);
r[i] = r0;
}
}
*scale = scaling;
return (order + 1);
}

View File

@@ -0,0 +1,145 @@
@
@ 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.
@
@ Reference code in filters.c. Output is bit-exact.
#include "webrtc/system_wrappers/interface/asm_defines.h"
GLOBAL_FUNCTION WebRtcIsacfix_AutocorrNeon
.align 2
@ int WebRtcIsacfix_AutocorrNeon(
@ int32_t* __restrict r,
@ const int16_t* __restrict x,
@ int16_t N,
@ int16_t order,
@ int16_t* __restrict scale);
DEFINE_FUNCTION WebRtcIsacfix_AutocorrNeon
push {r3 - r12}
@ Constant initializations
mov r4, #33
vmov.i32 d0, #0
vmov.i32 q8, #0
vmov.i32 d29, #0 @ Initialize (-scale).
vmov.u8 d30, #255 @ Initialize d30 as -1.
vmov.i32 d0[0], r4 @ d0: 00000033 (low), 00000000 (high)
vmov.i32 d25, #32
mov r5, r1 @ x
mov r6, r2 @ N
@ Generate the first coefficient r0.
LOOP_R0:
vld1.16 {d18}, [r5]! @ x[]
subs r6, r6, #4
vmull.s16 q9, d18, d18
vpadal.s32 q8, q9
bgt LOOP_R0
vadd.i64 d16, d16, d17
@ Calculate scaling (the value of shifting).
vmov d17, d16
@ Check overflow and determine the value for 'scale'.
@ vclz cannot deal with a 64-bit, so we have to do vclz on both the upper and
@ lower 32-bit words. Note that we don't care about the value of the upper
@ word in d17.
@ Check the case of 1 bit overflow. If it occurs store the results for
@ scale and r[0] in d17 and d29.
vshr.u64 d3, d16, #1
vclt.s32 d1, d16, #0 @ < 0 ?
vbit d17, d3, d1 @ For r[0]
vbit d29, d30, d1 @ -scale = -1
@ For the case of more than 1 bit overflow. If it occurs overwrite the
@ results for scale and r[0] in d17 and d29.
vclz.s32 d5, d16 @ Leading zeros of the two 32 bit words.
vshr.s64 d26, d5, #32 @ Keep only the upper 32 bits.
vsub.i64 d31, d26, d0 @ zeros - 33
vshl.i64 d27, d26, #32
vorr d27, d26 @ Duplicate the high word with its low one.
vshl.u64 d2, d16, d31 @ Shift by (-scale).
vclt.s32 d1, d27, d25 @ < 32 ?
vbit d17, d2, d1 @ For r[0]
vbit d29, d31, d1 @ -scale
vst1.32 d17[0], [r0]! @ r[0]
mov r5, #1 @ outer loop counter
@ Generate rest of the coefficients
LOOP_R:
vmov.i32 q8, #0 @ Initialize the accumulation result.
vmov.i32 q9, #0 @ Initialize the accumulation result.
mov r7, r1 @ &x[0]
add r6, r7, r5, lsl #1 @ x[i]
sub r12, r2, r5 @ N - i
lsr r8, r12, #3 @ inner loop counter
sub r12, r8, lsl #3 @ Leftover samples to be processed
LOOP_8X_SAMPLES: @ Multiple of 8 samples
vld1.16 {d20, d21}, [r7]! @ x[0, ...]
vld1.16 {d22, d23}, [r6]! @ x[i, ...]
vmull.s16 q12, d20, d22
vmull.s16 q13, d21, d23
subs r8, #1
vpadal.s32 q8, q12
vpadal.s32 q9, q13
bgt LOOP_8X_SAMPLES
cmp r12, #4
blt REST_SAMPLES
Four_SAMPLES:
vld1.16 d20, [r7]!
vld1.16 d22, [r6]!
vmull.s16 q12, d20, d22
vpadal.s32 q8, q12
sub r12, #4
REST_SAMPLES:
mov r8, #0 @ Initialize lower word of the accumulation.
mov r4, #0 @ Initialize upper word of the accumulation.
cmp r12, #0
ble SUMUP
LOOP_REST_SAMPLES:
ldrh r9, [r7], #2 @ x[0, ...]
ldrh r10, [r6], #2 @ x[i, ...]
smulbb r11, r9, r10
adds r8, r8, r11 @ lower word of the accumulation.
adc r4, r4, r11, asr #31 @ upper word of the accumulation.
subs r12, #1
bgt LOOP_REST_SAMPLES
@ Added the multiplication results together and do a shift.
SUMUP:
vadd.i64 d16, d17
vadd.i64 d18, d19
vadd.i64 d18, d16
vmov d17, r8, r4
vadd.i64 d18, d17
vshl.s64 d18, d29 @ Shift left by (-scale).
vst1.32 d18[0], [r0]! @ r[i]
add r5, #1
cmp r5, r3
ble LOOP_R
vneg.s32 d29, d29 @ Get value for 'scale'.
ldr r2, [sp, #40] @ &scale
add r0, r3, #1 @ return (order + 1)
vst1.s16 d29[0], [r2] @ Store 'scale'
pop {r3 - r12}
bx lr

View File

@@ -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.
*/
#include "gtest/gtest.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
#include "webrtc/typedefs.h"
class FiltersTest : public testing::Test {
protected:
// Pass a function pointer to the Tester function.
void FiltersTester(AutocorrFix WebRtcIsacfix_AutocorrFixFunction) {
const int kOrder = 12;
const int kBuffer = 40;
int16_t scale = 0;
int32_t r_buffer[kOrder + 2] = {0};
// Test an overflow case.
const int16_t x_buffer_0[kBuffer] = {0, 0, 3010, 22351, 21106, 16969, -2095,
-664, 3513, -30980, 32767, -23839, 13335, 20289, -6831, 339, -17207,
32767, 4959, 6177, 32767, 16599, -4747, 20504, 3513, -30980, 32767,
-23839, 13335, 20289, 0, -16969, -2095, -664, 3513, 31981, 32767,
-13839, 23336, 30281};
const int32_t r_expected_0[kOrder + 2] = {1872498461, -224288754, 203789985,
483400487, -208272635, 2436500, 137785322, 266600814, -208486262,
329510080, 137949184, -161738972, -26894267, 237630192};
WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_0,
kBuffer, kOrder + 1, &scale);
for (int i = 0; i < kOrder + 2; i++) {
EXPECT_EQ(r_expected_0[i], r_buffer[i]);
}
EXPECT_EQ(3, scale);
// Test a no-overflow case.
const int16_t x_buffer_1[kBuffer] = {0, 0, 300, 21, 206, 169, -295,
-664, 3513, -300, 327, -29, 15, 289, -6831, 339, -107,
37, 59, 6177, 327, 169, -4747, 204, 313, -980, 767,
-9, 135, 289, 0, -6969, -2095, -664, 0, 1, 7,
-39, 236, 281};
const int32_t r_expected_1[kOrder + 2] = {176253864, 8126617, 1983287,
-26196788, -3487363, -42839676, -24644043, 3469813, 30559879, 31905045,
5101567, 29328896, -55787438, -13163978};
WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_1,
kBuffer, kOrder + 1, &scale);
for (int i = 0; i < kOrder + 2; i++) {
EXPECT_EQ(r_expected_1[i], r_buffer[i]);
}
EXPECT_EQ(0, scale);
}
};
TEST_F(FiltersTest, AutocorrFixTest) {
FiltersTester(WebRtcIsacfix_AutocorrC);
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
FiltersTester(WebRtcIsacfix_AutocorrNeon);
}
#elif defined(WEBRTC_ARCH_ARM_NEON)
FiltersTester(WebRtcIsacfix_AutocorrNeon);
#endif
}

View File

@@ -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] = (int16_t) 0;
maskdata->DataBufferHiQ0[k] = (int16_t) 0;
}
for (k = 0; k < ORDERLO+1; k++) {
maskdata->CorrBufLoQQ[k] = (int32_t) 0;
maskdata->CorrBufLoQdom[k] = 0;
maskdata->PreStateLoGQ15[k] = 0;
}
for (k = 0; k < ORDERHI+1; k++) {
maskdata->CorrBufHiQQ[k] = (int32_t) 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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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.
{
'targets': [
{
'target_name': 'iSACFix',
'type': 'static_library',
'dependencies': [
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'include_dirs': [
'../interface',
'<(webrtc_root)'
],
'direct_dependent_settings': {
'include_dirs': [
'../interface',
'<(webrtc_root)',
],
},
'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_estimator_c.c',
'pitch_filter.c',
'pitch_filter_c.c',
'pitch_gain_tables.c',
'pitch_lag_tables.c',
'spectrum_ar_model_tables.c',
'transform.c',
'transform_tables.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 arm_version==7) or target_arch=="armv7"', {
'dependencies': [ 'isac_neon', ],
'sources': [
'lattice_armv7.S',
'pitch_filter_armv6.S',
],
'sources!': [
'lattice_c.c',
'pitch_filter_c.c',
],
}],
['target_arch=="mipsel"', {
'sources': [
'entropy_coding_mips.c',
'filters_mips.c',
'lattice_mips.c',
'pitch_estimator_mips.c',
'transform_mips.c',
],
'sources!': [
'lattice_c.c',
'pitch_estimator_c.c',
],
'conditions': [
['mips_dsp_rev>0', {
'sources': [
'filterbanks_mips.c',
],
}],
['mips_dsp_rev>1', {
'sources': [
'lpc_masking_model_mips.c',
'pitch_filter_mips.c',
],
'sources!': [
'pitch_filter_c.c',
],
}],
],
}],
],
},
],
'conditions': [
['(target_arch=="arm" and arm_version==7) or target_arch=="armv7"', {
'targets': [
{
'target_name': 'isac_neon',
'type': 'static_library',
'includes': ['../../../../../../build/arm_neon.gypi',],
'dependencies': [
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
],
'include_dirs': [
'<(webrtc_root)',
],
'sources': [
'entropy_coding_neon.c',
'filterbanks_neon.S',
'filters_neon.S',
'lattice_neon.S',
'lpc_masking_model_neon.S',
'transform_neon.S',
],
},
],
}],
],
}

View File

@@ -0,0 +1,311 @@
/*
* 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) \
((int32_t)(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 int32_t*int32_t 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 int32_t. In the
cases used in here, the int32_t will be enough, since (for a good
reason) the involved multiplicands aren't big enough to overflow a
int32_t after shifting right 16 bits. I have compared the result of a
multiplication between t32 and tmp32, done in two ways:
1) Using (int32_t) (((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
}
}
/* filter the signal using normalized lattice filter */
/* MA filter */
void WebRtcIsacfix_NormLatticeFilterMa(int16_t orderCoef,
int32_t *stateGQ15,
int16_t *lat_inQ0,
int16_t *filt_coefQ15,
int32_t *gain_lo_hiQ17,
int16_t lo_hi,
int16_t *lat_outQ9)
{
int16_t sthQ15[MAX_AR_MODEL_ORDER];
int16_t cthQ15[MAX_AR_MODEL_ORDER];
int u, i, k, n;
int16_t temp2,temp3;
int16_t ord_1 = orderCoef+1;
int32_t inv_cthQ16[MAX_AR_MODEL_ORDER];
int32_t gain32, fQtmp;
int16_t gain16;
int16_t gain_sh;
int32_t tmp32, tmp32b;
int32_t fQ15vec[HALF_SUBFRAMELEN];
int32_t gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
int16_t sh;
int16_t t16a;
int16_t t16b;
for (u=0;u<SUBFRAMES;u++)
{
int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN);
/* set the Direct Form coefficients */
temp2 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef);
temp3 = (int16_t)WEBRTC_SPL_MUL_16_16(2, u)+lo_hi;
/* compute lattice filter coefficients */
memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(int16_t));
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((int32_t)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16
}
gain16 = (int16_t) 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((int32_t)lat_inQ0[i + temp1], 15); //Q15
gQ15[0][i] = WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
t16b = (int16_t) (tmp32-WEBRTC_SPL_LSHIFT_W32(((int32_t)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 = (int16_t) 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(int16_t orderCoef,
int16_t *stateGQ0,
int32_t *lat_inQ25,
int16_t *filt_coefQ15,
int32_t *gain_lo_hiQ17,
int16_t lo_hi,
int16_t *lat_outQ0)
{
int ii,n,k,i,u;
int16_t sthQ15[MAX_AR_MODEL_ORDER];
int16_t cthQ15[MAX_AR_MODEL_ORDER];
int32_t tmp32;
int16_t tmpAR;
int16_t ARfQ0vec[HALF_SUBFRAMELEN];
int16_t ARgQ0vec[MAX_AR_MODEL_ORDER+1];
int32_t inv_gain32;
int16_t inv_gain16;
int16_t den16;
int16_t sh;
int16_t temp2,temp3;
int16_t 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 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef);
temp3 = (int16_t)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 = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits)
inv_gain32 = WebRtcSpl_DivW32W16((int32_t)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh)
//initial conditions
inv_gain16 = (int16_t) 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] = (int16_t)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 = (int16_t)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] = (int16_t)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;
}

View File

@@ -0,0 +1,75 @@
@
@ 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 "webrtc/system_wrappers/interface/asm_defines.h"
#include "settings.h"
GLOBAL_FUNCTION WebRtcIsacfix_FilterArLoop
.align 2
DEFINE_FUNCTION WebRtcIsacfix_FilterArLoop
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

View File

@@ -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 = (int16_t)WebRtcSpl_SatW32ToW16(tmp32);
ar_g_Q0[k + 1] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32_2);
}
ar_f_Q0[n + 1] = tmpAR;
ar_g_Q0[0] = tmpAR;
}
}

View File

@@ -0,0 +1,327 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/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 count = order_coef - 1;
int offset;
#if !defined(MIPS_DSP_R1_LE)
int16_t* tmp_cth;
int16_t* tmp_sth;
int16_t* tmp_arg;
int32_t max_q16 = 0x7fff;
int32_t min_q16 = 0xffff8000;
#endif
// Declare variables used as temporary registers.
int32_t r0, r1, r2, t0, t1, t2, t_ar;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"bltz %[count], 2f \n\t"
" lh %[t_ar], 0(%[tmp]) \n\t"
// Inner loop
"1: \n\t"
"sll %[offset], %[count], 1 \n\t"
#if defined(MIPS_DSP_R1_LE)
"lhx %[r0], %[offset](%[cth_Q15]) \n\t"
"lhx %[r1], %[offset](%[sth_Q15]) \n\t"
"lhx %[r2], %[offset](%[ar_g_Q0]) \n\t"
#else
"addu %[tmp_cth], %[cth_Q15], %[offset] \n\t"
"addu %[tmp_sth], %[sth_Q15], %[offset] \n\t"
"addu %[tmp_arg], %[ar_g_Q0], %[offset] \n\t"
"lh %[r0], 0(%[tmp_cth]) \n\t"
"lh %[r1], 0(%[tmp_sth]) \n\t"
"lh %[r2], 0(%[tmp_arg]) \n\t"
#endif
"mul %[t0], %[r0], %[t_ar] \n\t"
"mul %[t1], %[r1], %[t_ar] \n\t"
"mul %[t2], %[r1], %[r2] \n\t"
"mul %[r0], %[r0], %[r2] \n\t"
"subu %[t0], %[t0], %[t2] \n\t"
"addu %[t1], %[t1], %[r0] \n\t"
#if defined(MIPS_DSP_R1_LE)
"shra_r.w %[t1], %[t1], 15 \n\t"
"shra_r.w %[t0], %[t0], 15 \n\t"
#else
"addiu %[t1], %[t1], 0x4000 \n\t"
"sra %[t1], %[t1], 15 \n\t"
"addiu %[t0], %[t0], 0x4000 \n\t"
"sra %[t0], %[t0], 15 \n\t"
#endif
"addiu %[offset], %[offset], 2 \n\t"
#if defined(MIPS_DSP_R1_LE)
"shll_s.w %[t1], %[t1], 16 \n\t"
"shll_s.w %[t_ar], %[t0], 16 \n\t"
#else
"slt %[r0], %[t1], %[max_q16] \n\t"
"slt %[r1], %[t0], %[max_q16] \n\t"
"movz %[t1], %[max_q16], %[r0] \n\t"
"movz %[t0], %[max_q16], %[r1] \n\t"
#endif
"addu %[offset], %[offset], %[ar_g_Q0] \n\t"
#if defined(MIPS_DSP_R1_LE)
"sra %[t1], %[t1], 16 \n\t"
"sra %[t_ar], %[t_ar], 16 \n\t"
#else
"slt %[r0], %[t1], %[min_q16] \n\t"
"slt %[r1], %[t0], %[min_q16] \n\t"
"movn %[t1], %[min_q16], %[r0] \n\t"
"movn %[t0], %[min_q16], %[r1] \n\t"
"addu %[t_ar], $zero, %[t0] \n\t"
#endif
"sh %[t1], 0(%[offset]) \n\t"
"bgtz %[count], 1b \n\t"
" addiu %[count], %[count], -1 \n\t"
"2: \n\t"
"sh %[t_ar], 0(%[tmp]) \n\t"
"sh %[t_ar], 0(%[ar_g_Q0]) \n\t"
".set pop \n\t"
: [t_ar] "=&r" (t_ar), [count] "+r" (count), [offset] "=&r" (offset),
[r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [t0] "=&r" (t0),
#if !defined(MIPS_DSP_R1_LE)
[tmp_cth] "=&r" (tmp_cth), [tmp_sth] "=&r" (tmp_sth),
[tmp_arg] "=&r" (tmp_arg),
#endif
[t1] "=&r" (t1), [t2] "=&r" (t2)
: [tmp] "r" (&ar_f_Q0[n+1]), [cth_Q15] "r" (cth_Q15),
#if !defined(MIPS_DSP_R1_LE)
[max_q16] "r" (max_q16), [min_q16] "r" (min_q16),
#endif
[sth_Q15] "r" (sth_Q15), [ar_g_Q0] "r" (ar_g_Q0)
: "memory", "hi", "lo"
);
}
}
// MIPS optimization of the 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_FilterMaLoopMIPS and WebRtcIsacfix_FilterMaLoopC
// are not bit-exact. The accuracy of the MIPS function is same or better.
void WebRtcIsacfix_FilterMaLoopMIPS(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
#if defined(MIPS_DSP_R2_LE)
// MIPS DSPR2 version. 4 available accumulators allows loop unrolling 4 times.
// This variant is not bit-exact with WebRtcIsacfix_FilterMaLoopC, since we
// are exploiting 64-bit accumulators. The accuracy of the MIPS DSPR2 function
// is same or better.
int n = (HALF_SUBFRAMELEN - 1) >> 2;
int m = (HALF_SUBFRAMELEN - 1) & 3;
int r0, r1, r2, r3;
int t0, t1, t2, t3;
int s0, s1, s2, s3;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"1: \n\t"
"lw %[r0], 0(%[ptr0]) \n\t"
"lw %[r1], 4(%[ptr0]) \n\t"
"lw %[r2], 8(%[ptr0]) \n\t"
"lw %[r3], 12(%[ptr0]) \n\t"
"mult $ac0, %[r0], %[input0] \n\t"
"mult $ac1, %[r1], %[input0] \n\t"
"mult $ac2, %[r2], %[input0] \n\t"
"mult $ac3, %[r3], %[input0] \n\t"
"lw %[t0], 0(%[ptr2]) \n\t"
"extr_rs.w %[s0], $ac0, 15 \n\t"
"extr_rs.w %[s1], $ac1, 15 \n\t"
"extr_rs.w %[s2], $ac2, 15 \n\t"
"extr_rs.w %[s3], $ac3, 15 \n\t"
"lw %[t1], 4(%[ptr2]) \n\t"
"lw %[t2], 8(%[ptr2]) \n\t"
"lw %[t3], 12(%[ptr2]) \n\t"
"addu %[t0], %[t0], %[s0] \n\t"
"addu %[t1], %[t1], %[s1] \n\t"
"addu %[t2], %[t2], %[s2] \n\t"
"addu %[t3], %[t3], %[s3] \n\t"
"mult $ac0, %[t0], %[input2] \n\t"
"mult $ac1, %[t1], %[input2] \n\t"
"mult $ac2, %[t2], %[input2] \n\t"
"mult $ac3, %[t3], %[input2] \n\t"
"addiu %[ptr0], %[ptr0], 16 \n\t"
"extr_rs.w %[t0], $ac0, 16 \n\t"
"extr_rs.w %[t1], $ac1, 16 \n\t"
"extr_rs.w %[t2], $ac2, 16 \n\t"
"extr_rs.w %[t3], $ac3, 16 \n\t"
"addiu %[n], %[n], -1 \n\t"
"mult $ac0, %[r0], %[input1] \n\t"
"mult $ac1, %[r1], %[input1] \n\t"
"mult $ac2, %[r2], %[input1] \n\t"
"mult $ac3, %[r3], %[input1] \n\t"
"sw %[t0], 0(%[ptr2]) \n\t"
"extr_rs.w %[s0], $ac0, 15 \n\t"
"extr_rs.w %[s1], $ac1, 15 \n\t"
"extr_rs.w %[s2], $ac2, 15 \n\t"
"extr_rs.w %[s3], $ac3, 15 \n\t"
"sw %[t1], 4(%[ptr2]) \n\t"
"sw %[t2], 8(%[ptr2]) \n\t"
"sw %[t3], 12(%[ptr2]) \n\t"
"mult $ac0, %[t0], %[input0] \n\t"
"mult $ac1, %[t1], %[input0] \n\t"
"mult $ac2, %[t2], %[input0] \n\t"
"mult $ac3, %[t3], %[input0] \n\t"
"addiu %[ptr2], %[ptr2], 16 \n\t"
"extr_rs.w %[t0], $ac0, 15 \n\t"
"extr_rs.w %[t1], $ac1, 15 \n\t"
"extr_rs.w %[t2], $ac2, 15 \n\t"
"extr_rs.w %[t3], $ac3, 15 \n\t"
"addu %[t0], %[t0], %[s0] \n\t"
"addu %[t1], %[t1], %[s1] \n\t"
"addu %[t2], %[t2], %[s2] \n\t"
"addu %[t3], %[t3], %[s3] \n\t"
"sw %[t0], 0(%[ptr1]) \n\t"
"sw %[t1], 4(%[ptr1]) \n\t"
"sw %[t2], 8(%[ptr1]) \n\t"
"sw %[t3], 12(%[ptr1]) \n\t"
"bgtz %[n], 1b \n\t"
" addiu %[ptr1], %[ptr1], 16 \n\t"
"beq %[m], %0, 3f \n\t"
" nop \n\t"
"2: \n\t"
"lw %[r0], 0(%[ptr0]) \n\t"
"lw %[t0], 0(%[ptr2]) \n\t"
"addiu %[ptr0], %[ptr0], 4 \n\t"
"mult $ac0, %[r0], %[input0] \n\t"
"mult $ac1, %[r0], %[input1] \n\t"
"extr_rs.w %[r1], $ac0, 15 \n\t"
"extr_rs.w %[t1], $ac1, 15 \n\t"
"addu %[t0], %[t0], %[r1] \n\t"
"mult $ac0, %[t0], %[input2] \n\t"
"extr_rs.w %[t0], $ac0, 16 \n\t"
"sw %[t0], 0(%[ptr2]) \n\t"
"mult $ac0, %[t0], %[input0] \n\t"
"addiu %[ptr2], %[ptr2], 4 \n\t"
"addiu %[m], %[m], -1 \n\t"
"extr_rs.w %[t0], $ac0, 15 \n\t"
"addu %[t0], %[t0], %[t1] \n\t"
"sw %[t0], 0(%[ptr1]) \n\t"
"bgtz %[m], 2b \n\t"
" addiu %[ptr1], %[ptr1], 4 \n\t"
"3: \n\t"
".set pop \n\t"
: [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
[r3] "=&r" (r3), [t0] "=&r" (t0), [t1] "=&r" (t1),
[t2] "=&r" (t2), [t3] "=&r" (t3), [s0] "=&r" (s0),
[s1] "=&r" (s1), [s2] "=&r" (s2), [s3] "=&r" (s3),
[ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1), [m] "+r" (m),
[ptr2] "+r" (ptr2), [n] "+r" (n)
: [input0] "r" (input0), [input1] "r" (input1),
[input2] "r" (input2)
: "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi",
"$ac2lo", "$ac3hi", "$ac3lo"
);
#else
// Non-DSPR2 version of the function. Avoiding the accumulator usage due to
// large latencies. This variant is bit-exact with C code.
int n = HALF_SUBFRAMELEN - 1;
int32_t t16a, t16b;
int32_t r0, r1, r2, r3, r4;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"sra %[t16a], %[input2], 16 \n\t"
"andi %[t16b], %[input2], 0xFFFF \n\t"
#if defined(MIPS32R2_LE)
"seh %[t16b], %[t16b] \n\t"
"seh %[input0], %[input0] \n\t"
"seh %[input1], %[input1] \n\t"
#else
"sll %[t16b], %[t16b], 16 \n\t"
"sra %[t16b], %[t16b], 16 \n\t"
"sll %[input0], %[input0], 16 \n\t"
"sra %[input0], %[input0], 16 \n\t"
"sll %[input1], %[input1], 16 \n\t"
"sra %[input1], %[input1], 16 \n\t"
#endif
"addiu %[r0], %[t16a], 1 \n\t"
"slt %[r1], %[t16b], $zero \n\t"
"movn %[t16a], %[r0], %[r1] \n\t"
"1: \n\t"
"lw %[r0], 0(%[ptr0]) \n\t"
"lw %[r1], 0(%[ptr2]) \n\t"
"addiu %[ptr0], %[ptr0], 4 \n\t"
"sra %[r2], %[r0], 16 \n\t"
"andi %[r0], %[r0], 0xFFFF \n\t"
"mul %[r3], %[r2], %[input0] \n\t"
"mul %[r4], %[r0], %[input0] \n\t"
"mul %[r2], %[r2], %[input1] \n\t"
"mul %[r0], %[r0], %[input1] \n\t"
"addiu %[ptr2], %[ptr2], 4 \n\t"
"sll %[r3], %[r3], 1 \n\t"
"sra %[r4], %[r4], 1 \n\t"
"addiu %[r4], %[r4], 0x2000 \n\t"
"sra %[r4], %[r4], 14 \n\t"
"addu %[r3], %[r3], %[r4] \n\t"
"addu %[r1], %[r1], %[r3] \n\t"
"sra %[r3], %[r1], 16 \n\t"
"andi %[r4], %[r1], 0xFFFF \n\t"
"sra %[r4], %[r4], 1 \n\t"
"mul %[r1], %[r1], %[t16a] \n\t"
"mul %[r3], %[r3], %[t16b] \n\t"
"mul %[r4], %[r4], %[t16b] \n\t"
"sll %[r2], %[r2], 1 \n\t"
"sra %[r0], %[r0], 1 \n\t"
"addiu %[r0], %[r0], 0x2000 \n\t"
"sra %[r0], %[r0], 14 \n\t"
"addu %[r0], %[r0], %[r2] \n\t"
"addiu %[n], %[n], -1 \n\t"
"addu %[r1], %[r1], %[r3] \n\t"
"addiu %[r4], %[r4], 0x4000 \n\t"
"sra %[r4], %[r4], 15 \n\t"
"addu %[r1], %[r1], %[r4] \n\t"
"sra %[r2], %[r1], 16 \n\t"
"andi %[r3], %[r1], 0xFFFF \n\t"
"mul %[r3], %[r3], %[input0] \n\t"
"mul %[r2], %[r2], %[input0] \n\t"
"sw %[r1], -4(%[ptr2]) \n\t"
"sra %[r3], %[r3], 1 \n\t"
"addiu %[r3], %[r3], 0x2000 \n\t"
"sra %[r3], %[r3], 14 \n\t"
"addu %[r0], %[r0], %[r3] \n\t"
"sll %[r2], %[r2], 1 \n\t"
"addu %[r0], %[r0], %[r2] \n\t"
"sw %[r0], 0(%[ptr1]) \n\t"
"bgtz %[n], 1b \n\t"
" addiu %[ptr1], %[ptr1], 4 \n\t"
".set pop \n\t"
: [t16a] "=&r" (t16a), [t16b] "=&r" (t16b), [r0] "=&r" (r0),
[r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
[r4] "=&r" (r4), [ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1),
[ptr2] "+r" (ptr2), [n] "+r" (n)
: [input0] "r" (input0), [input1] "r" (input1),
[input2] "r" (input2)
: "hi", "lo", "memory"
);
#endif
}

View File

@@ -0,0 +1,146 @@
@
@ 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.
#include "webrtc/system_wrappers/interface/asm_defines.h"
#include "settings.h"
GLOBAL_FUNCTION WebRtcIsacfix_FilterMaLoopNeon
.align 2
DEFINE_FUNCTION WebRtcIsacfix_FilterMaLoopNeon
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

View File

@@ -0,0 +1,959 @@
/*
* 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(
int16_t *a16, /* Q11 */
int16_t useOrder,
int16_t *k16 /* Q15 */
)
{
int m, k;
int32_t tmp32[MAX_AR_MODEL_ORDER];
int32_t tmp32b;
int32_t tmp_inv_denum32;
int16_t 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 = ((int32_t) 1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]); // (1 - k^2) in Q30
tmp_inv_denum16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp_inv_denum32, 15); // (1 - k^2) in Q15
for (k=1; k<=m; k++) {
tmp32b = WEBRTC_SPL_LSHIFT_W32((int32_t)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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q12>>1 => Q11
}
tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092);
k16[m-1] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmp32[m], 3); //Q12<<3 => Q15
}
return;
}
int16_t WebRtcSpl_LevinsonW32_JSK(
int32_t *R, /* (i) Autocorrelation of length >= order+1 */
int16_t *A, /* (o) A[0..order] LPC coefficients (Q11) */
int16_t *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */
int16_t order /* (i) filter order */
) {
int16_t i, j;
int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
/* Aurocorr coefficients in high precision */
int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
/* LPC coefficients in high precicion */
int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
/* LPC coefficients for next iteration */
int16_t K_hi, K_low; /* reflection coefficient in high precision */
int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
and with scale factor */
int16_t tmp_hi, tmp_low;
int32_t temp1W32, temp2W32, temp3W32;
int16_t 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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
R_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16)), 1);
}
/* K = A[1] = -R[1] / R[0] */
temp2W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[1],16) +
WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
A_low[1] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int32_t)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */
/* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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((int32_t)R_hi[i], 16) +
WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int32_t)0x7fffffffL;
} else
{
temp3W32 = (int32_t)0x80000000L;
}
}
/* Put K on hi and low format */
K_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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 ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)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((int32_t)A_hi[j],16) +
WEBRTC_SPL_LSHIFT_W32((int32_t)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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
A_upd_low[j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
A_upd_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int32_t)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */
/* Convert 1- K^2 in hi and low format */
tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)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((int32_t)A_hi[i], 16) +
WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[i], 1);
/* Round and store upper word */
A[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32+(int32_t)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 int16_t 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 int16_t kPolyVecLo[12] = {
29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
};
static const int16_t kPolyVecHi[6] = {
26214, 20972, 16777, 13422, 10737, 8590
};
static __inline int32_t log2_Q8_LPC( uint32_t x ) {
int32_t zeros, lg2;
int16_t frac;
zeros=WebRtcSpl_NormU32(x);
frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
/* log2(x) */
lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
return lg2;
}
static const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */
static const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
static const int16_t 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 int16_t *input, const int16_t *pitchGains_Q12,
uint32_t *oldEnergy, int16_t *varscale)
{
int k;
uint32_t nrgQ[4];
int16_t nrgQlog[4];
int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
int32_t expPg32;
int16_t expPg, divVal;
int16_t 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] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
}
oldNrgQlog = (int16_t)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 = (int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pgQ,11); /* pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 */
pg3 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pg3,13); /* Q17*Q14>>13 =>Q18 */
pg3 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pg3, kMulPitchGain ,5); /* Q10 kMulPitchGain = -25 = -200 in Q-3. */
tmp16=(int16_t)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((uint16_t)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
if (tmp16_1<0)
expPg=(int16_t) -WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
else
expPg=(int16_t) -WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
} else
expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */
expPg32 = (int32_t)WEBRTC_SPL_LSHIFT_W16((int32_t)expPg, 8); /* Q22 */
divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
tmp16=(int16_t)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((uint16_t)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
if (tmp16_1<0)
expPg=(int16_t) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
else
expPg=(int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
} else
expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */
*varscale = expPg-1;
*oldEnergy = nrgQ[3];
}
static __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10
int16_t tmp16_1, tmp16_2;
tmp16_2=(int16_t)(0x0400|(x&0x03FF));
tmp16_1=-(int16_t)WEBRTC_SPL_RSHIFT_W16(x,10);
if(tmp16_1>0)
return (int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
else
return (int16_t) 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(int16_t *inLoQ0,
int16_t *inHiQ0,
MaskFiltstr_enc *maskdata,
int16_t snrQ10,
const int16_t *pitchGains_Q12,
int32_t *gain_lo_hiQ17,
int16_t *lo_coeffQ15,
int16_t *hi_coeffQ15)
{
int k, n, ii;
int pos1, pos2;
int sh_lo, sh_hi, sh, ssh, shMem;
int16_t varscaleQ14;
int16_t tmpQQlo, tmpQQhi;
int32_t tmp32;
int16_t tmp16,tmp16b;
int16_t polyHI[ORDERHI+1];
int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN];
int32_t corrloQQ[ORDERLO+2];
int32_t corrhiQQ[ORDERHI+1];
int32_t corrlo2QQ[ORDERLO+1];
int16_t scale;
int16_t QdomLO, QdomHI, newQdomHI, newQdomLO;
int32_t res_nrgQQ;
int32_t sqrt_nrg;
/* less-noise-at-low-frequencies factor */
int16_t 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
*/
int16_t snrq;
int shft;
int16_t tmp16a;
int32_t tmp32a, tmp32b, tmp32c;
int16_t a_LOQ11[ORDERLO+1];
int16_t k_vecloQ15[ORDERLO];
int16_t a_HIQ12[ORDERHI+1];
int16_t k_vechiQ15[ORDERHI];
int16_t stab;
snrq=snrQ10;
/* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/
tmp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(snrq, 172, 10); // Q10
tmp16b = exp2_Q10_T(tmp16); // Q10
snrq = (int16_t) 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 = (int16_t) WEBRTC_SPL_RSHIFT_W32(
(WEBRTC_SPL_MUL_16_16(22938, (8192 + WEBRTC_SPL_RSHIFT_W32(varscaleQ14, 1)))
+ ((int32_t)32768)), 16);
/* Calculate tmp = (1.0 + aa*aa); in Q12 */
tmp16 = (int16_t) 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 = (int16_t) 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] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
DataHiQ6[pos1] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
}
pos2 = (int16_t)(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] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
DataHiQ6[pos1] = (int16_t) 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((int32_t) 1, QdomLO-20);
corrlo2QQ[0] += tmp32;
tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 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++) {
int32_t tmp, tmpB, tmpCorr;
int16_t alpha=328; //0.01 in Q15
int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
int16_t 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++) {
int32_t tmp, tmpB, tmpCorr;
int16_t alpha=328; //0.01 in Q15
int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
int16_t 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] = (int16_t) ((WEBRTC_SPL_MUL_16_16(
kPolyVecLo[n-1], a_LOQ11[n]) + ((int32_t) (1 << 14))) >> 15);
}
polyHI[0] = a_HIQ12[0];
for (n = 1; n <= ORDERHI; n++) {
a_HIQ12[n] = (int16_t) ((WEBRTC_SPL_MUL_16_16(
kPolyVecHi[n-1], a_HIQ12[n]) + ((int32_t) (1 << 14))) >> 15);
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((int32_t) 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 = (int16_t) 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; //(int32_t)WEBRTC_SPL_LSHIFT_W32( (int32_t)1, 17); // Gains in Q17
}
gain_lo_hiQ17++;
/* copy coefficients to output array */
for (n = 0; n < ORDERLO; n++) {
*lo_coeffQ15 = (int16_t) (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((int32_t) 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 = (int16_t) 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; //(int32_t)WEBRTC_SPL_LSHIFT_W32( (int32_t)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++;
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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 int16_t *input,
const int16_t *pitchGains_Q12,
uint32_t *oldEnergy,
int16_t *varscale);
void WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0,
int16_t *inHiQ0,
MaskFiltstr_enc *maskdata,
int16_t snrQ10,
const int16_t *pitchGains_Q12,
int32_t *gain_lo_hiQ17,
int16_t *lo_coeffQ15,
int16_t *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
#if defined(MIPS_DSP_R2_LE)
int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(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_ */

View File

@@ -0,0 +1,237 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
// MIPS DSPR2 optimization for function WebRtcIsacfix_CalculateResidualEnergy
// Bit-exact with WebRtcIsacfix_CalculateResidualEnergyC from file
// lpc_masking_model.c
int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(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;
int32_t tmp_corr_c = corr_coeffs[0];
int16_t* tmp_a_poly = &a_polynomial[0];
int32_t sum64_hi = 0;
int32_t sum64_lo = 0;
for (j = 0; j <= lpc_order; j++) {
// For the case of i == 0:
// residual_energy +=
// a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
int32_t tmp2, tmp3;
int16_t sign_1;
int16_t sign_2;
int16_t sign_3;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"lh %[tmp2], 0(%[tmp_a_poly]) \n\t"
"mul %[tmp32], %[tmp2], %[tmp2] \n\t"
"addiu %[tmp_a_poly], %[tmp_a_poly], 2 \n\t"
"sra %[sign_2], %[sum64_hi], 31 \n\t"
"mult $ac0, %[tmp32], %[tmp_corr_c] \n\t"
"shilov $ac0, %[shift_internal] \n\t"
"mfhi %[tmp2], $ac0 \n\t"
"mflo %[tmp3], $ac0 \n\t"
"sra %[sign_1], %[tmp2], 31 \n\t"
"xor %[sign_3], %[sign_1], %[sign_2] \n\t"
".set pop \n\t"
: [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
[tmp_a_poly] "+r" (tmp_a_poly), [sign_1] "=&r" (sign_1),
[sign_3] "=&r" (sign_3), [sign_2] "=&r" (sign_2),
[sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
: [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
: "hi", "lo", "memory"
);
if (sign_3 != 0) {
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
: [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
: "hi", "lo", "memory"
);
} else {
if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
// Shift right for overflow.
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addiu %[shift_internal], %[shift_internal], 1 \n\t"
"prepend %[sum64_lo], %[sum64_hi], 1 \n\t"
"sra %[sum64_hi], %[sum64_hi], 1 \n\t"
"prepend %[tmp3], %[tmp2], 1 \n\t"
"sra %[tmp2], %[tmp2], 1 \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
[shift_internal] "+r" (shift_internal),
[sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
:
: "hi", "lo", "memory"
);
} else {
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
: [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
: "hi", "lo", "memory"
);
}
}
}
for (i = 1; i <= lpc_order; i++) {
tmp_corr_c = corr_coeffs[i];
int16_t* tmp_a_poly_j = &a_polynomial[i];
int16_t* tmp_a_poly_j_i = &a_polynomial[0];
for (j = i; j <= lpc_order; j++) {
// For the case of i = 1 .. lpc_order:
// residual_energy +=
// a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
int32_t tmp2, tmp3;
int16_t sign_1;
int16_t sign_2;
int16_t sign_3;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"lh %[tmp3], 0(%[tmp_a_poly_j]) \n\t"
"lh %[tmp2], 0(%[tmp_a_poly_j_i]) \n\t"
"addiu %[tmp_a_poly_j], %[tmp_a_poly_j], 2 \n\t"
"addiu %[tmp_a_poly_j_i], %[tmp_a_poly_j_i], 2 \n\t"
"mul %[tmp32], %[tmp3], %[tmp2] \n\t"
"sll %[tmp32], %[tmp32], 1 \n\t"
"mult $ac0, %[tmp32], %[tmp_corr_c] \n\t"
"shilov $ac0, %[shift_internal] \n\t"
"mfhi %[tmp2], $ac0 \n\t"
"mflo %[tmp3], $ac0 \n\t"
"sra %[sign_1], %[tmp2], 31 \n\t"
"sra %[sign_2], %[sum64_hi], 31 \n\t"
"xor %[sign_3], %[sign_1], %[sign_2] \n\t"
".set pop \n\t"
: [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
[tmp_a_poly_j] "+r" (tmp_a_poly_j), [sign_1] "=&r" (sign_1),
[tmp_a_poly_j_i] "+r" (tmp_a_poly_j_i), [sign_2] "=&r" (sign_2),
[sign_3] "=&r" (sign_3), [sum64_hi] "+r" (sum64_hi),
[sum64_lo] "+r" (sum64_lo)
: [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
: "hi", "lo", "memory"
);
if (sign_3 != 0) {
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3), [sum64_hi] "+r" (sum64_hi),
[sum64_lo] "+r" (sum64_lo)
:
:"memory"
);
} else {
// Test overflow and sum the result.
if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
// Shift right for overflow.
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addiu %[shift_internal], %[shift_internal], 1 \n\t"
"prepend %[sum64_lo], %[sum64_hi], 1 \n\t"
"sra %[sum64_hi], %[sum64_hi], 1 \n\t"
"prepend %[tmp3], %[tmp2], 1 \n\t"
"sra %[tmp2], %[tmp2], 1 \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
[shift_internal] "+r" (shift_internal),
[sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
:
: "hi", "lo", "memory"
);
} else {
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
"addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
".set pop \n\t"
: [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
[sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
:
: "hi", "lo", "memory"
);
}
}
}
}
word32_high = sum64_hi;
word32_low = sum64_lo;
// Calculate the value of shifting (shift_norm) for the 64-bit sum.
if (word32_high != 0) {
shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
int tmp1;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"srl %[residual_energy], %[sum64_lo], %[shift_norm] \n\t"
"li %[tmp1], 32 \n\t"
"subu %[tmp1], %[tmp1], %[shift_norm] \n\t"
"sll %[tmp1], %[sum64_hi], %[tmp1] \n\t"
"or %[residual_energy], %[residual_energy], %[tmp1] \n\t"
".set pop \n\t"
: [residual_energy] "=&r" (residual_energy), [tmp1]"=&r"(tmp1),
[sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
: [shift_norm] "r" (shift_norm)
: "memory"
);
} 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;
}

View File

@@ -0,0 +1,173 @@
@
@ 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.
#include "webrtc/system_wrappers/interface/asm_defines.h"
GLOBAL_FUNCTION 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);
DEFINE_FUNCTION WebRtcIsacfix_CalculateResidualEnergyNeon
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

View File

@@ -0,0 +1,68 @@
/*
* 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 "gtest/gtest.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
#include "webrtc/typedefs.h"
class LpcMaskingModelTest : 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(LpcMaskingModelTest, 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
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 uint16_t WebRtcIsacfix_kSelIndGain[12];
extern const uint16_t WebRtcIsacfix_kSelIndShape[108];
/* cdf array for model indicator */
extern const uint16_t WebRtcIsacfix_kModelCdf[KLT_NUM_MODELS+1];
/* pointer to cdf array for model indicator */
extern const uint16_t *WebRtcIsacfix_kModelCdfPtr[1];
/* initial cdf index for decoder of model indicator */
extern const uint16_t WebRtcIsacfix_kModelInitIndex[1];
/* offset to go from rounded value to quantization index */
extern const int16_t WebRtcIsacfix_kQuantMinGain[12];
extern const int16_t WebRtcIsacfix_kQuantMinShape[108];
/* maximum quantization index */
extern const uint16_t WebRtcIsacfix_kMaxIndGain[12];
extern const uint16_t WebRtcIsacfix_kMaxIndShape[108];
/* index offset */
extern const uint16_t WebRtcIsacfix_kOffsetGain[KLT_NUM_MODELS][12];
extern const uint16_t WebRtcIsacfix_kOffsetShape[KLT_NUM_MODELS][108];
/* initial cdf index for KLT coefficients */
extern const uint16_t WebRtcIsacfix_kInitIndexGain[KLT_NUM_MODELS][12];
extern const uint16_t WebRtcIsacfix_kInitIndexShape[KLT_NUM_MODELS][108];
/* offsets for quantizer representation levels */
extern const uint16_t WebRtcIsacfix_kOfLevelsGain[3];
extern const uint16_t WebRtcIsacfix_kOfLevelsShape[3];
/* quantizer representation levels */
extern const int32_t WebRtcIsacfix_kLevelsGainQ17[1176];
extern const int16_t WebRtcIsacfix_kLevelsShapeQ10[1735];
/* cdf tables for quantizer indices */
extern const uint16_t WebRtcIsacfix_kCdfGain[1212];
extern const uint16_t WebRtcIsacfix_kCdfShape[2059];
/* pointers to cdf tables for quantizer indices */
extern const uint16_t *WebRtcIsacfix_kCdfGainPtr[KLT_NUM_MODELS][12];
extern const uint16_t *WebRtcIsacfix_kCdfShapePtr[KLT_NUM_MODELS][108];
/* code length for all coefficients using different models */
extern const int16_t WebRtcIsacfix_kCodeLenGainQ11[392];
extern const int16_t WebRtcIsacfix_kCodeLenShapeQ11[577];
/* left KLT transforms */
extern const int16_t WebRtcIsacfix_kT1GainQ15[KLT_NUM_MODELS][4];
extern const int16_t WebRtcIsacfix_kT1ShapeQ15[KLT_NUM_MODELS][324];
/* right KLT transforms */
extern const int16_t WebRtcIsacfix_kT2GainQ15[KLT_NUM_MODELS][36];
extern const int16_t WebRtcIsacfix_kT2ShapeQ15[KLT_NUM_MODELS][36];
/* means of log gains and LAR coefficients */
extern const int16_t WebRtcIsacfix_kMeansGainQ8[KLT_NUM_MODELS][12];
extern const int32_t WebRtcIsacfix_kMeansShapeQ17[3][108];
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_ */

View File

@@ -0,0 +1,446 @@
/*
* 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
#ifdef WEBRTC_ARCH_ARM_NEON
#include <arm_neon.h>
#endif
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/system_wrappers/interface/compile_assert_c.h"
/* log2[0.2, 0.5, 0.98] in Q8 */
static const int16_t kLogLagWinQ8[3] = {
-594, -256, -7
};
/* [1 -0.75 0.25] in Q12 */
static const int16_t kACoefQ12[3] = {
4096, -3072, 1024
};
int32_t WebRtcIsacfix_Log2Q8(uint32_t x) {
int32_t zeros, lg2;
int16_t frac;
zeros=WebRtcSpl_NormU32(x);
frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)(WEBRTC_SPL_LSHIFT_W32(x, zeros))&0x7FFFFFFF), 23);
/* log2(magn(i)) */
lg2= (WEBRTC_SPL_LSHIFT_W32((31-zeros), 8)+frac);
return lg2;
}
static __inline int16_t Exp2Q10(int16_t x) { // Both in and out in Q10
int16_t tmp16_1, tmp16_2;
tmp16_2=(int16_t)(0x0400|(x&0x03FF));
tmp16_1=-(int16_t)WEBRTC_SPL_RSHIFT_W16(x,10);
if(tmp16_1>0)
return (int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
else
return (int16_t) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
}
/* 1D parabolic interpolation . All input and output values are in Q8 */
static __inline void Intrp1DQ8(int32_t *x, int32_t *fx, int32_t *y, int32_t *fy) {
int16_t sign1=1, sign2=1;
int32_t r32, q32, t32, nom32, den32;
int16_t 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 = (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) */
/* t in Q31, without signs */
t32 = WebRtcSpl_DivResultInQ31(nom32 * sign1, den32 * sign2);
t16=(int16_t)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=(int16_t)WEBRTC_SPL_MUL_16_16(t16,t16); /* Q8*Q8=Q16 */
tmp16_1 = WEBRTC_SPL_RSHIFT_W16(tmp16_1,2); /* Q16>>2 = Q14 */
t16 = (int16_t)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(int32_t *in, int16_t length, int16_t *bestind)
{
int32_t best[4]= {-100, -100, -100, -100};
int16_t 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;
}
}
}
}
extern void WebRtcIsacfix_PCorr2Q32(const int16_t *in, int32_t *logcorQ8);
void WebRtcIsacfix_InitialPitch(const int16_t *in, /* Q0 */
PitchAnalysisStruct *State,
int16_t *lagsQ7 /* Q7 */
)
{
int16_t buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
int32_t *crrvecQ8_1,*crrvecQ8_2;
int32_t cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2];
int k;
int16_t peaks_indq;
int16_t peakiq[PITCH_LAG_SPAN2];
int32_t corr;
int32_t corr32, corr_max32, corr_max_o32;
int16_t npkq;
int16_t best4q[4]={0,0,0,0};
int32_t xq[3],yq[1],fyq[1];
int32_t *fxq;
int32_t best_lag1q, best_lag2q;
int32_t tmp32a,tmp32b,lag32,ratq;
int16_t start;
int16_t oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16;
int32_t tmp32c,tmp32d, tmp32e;
int16_t old_lagQ;
int32_t old_lagQ8;
int32_t lagsQ8[4];
old_lagQ = State->PFstr_wght.oldlagQ7; // Q7
old_lagQ8= WEBRTC_SPL_LSHIFT_W32((int32_t)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(int16_t), (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],(int16_t*)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 */
WebRtcIsacfix_PCorr2Q32(buf_dec16, crrvecQ8_1);
WebRtcIsacfix_PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2);
/* bias towards pitch lag of previous frame */
tmp32a = WebRtcIsacfix_Log2Q8((uint32_t) old_lagQ8) - 2304;
// log2(0.5*oldlag) in Q8
tmp32b = WEBRTC_SPL_MUL_16_16_RSFT(oldgQ12,oldgQ12, 10); //Q12 & * 4.0;
gain_bias16 = (int16_t) 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 = WebRtcIsacfix_Log2Q8((uint32_t) (k + (PITCH_MIN_LAG/2-2)));
tmp16a = (int16_t) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4
tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(tmp16a,tmp16a, 6); //Q10
tmp16b = (int16_t) tmp32c; // Q10 & <8
tmp32d = WEBRTC_SPL_MUL_16_16_RSFT(tmp16b, 177 , 8); // mult with ln2 in Q8
tmp16c = (int16_t) tmp32d; // Q10 & <4
tmp16d = Exp2Q10((int16_t) -tmp16c); //Q10
tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(gain_bias16,tmp16d,13); // Q10 & * 0.5
bias16 = (int16_t) (1024 + tmp32c); // Q10
tmp32b = WebRtcIsacfix_Log2Q8((uint32_t)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, (int16_t) 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= WebRtcIsacfix_Log2Q8((uint32_t) *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((int16_t) 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 = (int32_t) (WEBRTC_SPL_LSHIFT_W32(tmp32a, 1)) - ratq; // Q8
tmp32c = WEBRTC_SPL_MUL_16_16_RSFT((int16_t) tmp32b, (int16_t) tmp32b, 8); // Q8
tmp32b = (int32_t)tmp32c + (int32_t)WEBRTC_SPL_RSHIFT_W32(ratq, 1);
// (k-r)^2 + 0.5 * r Q8
tmp32c = WebRtcIsacfix_Log2Q8((uint32_t)tmp32a) - 2048;
// offset 8*2^8 , log2(0.5*k) Q8
tmp32d = WebRtcIsacfix_Log2Q8((uint32_t)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, (int16_t) 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= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
tmp32b= WEBRTC_SPL_MUL_16_16_RSFT((int16_t) 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]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[0], 1);
lagsQ7[1]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[1], 1);
lagsQ7[2]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[2], 1);
lagsQ7[3]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[3], 1);
}
void WebRtcIsacfix_PitchAnalysis(const int16_t *inn, /* PITCH_FRAME_LEN samples */
int16_t *outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
PitchAnalysisStruct *State,
int16_t *PitchLags_Q7,
int16_t *PitchGains_Q12)
{
int16_t inbufQ0[PITCH_FRAME_LEN + QLOOKAHEAD];
int16_t 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] = (int16_t) 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];
}
}

View File

@@ -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.
*/
/*
* 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 int16_t *in, /* PITCH_FRAME_LEN samples */
int16_t *outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
PitchAnalysisStruct *State,
int16_t *lagsQ7,
int16_t *PitchGains_Q12);
void WebRtcIsacfix_InitialPitch(const int16_t *in,
PitchAnalysisStruct *State,
int16_t *qlags);
void WebRtcIsacfix_PitchFilter(int16_t *indatFix,
int16_t *outdatQQ,
PitchFiltstr *pfp,
int16_t *lagsQ7,
int16_t *gainsQ12,
int16_t type);
void WebRtcIsacfix_PitchFilterCore(int loopNumber,
int16_t gain,
int index,
int16_t sign,
int16_t* inputState,
int16_t* outputBuff2,
const int16_t* coefficient,
int16_t* inputBuf,
int16_t* outputBuf,
int* index2);
void WebRtcIsacfix_PitchFilterGains(const int16_t *indatQ0,
PitchFiltstr *pfp,
int16_t *lagsQ7,
int16_t *gainsQ12);
void WebRtcIsacfix_DecimateAllpass32(const int16_t *in,
int32_t *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
int16_t N, /* number of input samples */
int16_t *out); /* array of size N/2 */
int32_t WebRtcIsacfix_Log2Q8( uint32_t x );
void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_ */

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
#ifdef WEBRTC_ARCH_ARM_NEON
#include <arm_neon.h>
#endif
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/system_wrappers/interface/compile_assert_c.h"
extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
int16_t scaling,n,k;
int32_t ysum32,csum32, lys, lcs;
int32_t oneQ8;
const int16_t* x;
const int16_t* inptr;
oneQ8 = WEBRTC_SPL_LSHIFT_W32((int32_t)1, 8); // 1.00 in Q8
x = in + PITCH_MAX_LAG / 2 + 2;
scaling = WebRtcSpl_GetScalingSquare((int16_t*)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((int16_t)in[n],
(int16_t)in[n],
scaling); // Q0
csum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)x[n],
(int16_t)in[n],
scaling); // Q0
}
logcorQ8 += PITCH_LAG_SPAN2 - 1;
lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32); // Q8
lys = WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
if (csum32 > 0) {
lcs = WebRtcIsacfix_Log2Q8((uint32_t)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((int16_t)in[k - 1],
(int16_t)in[k - 1],
scaling);
ysum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)in[PITCH_CORR_LEN2 + k - 1],
(int16_t)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 = WebRtcIsacfix_Log2Q8((uint32_t)ysum32); // Q8
lys = WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
if (csum32 > 0) {
lcs = WebRtcIsacfix_Log2Q8((uint32_t)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;
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/system_wrappers/interface/compile_assert_c.h"
extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
int16_t scaling,n,k;
int32_t ysum32,csum32, lys, lcs;
int32_t oneQ8;
const int16_t* x;
const int16_t* inptr;
oneQ8 = WEBRTC_SPL_LSHIFT_W32((int32_t)1, 8); // 1.00 in Q8
x = in + PITCH_MAX_LAG / 2 + 2;
scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
PITCH_CORR_LEN2,
PITCH_CORR_LEN2);
ysum32 = 1;
csum32 = 0;
x = in + PITCH_MAX_LAG / 2 + 2;
{
const int16_t* tmp_x = x;
const int16_t* tmp_in = in;
int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
n = PITCH_CORR_LEN2;
COMPILE_ASSERT(PITCH_CORR_LEN2 % 4 == 0);
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"1: \n\t"
"lh %[tmp1], 0(%[tmp_in]) \n\t"
"lh %[tmp2], 2(%[tmp_in]) \n\t"
"lh %[tmp3], 4(%[tmp_in]) \n\t"
"lh %[tmp4], 6(%[tmp_in]) \n\t"
"lh %[tmp5], 0(%[tmp_x]) \n\t"
"lh %[tmp6], 2(%[tmp_x]) \n\t"
"lh %[tmp7], 4(%[tmp_x]) \n\t"
"lh %[tmp8], 6(%[tmp_x]) \n\t"
"mul %[tmp5], %[tmp1], %[tmp5] \n\t"
"mul %[tmp1], %[tmp1], %[tmp1] \n\t"
"mul %[tmp6], %[tmp2], %[tmp6] \n\t"
"mul %[tmp2], %[tmp2], %[tmp2] \n\t"
"mul %[tmp7], %[tmp3], %[tmp7] \n\t"
"mul %[tmp3], %[tmp3], %[tmp3] \n\t"
"mul %[tmp8], %[tmp4], %[tmp8] \n\t"
"mul %[tmp4], %[tmp4], %[tmp4] \n\t"
"addiu %[n], %[n], -4 \n\t"
"srav %[tmp5], %[tmp5], %[scaling] \n\t"
"srav %[tmp1], %[tmp1], %[scaling] \n\t"
"srav %[tmp6], %[tmp6], %[scaling] \n\t"
"srav %[tmp2], %[tmp2], %[scaling] \n\t"
"srav %[tmp7], %[tmp7], %[scaling] \n\t"
"srav %[tmp3], %[tmp3], %[scaling] \n\t"
"srav %[tmp8], %[tmp8], %[scaling] \n\t"
"srav %[tmp4], %[tmp4], %[scaling] \n\t"
"addu %[ysum32], %[ysum32], %[tmp1] \n\t"
"addu %[csum32], %[csum32], %[tmp5] \n\t"
"addu %[ysum32], %[ysum32], %[tmp2] \n\t"
"addu %[csum32], %[csum32], %[tmp6] \n\t"
"addu %[ysum32], %[ysum32], %[tmp3] \n\t"
"addu %[csum32], %[csum32], %[tmp7] \n\t"
"addu %[ysum32], %[ysum32], %[tmp4] \n\t"
"addu %[csum32], %[csum32], %[tmp8] \n\t"
"addiu %[tmp_in], %[tmp_in], 8 \n\t"
"bgtz %[n], 1b \n\t"
" addiu %[tmp_x], %[tmp_x], 8 \n\t"
".set pop \n\t"
: [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
[tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
[tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [tmp_in] "+r" (tmp_in),
[ysum32] "+r" (ysum32), [tmp_x] "+r" (tmp_x), [csum32] "+r" (csum32),
[n] "+r" (n)
: [scaling] "r" (scaling)
: "memory", "hi", "lo"
);
}
logcorQ8 += PITCH_LAG_SPAN2 - 1;
lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32); // Q8
lys = WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
if (csum32 > 0) {
lcs = WebRtcIsacfix_Log2Q8((uint32_t)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];
const int16_t* tmp_in1 = &in[k - 1];
const int16_t* tmp_in2 = &in[PITCH_CORR_LEN2 + k - 1];
const int16_t* tmp_x = x;
int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
n = PITCH_CORR_LEN2;
csum32 = 0;
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"lh %[tmp1], 0(%[tmp_in1]) \n\t"
"lh %[tmp2], 0(%[tmp_in2]) \n\t"
"mul %[tmp1], %[tmp1], %[tmp1] \n\t"
"mul %[tmp2], %[tmp2], %[tmp2] \n\t"
"srav %[tmp1], %[tmp1], %[scaling] \n\t"
"srav %[tmp2], %[tmp2], %[scaling] \n\t"
"subu %[ysum32], %[ysum32], %[tmp1] \n\t"
"bnez %[scaling], 2f \n\t"
" addu %[ysum32], %[ysum32], %[tmp2] \n\t"
"1: \n\t"
"lh %[tmp1], 0(%[inptr]) \n\t"
"lh %[tmp2], 0(%[tmp_x]) \n\t"
"lh %[tmp3], 2(%[inptr]) \n\t"
"lh %[tmp4], 2(%[tmp_x]) \n\t"
"lh %[tmp5], 4(%[inptr]) \n\t"
"lh %[tmp6], 4(%[tmp_x]) \n\t"
"lh %[tmp7], 6(%[inptr]) \n\t"
"lh %[tmp8], 6(%[tmp_x]) \n\t"
"mul %[tmp1], %[tmp1], %[tmp2] \n\t"
"mul %[tmp2], %[tmp3], %[tmp4] \n\t"
"mul %[tmp3], %[tmp5], %[tmp6] \n\t"
"mul %[tmp4], %[tmp7], %[tmp8] \n\t"
"addiu %[n], %[n], -4 \n\t"
"addiu %[inptr], %[inptr], 8 \n\t"
"addiu %[tmp_x], %[tmp_x], 8 \n\t"
"addu %[csum32], %[csum32], %[tmp1] \n\t"
"addu %[csum32], %[csum32], %[tmp2] \n\t"
"addu %[csum32], %[csum32], %[tmp3] \n\t"
"bgtz %[n], 1b \n\t"
" addu %[csum32], %[csum32], %[tmp4] \n\t"
"b 3f \n\t"
" nop \n\t"
"2: \n\t"
"lh %[tmp1], 0(%[inptr]) \n\t"
"lh %[tmp2], 0(%[tmp_x]) \n\t"
"lh %[tmp3], 2(%[inptr]) \n\t"
"lh %[tmp4], 2(%[tmp_x]) \n\t"
"lh %[tmp5], 4(%[inptr]) \n\t"
"lh %[tmp6], 4(%[tmp_x]) \n\t"
"lh %[tmp7], 6(%[inptr]) \n\t"
"lh %[tmp8], 6(%[tmp_x]) \n\t"
"mul %[tmp1], %[tmp1], %[tmp2] \n\t"
"mul %[tmp2], %[tmp3], %[tmp4] \n\t"
"mul %[tmp3], %[tmp5], %[tmp6] \n\t"
"mul %[tmp4], %[tmp7], %[tmp8] \n\t"
"addiu %[n], %[n], -4 \n\t"
"addiu %[inptr], %[inptr], 8 \n\t"
"addiu %[tmp_x], %[tmp_x], 8 \n\t"
"srav %[tmp1], %[tmp1], %[scaling] \n\t"
"srav %[tmp2], %[tmp2], %[scaling] \n\t"
"srav %[tmp3], %[tmp3], %[scaling] \n\t"
"srav %[tmp4], %[tmp4], %[scaling] \n\t"
"addu %[csum32], %[csum32], %[tmp1] \n\t"
"addu %[csum32], %[csum32], %[tmp2] \n\t"
"addu %[csum32], %[csum32], %[tmp3] \n\t"
"bgtz %[n], 2b \n\t"
" addu %[csum32], %[csum32], %[tmp4] \n\t"
"3: \n\t"
".set pop \n\t"
: [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
[tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
[tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [inptr] "+r" (inptr),
[csum32] "+r" (csum32), [tmp_x] "+r" (tmp_x), [ysum32] "+r" (ysum32),
[n] "+r" (n)
: [tmp_in1] "r" (tmp_in1), [tmp_in2] "r" (tmp_in2),
[scaling] "r" (scaling)
: "memory", "hi", "lo"
);
logcorQ8--;
lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32); // Q8
lys = WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum);
if (csum32 > 0) {
lcs = WebRtcIsacfix_Log2Q8((uint32_t)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;
}
}
}

View File

@@ -0,0 +1,269 @@
/*
* 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/structs.h"
#include "webrtc/system_wrappers/interface/compile_assert_c.h"
// Number of segments in a pitch subframe.
static const int kSegments = 5;
// A division factor of 1/5 in Q15.
static const int16_t kDivFactor = 6553;
// Interpolation coefficients; generated by design_pitch_filter.m.
// Coefficients are stored in Q14.
static const int16_t 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,
int16_t gain,
int index,
int16_t sign,
int16_t* inputState,
int16_t* outputBuf2,
const int16_t* coefficient,
int16_t* inputBuf,
int16_t* outputBuf,
int* index2);
static __inline int32_t CalcLrIntQ(int32_t fixVal,
int16_t qDomain) {
int32_t intgr;
int32_t roundVal;
roundVal = WEBRTC_SPL_LSHIFT_W32((int32_t)1, qDomain - 1);
intgr = WEBRTC_SPL_RSHIFT_W32(fixVal + roundVal, qDomain);
return intgr;
}
void WebRtcIsacfix_PitchFilter(int16_t* indatQQ, // Q10 if type is 1 or 4,
// Q0 if type is 2.
int16_t* outdatQQ,
PitchFiltstr* pfp,
int16_t* lagsQ7,
int16_t* gainsQ12,
int16_t type) {
int k, ind, cnt;
int16_t sign = 1;
int16_t inystateQQ[PITCH_DAMPORDER];
int16_t ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD];
const int16_t Gain = 21299; // 1.3 in Q14
int16_t oldLagQ7;
int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
int indW32 = 0, frcQQ = 0;
int32_t tmpW32;
const int16_t* 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] = (int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
lagdeltaQ7, kDivFactor, 15);
curLagQ7 = oldLagQ7;
gaindeltaQ12 = gainsQ12[k] - oldGainQ12;
gaindeltaQ12 = (int16_t)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 int16_t* indatQ0,
PitchFiltstr* pfp,
int16_t* lagsQ7,
int16_t* gainsQ12) {
int k, n, m, ind, pos, pos3QQ;
int16_t ubufQQ[PITCH_INTBUFFSIZE];
int16_t oldLagQ7, lagdeltaQ7, curLagQ7;
const int16_t* fracoeffQQ = NULL;
int16_t scale;
int16_t cnt = 0, frcQQ, indW16 = 0, tmpW16;
int32_t 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 = (int16_t)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 = (int16_t)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 = (int16_t)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] = (int16_t)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];
}

View File

@@ -0,0 +1,143 @@
@
@ 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 "webrtc/system_wrappers/interface/asm_defines.h"
#include "settings.h"
GLOBAL_FUNCTION WebRtcIsacfix_PitchFilterCore
.align 2
@ void WebRtcIsacfix_PitchFilterCore(int loopNumber,
@ int16_t gain,
@ int index,
@ int16_t sign,
@ int16_t* inputState,
@ int16_t* outputBuf2,
@ const int16_t* coefficient,
@ int16_t* inputBuf,
@ int16_t* outputBuf,
@ int* index2) {
DEFINE_FUNCTION WebRtcIsacfix_PitchFilterCore
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
.align 2
kDampFilter:
.short -2294, 8192, 20972, 8192, -2294

View File

@@ -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 int16_t kDampFilter[PITCH_DAMPORDER] = {
-2294, 8192, 20972, 8192, -2294
};
void WebRtcIsacfix_PitchFilterCore(int loopNumber,
int16_t gain,
int index,
int16_t sign,
int16_t* inputState,
int16_t* outputBuf2,
const int16_t* coefficient,
int16_t* inputBuf,
int16_t* outputBuf,
int* index2) {
int i = 0, j = 0; /* Loop counters. */
int16_t* ubufQQpos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)];
int16_t tmpW16 = 0;
for (i = 0; i < loopNumber; i++) {
int32_t 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 = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 14);
/* Shift low pass filter state. */
memmove(&inputState[1], &inputState[0],
(PITCH_DAMPORDER - 1) * sizeof(int16_t));
inputState[0] = (int16_t)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 = (int16_t)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)++;
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
void WebRtcIsacfix_PitchFilterCore(int loopNumber,
int16_t gain,
int index,
int16_t sign,
int16_t* inputState,
int16_t* outputBuf2,
const int16_t* coefficient,
int16_t* inputBuf,
int16_t* outputBuf,
int* index2) {
int ind2t = *index2;
int i = 0;
int16_t* out2_pos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)] + ind2t;
int32_t w1, w2, w3, w4, w5, gain32, sign32;
int32_t coef1, coef2, coef3, coef4, coef5 = 0;
// Define damp factors as int32_t (pair of int16_t)
int32_t kDampF0 = 0x0000F70A;
int32_t kDampF1 = 0x51EC2000;
int32_t kDampF2 = 0xF70A2000;
int16_t* input1 = inputBuf + ind2t;
int16_t* output1 = outputBuf + ind2t;
int16_t* output2 = outputBuf2 + ind2t + PITCH_BUFFSIZE;
// Load coefficients outside the loop and sign-extend gain and sign
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
"lwl %[coef1], 3(%[coefficient]) \n\t"
"lwl %[coef2], 7(%[coefficient]) \n\t"
"lwl %[coef3], 11(%[coefficient]) \n\t"
"lwl %[coef4], 15(%[coefficient]) \n\t"
"lwr %[coef1], 0(%[coefficient]) \n\t"
"lwr %[coef2], 4(%[coefficient]) \n\t"
"lwr %[coef3], 8(%[coefficient]) \n\t"
"lwr %[coef4], 12(%[coefficient]) \n\t"
"lhu %[coef5], 16(%[coefficient]) \n\t"
"seh %[gain32], %[gain] \n\t"
"seh %[sign32], %[sign] \n\t"
".set pop \n\t"
: [coef1] "=&r" (coef1), [coef2] "=&r" (coef2), [coef3] "=&r" (coef3),
[coef4] "=&r" (coef4), [coef5] "=&r" (coef5), [gain32] "=&r" (gain32),
[sign32] "=&r" (sign32)
: [coefficient] "r" (coefficient), [gain] "r" (gain),
[sign] "r" (sign)
: "memory"
);
for (i = 0; i < loopNumber; i++) {
__asm __volatile (
".set push \n\t"
".set noreorder \n\t"
// Filter to get fractional pitch
"li %[w1], 8192 \n\t"
"mtlo %[w1] \n\t"
"mthi $0 \n\t"
"lwl %[w1], 3(%[out2_pos2]) \n\t"
"lwl %[w2], 7(%[out2_pos2]) \n\t"
"lwl %[w3], 11(%[out2_pos2]) \n\t"
"lwl %[w4], 15(%[out2_pos2]) \n\t"
"lwr %[w1], 0(%[out2_pos2]) \n\t"
"lwr %[w2], 4(%[out2_pos2]) \n\t"
"lwr %[w3], 8(%[out2_pos2]) \n\t"
"lwr %[w4], 12(%[out2_pos2]) \n\t"
"lhu %[w5], 16(%[out2_pos2]) \n\t"
"dpa.w.ph $ac0, %[w1], %[coef1] \n\t"
"dpa.w.ph $ac0, %[w2], %[coef2] \n\t"
"dpa.w.ph $ac0, %[w3], %[coef3] \n\t"
"dpa.w.ph $ac0, %[w4], %[coef4] \n\t"
"dpa.w.ph $ac0, %[w5], %[coef5] \n\t"
"addiu %[out2_pos2], %[out2_pos2], 2 \n\t"
"mthi $0, $ac1 \n\t"
"lwl %[w2], 3(%[inputState]) \n\t"
"lwl %[w3], 7(%[inputState]) \n\t"
// Fractional pitch shift & saturation
"extr_s.h %[w1], $ac0, 14 \n\t"
"li %[w4], 16384 \n\t"
"lwr %[w2], 0(%[inputState]) \n\t"
"lwr %[w3], 4(%[inputState]) \n\t"
"mtlo %[w4], $ac1 \n\t"
// Shift low pass filter state
"swl %[w2], 5(%[inputState]) \n\t"
"swl %[w3], 9(%[inputState]) \n\t"
"mul %[w1], %[gain32], %[w1] \n\t"
"swr %[w2], 2(%[inputState]) \n\t"
"swr %[w3], 6(%[inputState]) \n\t"
// Low pass filter accumulation
"dpa.w.ph $ac1, %[kDampF1], %[w2] \n\t"
"dpa.w.ph $ac1, %[kDampF2], %[w3] \n\t"
"lh %[w4], 0(%[input1]) \n\t"
"addiu %[input1], %[input1], 2 \n\t"
"shra_r.w %[w1], %[w1], 12 \n\t"
"sh %[w1], 0(%[inputState]) \n\t"
"dpa.w.ph $ac1, %[kDampF0], %[w1] \n\t"
// Low pass filter shift & saturation
"extr_s.h %[w2], $ac1, 15 \n\t"
"mul %[w2], %[w2], %[sign32] \n\t"
// Buffer update
"subu %[w2], %[w4], %[w2] \n\t"
"shll_s.w %[w2], %[w2], 16 \n\t"
"sra %[w2], %[w2], 16 \n\t"
"sh %[w2], 0(%[output1]) \n\t"
"addu %[w2], %[w2], %[w4] \n\t"
"shll_s.w %[w2], %[w2], 16 \n\t"
"addiu %[output1], %[output1], 2 \n\t"
"sra %[w2], %[w2], 16 \n\t"
"sh %[w2], 0(%[output2]) \n\t"
"addiu %[output2], %[output2], 2 \n\t"
".set pop \n\t"
: [w1] "=&r" (w1), [w2] "=&r" (w2), [w3] "=&r" (w3), [w4] "=&r" (w4),
[w5] "=&r" (w5), [input1] "+r" (input1), [out2_pos2] "+r" (out2_pos2),
[output1] "+r" (output1), [output2] "+r" (output2)
: [coefficient] "r" (coefficient), [inputState] "r" (inputState),
[gain32] "r" (gain32), [sign32] "r" (sign32), [kDampF0] "r" (kDampF0),
[kDampF1] "r" (kDampF1), [kDampF2] "r" (kDampF2),
[coef1] "r" (coef1), [coef2] "r" (coef2), [coef3] "r" (coef3),
[coef4] "r" (coef4), [coef5] "r" (coef5)
: "hi", "lo", "$ac1hi", "$ac1lo", "memory"
);
}
(*index2) += loopNumber;
}

View File

@@ -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 uint16_t 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 int16_t WebRtcIsacfix_kLowerlimiGain[3] = {
-7, -2, -1
};
const int16_t WebRtcIsacfix_kUpperlimitGain[3] = {
0, 3, 1
};
const uint16_t WebRtcIsacfix_kMultsGain[2] = {
18, 3
};
/* size of cdf table */
const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1] = {
256
};
/* mean values of pitch filter gains in FIXED point Q12 */
const int16_t 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 int16_t 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 int16_t 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 int16_t 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 int16_t WebRtcIsacfix_kTransform[4][4] = {
{ -2048, -2048, -2048, -2048 },
{ 2748, 916, -916, -2748 },
{ 2048, -2048, -2048, 2048 },
{ 916, -2748, 2748, -916 }
};

View File

@@ -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 uint16_t WebRtcIsacfix_kPitchGainCdf[255];
/* index limits and ranges */
extern const int16_t WebRtcIsacfix_kLowerlimiGain[3];
extern const int16_t WebRtcIsacfix_kUpperlimitGain[3];
extern const uint16_t WebRtcIsacfix_kMultsGain[2];
/* mean values of pitch filter gains in Q12*/
extern const int16_t WebRtcIsacfix_kPitchGain1[144];
extern const int16_t WebRtcIsacfix_kPitchGain2[144];
extern const int16_t WebRtcIsacfix_kPitchGain3[144];
extern const int16_t WebRtcIsacfix_kPitchGain4[144];
/* size of cdf table */
extern const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1];
/* transform matrix */
extern const int16_t WebRtcIsacfix_kTransform[4][4];
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_ */

View File

@@ -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 uint16_t 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 uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20] = {
0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535
};
const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2] = {
0, 65535
};
const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10] = {
0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535
};
const uint16_t *WebRtcIsacfix_kPitchLagPtrLo[4] = {
WebRtcIsacfix_kPitchLagCdf1Lo,
WebRtcIsacfix_kPitchLagCdf2Lo,
WebRtcIsacfix_kPitchLagCdf3Lo,
WebRtcIsacfix_kPitchLagCdf4Lo
};
/* size of first cdf table */
const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1] = {
128
};
/* index limits and ranges */
const int16_t WebRtcIsacfix_kLowerLimitLo[4] = {
-140, -9, 0, -4
};
const int16_t WebRtcIsacfix_kUpperLimitLo[4] = {
-20, 9, 0, 4
};
/* initial index for arithmetic decoder */
const uint16_t WebRtcIsacfix_kInitIndLo[3] = {
10, 1, 5
};
/* mean values of pitch filter lags in Q10 */
const int16_t WebRtcIsacfix_kMeanLag2Lo[19] = {
-17627, -16207, -14409, -12319, -10253, -8200, -6054, -3986, -1948, -19,
1937, 3974, 6064, 8155, 10229, 12270, 14296, 16127, 17520
};
const int16_t 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 uint16_t 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 uint16_t 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 uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2] = {
0, 65535
};
const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20] = {
0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535
};
const uint16_t *WebRtcIsacfix_kPitchLagPtrMid[4] = {
WebRtcIsacfix_kPitchLagCdf1Mid,
WebRtcIsacfix_kPitchLagCdf2Mid,
WebRtcIsacfix_kPitchLagCdf3Mid,
WebRtcIsacfix_kPitchLagCdf4Mid
};
/* size of first cdf table */
const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1] = {
256
};
/* index limits and ranges */
const int16_t WebRtcIsacfix_kLowerLimitMid[4] = {
-280, -17, 0, -9
};
const int16_t WebRtcIsacfix_kUpperLimitMid[4] = {
-40, 17, 0, 9
};
/* initial index for arithmetic decoder */
const uint16_t WebRtcIsacfix_kInitIndMid[3] = {
18, 1, 10
};
/* mean values of pitch filter lags in Q10 */
const int16_t 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 int16_t 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 uint16_t 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 uint16_t 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 uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2] = {
0, 65535
};
const uint16_t 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 uint16_t *WebRtcIsacfix_kPitchLagPtrHi[4] = {
WebRtcIsacfix_kPitchLagCdf1Hi,
WebRtcIsacfix_kPitchLagCdf2Hi,
WebRtcIsacfix_kPitchLagCdf3Hi,
WebRtcIsacfix_kPitchLagCdf4Hi
};
/* size of first cdf table */
const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1] = {
512
};
/* index limits and ranges */
const int16_t WebRtcIsacfix_kLowerLimitHi[4] = {
-552, -34, 0, -16
};
const int16_t WebRtcIsacfix_kUpperLimitHi[4] = {
-80, 32, 0, 17
};
/* initial index for arithmetic decoder */
const uint16_t WebRtcIsacfix_kInitIndHi[3] = {
34, 1, 18
};
/* mean values of pitch filter lags */
const int16_t 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 int16_t 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
};

View File

@@ -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 uint16_t WebRtcIsacfix_kPitchLagCdf1Lo[127];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10];
extern const uint16_t *WebRtcIsacfix_kPitchLagPtrLo[4];
/* size of first cdf table */
extern const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1];
/* index limits and ranges */
extern const int16_t WebRtcIsacfix_kLowerLimitLo[4];
extern const int16_t WebRtcIsacfix_kUpperLimitLo[4];
/* initial index for arithmetic decoder */
extern const uint16_t WebRtcIsacfix_kInitIndLo[3];
/* mean values of pitch filter lags */
extern const int16_t WebRtcIsacfix_kMeanLag2Lo[19];
extern const int16_t WebRtcIsacfix_kMeanLag4Lo[9];
/* tables for use with medium pitch gain */
/* cdfs for quantized pitch lags */
extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Mid[255];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Mid[36];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20];
extern const uint16_t *WebRtcIsacfix_kPitchLagPtrMid[4];
/* size of first cdf table */
extern const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1];
/* index limits and ranges */
extern const int16_t WebRtcIsacfix_kLowerLimitMid[4];
extern const int16_t WebRtcIsacfix_kUpperLimitMid[4];
/* initial index for arithmetic decoder */
extern const uint16_t WebRtcIsacfix_kInitIndMid[3];
/* mean values of pitch filter lags */
extern const int16_t WebRtcIsacfix_kMeanLag2Mid[35];
extern const int16_t WebRtcIsacfix_kMeanLag4Mid[19];
/* tables for use with large pitch gain */
/* cdfs for quantized pitch lags */
extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Hi[511];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Hi[68];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2];
extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Hi[35];
extern const uint16_t *WebRtcIsacfix_kPitchLagPtrHi[4];
/* size of first cdf table */
extern const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1];
/* index limits and ranges */
extern const int16_t WebRtcIsacfix_kLowerLimitHi[4];
extern const int16_t WebRtcIsacfix_kUpperLimitHi[4];
/* initial index for arithmetic decoder */
extern const uint16_t WebRtcIsacfix_kInitIndHi[3];
/* mean values of pitch filter lags */
extern const int16_t WebRtcIsacfix_kMeanLag2Hi[67];
extern const int16_t WebRtcIsacfix_kMeanLag4Hi[34];
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_ */

View File

@@ -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 (uint32_t) 24000
/* Three times Sampling frequency */
#define FS3 (uint32_t) 48000
/* Eight times Sampling frequency */
#define FS8 (uint32_t) 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_ */

View File

@@ -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 uint16_t WebRtcIsacfix_kRc1Cdf[12] = {
0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
65533, 65535
};
/* cdf for quantized reflection coefficient 2 */
const uint16_t WebRtcIsacfix_kRc2Cdf[12] = {
0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
65533, 65535
};
/* cdf for quantized reflection coefficient 3 */
const uint16_t WebRtcIsacfix_kRc3Cdf[12] = {
0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
65533, 65535
};
/* cdf for quantized reflection coefficient 4 */
const uint16_t WebRtcIsacfix_kRc4Cdf[12] = {
0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
65533, 65535
};
/* cdf for quantized reflection coefficient 5 */
const uint16_t WebRtcIsacfix_kRc5Cdf[12] = {
0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
65533, 65535
};
/* cdf for quantized reflection coefficient 6 */
const uint16_t WebRtcIsacfix_kRc6Cdf[12] = {
0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
65533, 65535
};
/* representation levels for quantized reflection coefficient 1 */
const int16_t WebRtcIsacfix_kRc1Levels[11] = {
-32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
};
/* representation levels for quantized reflection coefficient 2 */
const int16_t WebRtcIsacfix_kRc2Levels[11] = {
-32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
};
/* representation levels for quantized reflection coefficient 3 */
const int16_t WebRtcIsacfix_kRc3Levels[11] = {
-32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
};
/* representation levels for quantized reflection coefficient 4 */
const int16_t WebRtcIsacfix_kRc4Levels[11] = {
-32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
};
/* representation levels for quantized reflection coefficient 5 */
const int16_t WebRtcIsacfix_kRc5Levels[11] = {
-32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
};
/* representation levels for quantized reflection coefficient 6 */
const int16_t WebRtcIsacfix_kRc6Levels[11] = {
-32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
};
/* quantization boundary levels for reflection coefficients */
const int16_t 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 uint16_t WebRtcIsacfix_kRcInitInd[6] = {
5, 5, 5, 5, 5, 5
};
/* pointers to AR cdf tables */
const uint16_t *WebRtcIsacfix_kRcCdfPtr[AR_ORDER] = {
WebRtcIsacfix_kRc1Cdf,
WebRtcIsacfix_kRc2Cdf,
WebRtcIsacfix_kRc3Cdf,
WebRtcIsacfix_kRc4Cdf,
WebRtcIsacfix_kRc5Cdf,
WebRtcIsacfix_kRc6Cdf
};
/* pointers to AR representation levels tables */
const int16_t *WebRtcIsacfix_kRcLevPtr[AR_ORDER] = {
WebRtcIsacfix_kRc1Levels,
WebRtcIsacfix_kRc2Levels,
WebRtcIsacfix_kRc3Levels,
WebRtcIsacfix_kRc4Levels,
WebRtcIsacfix_kRc5Levels,
WebRtcIsacfix_kRc6Levels
};
/******************** GAIN Coefficient Tables ***********************/
/* cdf for Gain coefficient */
const uint16_t 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 int32_t 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 int32_t 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 uint16_t *WebRtcIsacfix_kGainPtr[1] = {
WebRtcIsacfix_kGainCdf
};
/* gain initial index for gain quantizer and cdf table search */
const uint16_t WebRtcIsacfix_kGainInitInd[1] = {
11
};
/************************* Cosine Tables ****************************/
/* cosine table */
const int16_t 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 }
};

View File

@@ -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 uint16_t WebRtcIsacfix_kRc1Cdf[12];
/* cdf for quantized reflection coefficient 2 */
extern const uint16_t WebRtcIsacfix_kRc2Cdf[12];
/* cdf for quantized reflection coefficient 3 */
extern const uint16_t WebRtcIsacfix_kRc3Cdf[12];
/* cdf for quantized reflection coefficient 4 */
extern const uint16_t WebRtcIsacfix_kRc4Cdf[12];
/* cdf for quantized reflection coefficient 5 */
extern const uint16_t WebRtcIsacfix_kRc5Cdf[12];
/* cdf for quantized reflection coefficient 6 */
extern const uint16_t WebRtcIsacfix_kRc6Cdf[12];
/* representation levels for quantized reflection coefficient 1 */
extern const int16_t WebRtcIsacfix_kRc1Levels[11];
/* representation levels for quantized reflection coefficient 2 */
extern const int16_t WebRtcIsacfix_kRc2Levels[11];
/* representation levels for quantized reflection coefficient 3 */
extern const int16_t WebRtcIsacfix_kRc3Levels[11];
/* representation levels for quantized reflection coefficient 4 */
extern const int16_t WebRtcIsacfix_kRc4Levels[11];
/* representation levels for quantized reflection coefficient 5 */
extern const int16_t WebRtcIsacfix_kRc5Levels[11];
/* representation levels for quantized reflection coefficient 6 */
extern const int16_t WebRtcIsacfix_kRc6Levels[11];
/* quantization boundary levels for reflection coefficients */
extern const int16_t WebRtcIsacfix_kRcBound[12];
/* initial indices for AR reflection coefficient quantizer and cdf table search */
extern const uint16_t WebRtcIsacfix_kRcInitInd[AR_ORDER];
/* pointers to AR cdf tables */
extern const uint16_t *WebRtcIsacfix_kRcCdfPtr[AR_ORDER];
/* pointers to AR representation levels tables */
extern const int16_t *WebRtcIsacfix_kRcLevPtr[AR_ORDER];
/******************** GAIN Coefficient Tables ***********************/
/* cdf for Gain coefficient */
extern const uint16_t WebRtcIsacfix_kGainCdf[19];
/* representation levels for quantized Gain coefficient */
extern const int32_t WebRtcIsacfix_kGain2Lev[18];
/* squared quantization boundary levels for Gain coefficient */
extern const int32_t WebRtcIsacfix_kGain2Bound[19];
/* pointer to Gain cdf table */
extern const uint16_t *WebRtcIsacfix_kGainPtr[1];
/* Gain initial index for gain quantizer and cdf table search */
extern const uint16_t WebRtcIsacfix_kGainInitInd[1];
/************************* Cosine Tables ****************************/
/* Cosine table */
extern const int16_t WebRtcIsacfix_kCos[6][60];
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ */

View File

@@ -0,0 +1,383 @@
/*
* 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 {
uint16_t stream[STREAM_MAXW16_60MS]; /* Array bytestream to decode */
uint32_t W_upper; /* Upper boundary of interval W */
uint32_t streamval;
uint16_t stream_index; /* Index to the current position in bytestream */
int16_t full; /* 0 - first byte in memory filled, second empty*/
/* 1 - both bytes are empty (we just filled the previous memory */
int stream_size; /* The size of stream. */
} Bitstr_dec;
/* Bitstream struct for encoder */
typedef struct Bitstreamstruct_enc {
uint16_t stream[STREAM_MAXW16_60MS]; /* Vector for adding encoded bytestream */
uint32_t W_upper; /* Upper boundary of interval W */
uint32_t streamval;
uint16_t stream_index; /* Index to the current position in bytestream */
int16_t full; /* 0 - first byte in memory filled, second empty*/
/* 1 - both bytes are empty (we just filled the previous memory */
} Bitstr_enc;
typedef struct {
int16_t DataBufferLoQ0[WINLEN];
int16_t DataBufferHiQ0[WINLEN];
int32_t CorrBufLoQQ[ORDERLO+1];
int32_t CorrBufHiQQ[ORDERHI+1];
int16_t CorrBufLoQdom[ORDERLO+1];
int16_t CorrBufHiQdom[ORDERHI+1];
int32_t PreStateLoGQ15[ORDERLO+1];
int32_t PreStateHiGQ15[ORDERHI+1];
uint32_t OldEnergy;
} MaskFiltstr_enc;
typedef struct {
int16_t PostStateLoGQ0[ORDERLO+1];
int16_t PostStateHiGQ0[ORDERHI+1];
uint32_t OldEnergy;
} MaskFiltstr_dec;
typedef struct {
//state vectors for each of the two analysis filters
int32_t INSTAT1_fix[2*(QORDER-1)];
int32_t INSTAT2_fix[2*(QORDER-1)];
int16_t INLABUF1_fix[QLOOKAHEAD];
int16_t INLABUF2_fix[QLOOKAHEAD];
/* High pass filter */
int32_t HPstates_fix[HPORDER];
} PreFiltBankstr;
typedef struct {
//state vectors for each of the two analysis filters
int32_t STATE_0_LOWER_fix[2*POSTQORDER];
int32_t STATE_0_UPPER_fix[2*POSTQORDER];
/* High pass filter */
int32_t HPstates1_fix[HPORDER];
int32_t HPstates2_fix[HPORDER];
} PostFiltBankstr;
typedef struct {
/* data buffer for pitch filter */
int16_t ubufQQ[PITCH_BUFFSIZE];
/* low pass state vector */
int16_t ystateQQ[PITCH_DAMPORDER];
/* old lag and gain */
int16_t oldlagQ7;
int16_t oldgainQ12;
} PitchFiltstr;
typedef struct {
//for inital estimator
int16_t dec_buffer16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2];
int32_t decimator_state32[2*ALLPASSSECTIONS+1];
int16_t inbuf[QLOOKAHEAD];
PitchFiltstr PFstr_wght;
PitchFiltstr PFstr;
} PitchAnalysisStruct;
typedef struct {
/* Parameters used in PLC to avoid re-computation */
/* --- residual signals --- */
int16_t prevPitchInvIn[FRAMESAMPLES/2];
int16_t prevPitchInvOut[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
int32_t prevHP[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
int16_t decayCoeffPriodic; /* how much to supress a sample */
int16_t decayCoeffNoise;
int16_t used; /* if PLC is used */
int16_t *lastPitchLP; // [FRAMESAMPLES/2]; saved 240;
/* --- LPC side info --- */
int16_t lofilt_coefQ15[ ORDERLO ];
int16_t hifilt_coefQ15[ ORDERHI ];
int32_t gain_lo_hiQ17[2];
/* --- LTP side info --- */
int16_t AvgPitchGain_Q12;
int16_t lastPitchGain_Q12;
int16_t lastPitchLag_Q7;
/* --- Add-overlap in recovery packet --- */
int16_t overlapLP[ RECOVERY_OVERLAP ]; // [FRAMESAMPLES/2]; saved 160
int16_t pitchCycles;
int16_t A;
int16_t B;
int16_t pitchIndex;
int16_t stretchLag;
int16_t *prevPitchLP; // [ FRAMESAMPLES/2 ]; saved 240
int16_t seed;
int16_t std;
} PLCstr;
/* Have instance of struct together with other iSAC structs */
typedef struct {
int16_t prevFrameSizeMs; /* Previous frame size (in ms) */
uint16_t prevRtpNumber; /* Previous RTP timestamp from received packet */
/* (in samples relative beginning) */
uint32_t prevSendTime; /* Send time for previous packet, from RTP header */
uint32_t prevArrivalTime; /* Arrival time for previous packet (in ms using timeGetTime()) */
uint16_t prevRtpRate; /* rate of previous packet, derived from RTP timestamps (in bits/s) */
uint32_t lastUpdate; /* Time since the last update of the Bottle Neck estimate (in samples) */
uint32_t lastReduction; /* Time sinse the last reduction (in samples) */
int32_t countUpdates; /* How many times the estimate was update in the beginning */
/* The estimated bottle neck rate from there to here (in bits/s) */
uint32_t recBw;
uint32_t recBwInv;
uint32_t recBwAvg;
uint32_t recBwAvgQ;
uint32_t minBwInv;
uint32_t maxBwInv;
/* The estimated mean absolute jitter value, as seen on this side (in ms) */
int32_t recJitter;
int32_t recJitterShortTerm;
int32_t recJitterShortTermAbs;
int32_t recMaxDelay;
int32_t recMaxDelayAvgQ;
int16_t recHeaderRate; /* (assumed) bitrate for headers (bps) */
uint32_t sendBwAvg; /* The estimated bottle neck rate from here to there (in bits/s) */
int32_t sendMaxDelayAvg; /* The estimated mean absolute jitter value, as seen on the other siee (in ms) */
int16_t countRecPkts; /* number of packets received since last update */
int16_t 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 */
int16_t countHighSpeedRec;
/* flag indicating bwe should not adjust down immediately for very late pckts */
int16_t inWaitPeriod;
/* variable holding the time of the start of a window of time when
bwe should not adjust down immediately for very late pckts */
uint32_t 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 */
int16_t countHighSpeedSent;
/* flag indicated the desired number of packets over threshold rate have been sent and
bwe will assume the connection is over broadband network */
int16_t highSpeedSend;
} BwEstimatorstr;
typedef struct {
/* boolean, flags if previous packet exceeded B.N. */
int16_t PrevExceed;
/* ms */
int16_t ExceedAgo;
/* packets left to send in current burst */
int16_t BurstCounter;
/* packets */
int16_t InitCounter;
/* ms remaining in buffer when next packet will be sent */
int16_t 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 */
int16_t framelength;
/* Pitch Gain */
int16_t pitchGain_index[2];
/* Pitch Lag */
int32_t meanGain[2];
int16_t pitchIndex[PITCH_SUBFRAMES*2];
/* LPC */
int32_t LPCcoeffs_g[12*2]; /* KLT_ORDER_GAIN = 12 */
int16_t LPCindex_s[108*2]; /* KLT_ORDER_SHAPE = 108 */
int16_t LPCindex_g[12*2]; /* KLT_ORDER_GAIN = 12 */
/* Encode Spec */
int16_t fre[FRAMESAMPLES];
int16_t fim[FRAMESAMPLES];
int16_t 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;
int16_t buffer_index;
int16_t current_framesamples;
int16_t data_buffer_fix[FRAMESAMPLES]; // the size was MAX_FRAMESAMPLES
int16_t frame_nb;
int16_t BottleNeck;
int16_t MaxDelay;
int16_t new_framelength;
int16_t s2nr;
uint16_t MaxBits;
int16_t bitstr_seed;
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
PostFiltBankstr interpolatorstr_obj;
#endif
ISAC_SaveEncData_t *SaveEnc_ptr;
int16_t payloadLimitBytes30; /* Maximum allowed number of bits for a 30 msec packet */
int16_t payloadLimitBytes60; /* Maximum allowed number of bits for a 30 msec packet */
int16_t maxPayloadBytes; /* Maximum allowed number of bits for both 30 and 60 msec packet */
int16_t maxRateInBytes; /* Maximum allowed rate in bytes per 30 msec packet */
int16_t 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;
int16_t CodingMode; /* 0 = adaptive; 1 = instantaneous */
int16_t errorcode;
int16_t initflag; /* 0 = nothing initiated; 1 = encoder or decoder */
/* not initiated; 2 = all initiated */
} ISACFIX_SubStruct;
typedef struct {
int32_t lpcGains[12]; /* 6 lower-band & 6 upper-band we may need to double it for 60*/
/* */
uint32_t W_upper; /* Upper boundary of interval W */
uint32_t streamval;
uint16_t stream_index; /* Index to the current position in bytestream */
int16_t full; /* 0 - first byte in memory filled, second empty*/
/* 1 - both bytes are empty (we just filled the previous memory */
uint16_t beforeLastWord;
uint16_t lastWord;
} transcode_obj;
//Bitstr_enc myBitStr;
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_ */

View File

@@ -0,0 +1,210 @@
/*
* 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 "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/fft.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
/* Tables are defined in transform_tables.c file or ARM assembly files. */
/* Cosine table 1 in Q14 */
extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
/* Sine table 1 in Q14 */
extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
/* Sine table 2 in Q14 */
extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
void WebRtcIsacfix_Time2SpecC(int16_t *inre1Q9,
int16_t *inre2Q9,
int16_t *outreQ7,
int16_t *outimQ7)
{
int k;
int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
int16_t tmp1rQ14, tmp1iQ14;
int32_t xrQ16, xiQ16, yrQ16, yiQ16;
int32_t v1Q16, v2Q16;
int16_t 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 = WebRtcIsacfix_kCosTab1[k];
tmp1iQ14 = WebRtcIsacfix_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] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmpreQ16[k], sh); //Q(16+sh)
inre2Q9[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmpimQ16[k], sh); //Q(16+sh)
}
} else {
int32_t round = WEBRTC_SPL_LSHIFT_W32((int32_t)1, -sh-1);
for (k=0; k<FRAMESAMPLES/2; k++) {
inre1Q9[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpreQ16[k]+round, -sh); //Q(16+sh)
inre2Q9[k] = (int16_t) 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((int32_t)inre1Q9[k], sh); //Q(16+sh) -> Q16
tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inre2Q9[k], sh); //Q(16+sh) -> Q16
}
} else {
for (k=0; k<FRAMESAMPLES/2; k++) {
tmpreQ16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inre1Q9[k], -sh); //Q(16+sh) -> Q16
tmpimQ16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)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 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
tmp1iQ14 = WebRtcIsacfix_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] = (int16_t) WEBRTC_SPL_RSHIFT_W32(v1Q16, 9);
outimQ7[k] = (int16_t) 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] = (int16_t)WEBRTC_SPL_RSHIFT_W32(v1Q16, 9); //CalcLrIntQ(v1Q16, 9);
outimQ7[FRAMESAMPLES/2 - 1 - k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(v2Q16, 9); //CalcLrIntQ(v2Q16, 9);
}
}
void WebRtcIsacfix_Spec2TimeC(int16_t *inreQ7, int16_t *inimQ7, int32_t *outre1Q16, int32_t *outre2Q16)
{
int k;
int16_t tmp1rQ14, tmp1iQ14;
int32_t xrQ16, xiQ16, yrQ16, yiQ16;
int32_t tmpInRe, tmpInIm, tmpInRe2, tmpInIm2;
int16_t factQ11;
int16_t sh;
for (k = 0; k < FRAMESAMPLES/4; k++) {
/* Move zero in time to beginning of frames */
tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
tmp1iQ14 = WebRtcIsacfix_kSinTab2[k];
tmpInRe = WEBRTC_SPL_LSHIFT_W32((int32_t) inreQ7[k], 9); // Q7 -> Q16
tmpInIm = WEBRTC_SPL_LSHIFT_W32((int32_t) inimQ7[k], 9); // Q7 -> Q16
tmpInRe2 = WEBRTC_SPL_LSHIFT_W32((int32_t) inreQ7[FRAMESAMPLES/2 - 1 - k], 9); // Q7 -> Q16
tmpInIm2 = WEBRTC_SPL_LSHIFT_W32((int32_t) 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] = (int16_t) WEBRTC_SPL_LSHIFT_W32(outre1Q16[k], sh); //Q(16+sh)
inimQ7[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(outre2Q16[k], sh); //Q(16+sh)
}
} else {
int32_t round = WEBRTC_SPL_LSHIFT_W32((int32_t)1, -sh-1);
for (k=0; k<240; k++) {
inreQ7[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(outre1Q16[k]+round, -sh); //Q(16+sh)
inimQ7[k] = (int16_t) 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((int32_t)inreQ7[k], sh); //Q(16+sh) -> Q16
outre2Q16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inimQ7[k], sh); //Q(16+sh) -> Q16
}
} else {
for (k=0; k<240; k++) {
outre1Q16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inreQ7[k], -sh); //Q(16+sh) -> Q16
outre2Q16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)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 = WebRtcIsacfix_kCosTab1[k];
tmp1iQ14 = WebRtcIsacfix_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;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,643 @@
@
@ 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.
@
@ Reference code in transform.c. Bit not exact due to how rounding is
@ done in C code and ARM instructions, but quality by assembly code is
@ not worse.
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/system_wrappers/interface/asm_defines.h"
GLOBAL_FUNCTION WebRtcIsacfix_Spec2TimeNeon
GLOBAL_FUNCTION WebRtcIsacfix_Time2SpecNeon
GLOBAL_LABEL WebRtcIsacfix_kSinTab1
GLOBAL_LABEL WebRtcIsacfix_kCosTab1
GLOBAL_LABEL WebRtcIsacfix_kSinTab2
@ void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
@ int16_t* inre2Q9,
@ int16_t* outreQ7,
@ int16_t* outimQ7);
DEFINE_FUNCTION WebRtcIsacfix_Time2SpecNeon
.align 2
push {r4-r11,lr}
sub sp, sp, #(16 + FRAMESAMPLES * 4)
str r0, [sp] @ inre1Q9
str r1, [sp, #4] @ inre2Q9
str r2, [sp, #8] @ outreQ7
str r3, [sp, #12] @ outimQ7
mov r8, #(FRAMESAMPLES - 16)
add r12, r0, r8 @ &inreQ7[FRAMESAMPLES / 2 - 4]
add r11, r1, r8 @ &inimQ7[FRAMESAMPLES / 2 - 4]
add r4, sp, #16 @ tmpreQ16;
add r5, sp, #(16 + FRAMESAMPLES * 2) @ tmpimQ16;
adr r9, WebRtcIsacfix_kCosTab1
#if defined(__APPLE__)
mov r6, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
#else
mov r6, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
#endif
add r10, r9, r6 @ WebRtcIsacfix_kSinTab1
vmov.u32 q14, #0 @ Initialize the maximum values for tmpInIm.
vmov.u32 q15, #0 @ Initialize the maximum values for tmpInRe.
movw r6, #16921 @ 0.5 / sqrt(240) in Q19
lsl r6, #5 @ Together with vqdmulh, net effect is ">> 26".
mov r8, #(FRAMESAMPLES / 2) @ loop counter
vdup.s32 q11, r6
Time2Spec_TransformAndFindMax:
@ Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code.
subs r8, #8
vld1.16 {q0}, [r9, :64]! @ WebRtcIsacfix_kCosTab1[]
vld1.16 {q2}, [r0]! @ inre1Q9[]
vmull.s16 q8, d0, d4 @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k]
vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab1[]
vmull.s16 q9, d1, d5 @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k]
vld1.16 {q3}, [r1]! @ inre2Q9[]
vmlal.s16 q8, d2, d6 @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k]
vmlal.s16 q9, d3, d7 @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k]
vmull.s16 q12, d0, d6 @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k]
vmull.s16 q13, d1, d7 @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k]
vmlsl.s16 q12, d2, d4 @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k]
vmlsl.s16 q13, d3, d5 @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k]
vqdmulh.s32 q0, q8, q11 @ xrQ16 * factQ19
vqdmulh.s32 q1, q9, q11 @ xrQ16 * factQ19
vqdmulh.s32 q2, q12, q11 @ xrQ16 * factQ19
vqdmulh.s32 q3, q13, q11 @ xrQ16 * factQ19
@ Find the absolute maximum in the vectors and store them.
vabs.s32 q8, q0
vabs.s32 q9, q1
vabs.s32 q12, q2
vst1.32 {q0, q1}, [r4]! @ tmpreQ16[k]
vabs.s32 q13, q3
vmax.u32 q14, q8 @ Use u32 so we don't lose the value 0x80000000.
vmax.u32 q15, q12
vst1.32 {q2, q3}, [r5]! @ tmpimQ16[k]
vmax.u32 q15, q13
vmax.u32 q14, q9 @ Maximum for outre1Q16[].
bgt Time2Spec_TransformAndFindMax
@ Find the maximum value in the Neon registers
vmax.u32 d28, d29
vmax.u32 d30, d31
vpmax.u32 d28, d28, d28 @ Both 32 bits words hold the same value tmpInIm.
vpmax.u32 d30, d30, d30 @ Both 32 bits words hold the same value tmpInRe.
vmax.s32 d30, d28, d30 @ if (yrQ16 > xrQ16) {xrQ16 = yrQ16};
ldr r4, [sp] @ inre1Q9
vcls.s32 d31, d30 @ sh = WebRtcSpl_NormW32(tmpInRe);
ldr r5, [sp, #4] @ inre2Q9
vmov.i32 d30, #24
add r6, sp, #16 @ tmpreQ16;
vsub.s32 d31, d31, d30 @ sh = sh - 24;
add r7, sp, #(16 + FRAMESAMPLES * 2) @ tmpimQ16;
vdup.s32 q8, d31[0] @ sh
mov r8, #(FRAMESAMPLES / 2) @ loop counter
Time2Spec_PreFftShift:
subs r8, #16
vld1.32 {q0, q1}, [r6]! @ tmpreQ16[]
vrshl.s32 q0, q0, q8
vld1.32 {q2, q3}, [r6]! @ tmpreQ16[]
vrshl.s32 q1, q1, q8
vld1.32 {q10, q11}, [r7]! @ tmpimQ16[]
vrshl.s32 q2, q2, q8
vld1.32 {q12, q13}, [r7]! @ tmpimQ16[]
vrshl.s32 q3, q3, q8
vrshl.s32 q10, q10, q8
vrshl.s32 q11, q11, q8
vrshl.s32 q12, q12, q8
vrshl.s32 q13, q13, q8
vmovn.s32 d0, q0
vmovn.s32 d1, q1
vmovn.s32 d2, q2
vmovn.s32 d3, q3
vmovn.s32 d4, q10
vmovn.s32 d5, q11
vmovn.s32 d6, q12
vmovn.s32 d7, q13
vst1.16 {q0, q1}, [r4]! @ inre1Q9[]
vst1.16 {q2, q3}, [r5]! @ inre2Q9[]
bgt Time2Spec_PreFftShift
vmov.s32 r10, d16[0] @ Store value of sh.
ldr r0, [sp] @ inre1Q9
ldr r1, [sp, #4] @ inre2Q9
mov r2, #-1
CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest
vdup.s32 q8, r10 @ sh
mov r8, #(FRAMESAMPLES - 8)
ldr r2, [sp, #8] @ outreQ7
ldr r3, [sp, #12] @ outimQ7
add r11, r2, r8 @ &outRe1Q16[FRAMESAMPLES / 2 - 4]
add r12, r3, r8 @ &outim2Q16[FRAMESAMPLES / 2 - 4]
ldr r6, [sp] @ inre1Q9
ldr r7, [sp, #4] @ inre2Q9
add r4, r6, r8 @ &inre1Q9[FRAMESAMPLES / 2 - 4]
add r5, r7, r8 @ &inre2Q9[FRAMESAMPLES / 2 - 4]
adr r10, WebRtcIsacfix_kSinTab2
add r9, r10, #(120*2 - 8) @ &WebRtcIsacfix_kSinTab2[119 - 4]
vneg.s32 q15, q8 @ -sh
vmov.i32 q0, #23
vsub.s32 q15, q15, q0 @ -sh - 23
mov r8, #(FRAMESAMPLES / 4) @ loop counter
@ Pre-load variables.
vld1.16 {d2}, [r4] @ inre1Q9[FRAMESAMPLES / 2 - 4 - i]
vld1.16 {d3}, [r5] @ inre2Q9[FRAMESAMPLES / 2 - 4 - i]
vld1.16 {d0}, [r6]! @ inre1Q9
vld1.16 {d1}, [r7]! @ inre2Q9
Time2Spec_PostFftTransform:
@ By vshl, we effectively did "<< (-sh - 23)", instead of "<< (-sh)",
@ ">> 14" and then ">> 9" as in the C code.
vld1.16 {d6}, [r9, :64] @ kCosTab2[]
vneg.s16 d6, d6
vld1.16 {d7}, [r10, :64]! @ WebRtcIsacfix_kSinTab2[]
vrev64.16 q1, q1 @ Reverse samples in 2nd half of xrQ16[].
vqadd.s16 d4, d0, d2 @ xrQ16
vqsub.s16 d5, d1, d3 @ xiQ16
vrev64.16 d6, d6
sub r9, #8 @ Update pointers for kCosTab2[].
sub r4, #8 @ Update pointers for inre1Q9[].
sub r5, #8 @ Update pointers for inr22Q9[].
subs r8, #4 @ Update loop counter.
vqadd.s16 d1, d1, d3 @ yrQ16
vqsub.s16 d0, d2, d0 @ yiQ16
vmull.s16 q12, d6, d4 @ kCosTab2[k] * xrQ16
vmlsl.s16 q12, d7, d5 @ WebRtcIsacfix_kSinTab2[k] * xiQ16
vmull.s16 q13, d7, d4 @ WebRtcIsacfix_kSinTab2[k] * xrQ16
vmlal.s16 q13, d6, d5 @ kCosTab2[k] * xiQ16
vmull.s16 q9, d7, d1 @ WebRtcIsacfix_kSinTab2[k] * yrQ16
vmlal.s16 q9, d6, d0 @ kCosTab2[k] * yiQ16
vmull.s16 q10, d7, d0 @ WebRtcIsacfix_kSinTab2[k] * yiQ16
vmlsl.s16 q10, d6, d1 @ kCosTab2[k] * yrQ16
vshl.s32 q12, q12, q15
vshl.s32 q13, q13, q15
vshl.s32 q9, q9, q15
vshl.s32 q10, q10, q15
vneg.s32 q8, q9
vld1.16 {d0}, [r6]! @ inre1Q9
vmovn.s32 d24, q12
vld1.16 {d1}, [r7]! @ inre2Q9
vmovn.s32 d25, q13
vld1.16 {d2}, [r4] @ inre1Q9[FRAMESAMPLES / 2 - 4 - i]
vmovn.s32 d5, q10
vld1.16 {d3}, [r5] @ inre2Q9[FRAMESAMPLES / 2 - 4 - i]
vmovn.s32 d4, q8
vst1.16 {d24}, [r2]! @ outreQ7[k]
vrev64.16 q2, q2 @ Reverse the order of the samples.
vst1.16 {d25}, [r3]! @ outimQ7[k]
vst1.16 {d4}, [r11] @ outreQ7[FRAMESAMPLES / 2 - 1 - k]
vst1.16 {d5}, [r12] @ outimQ7[FRAMESAMPLES / 2 - 1 - k]
sub r11, #8 @ Update pointers for outreQ7[].
sub r12, #8 @ Update pointers for outimQ7[].
bgt Time2Spec_PostFftTransform
add sp, sp, #(16 + FRAMESAMPLES * 4)
pop {r4-r11,pc}
.align 8
@ Cosine table 1 in Q14
WebRtcIsacfix_kCosTab1:
_WebRtcIsacfix_kCosTab1: @ Label for iOS
.short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315
.short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069
.short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647
.short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053
.short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295
.short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380
.short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318
.short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121
.short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803
.short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377
.short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859
.short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266
.short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616
.short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926
.short 1713, 1499, 1285, 1072, 857, 643, 429, 214
.short 0, -214, -429, -643, -857, -1072, -1285, -1499
.short -1713, -1926, -2139, -2351, -2563, -2775, -2986, -3196
.short -3406, -3616, -3825, -4033, -4240, -4447, -4653, -4859
.short -5063, -5266, -5469, -5671, -5872, -6071, -6270, -6467
.short -6664, -6859, -7053, -7246, -7438, -7629, -7818, -8006
.short -8192, -8377, -8561, -8743, -8923, -9102, -9280, -9456
.short -9630, -9803, -9974, -10143, -10311, -10477, -10641, -10803
.short -10963, -11121, -11278, -11433, -11585, -11736, -11885, -12031
.short -12176, -12318, -12458, -12597, -12733, -12867, -12998, -13128
.short -13255, -13380, -13502, -13623, -13741, -13856, -13970, -14081
.short -14189, -14295, -14399, -14500, -14598, -14694, -14788, -14879
.short -14968, -15053, -15137, -15218, -15296, -15371, -15444, -15515
.short -15582, -15647, -15709, -15769, -15826, -15880, -15931, -15980
.short -16026, -16069, -16110, -16147, -16182, -16214, -16244, -16270
.short -16294, -16315, -16333, -16349, -16362, -16371, -16378, -16383
.align 8
@ Sine table 2 in Q14
WebRtcIsacfix_kSinTab2:
_WebRtcIsacfix_kSinTab2: @ Label for iOS
.short 16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305
.short 16283, -16257, 16229, -16199, 16165, -16129, 16090, -16048
.short 16003, -15956, 15906, -15853, 15798, -15739, 15679, -15615
.short 15549, -15480, 15408, -15334, 15257, -15178, 15095, -15011
.short 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242
.short 14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318
.short 13192, -13063, 12933, -12800, 12665, -12528, 12389, -12247
.short 12104, -11958, 11810, -11661, 11509, -11356, 11200, -11042
.short 10883, -10722, 10559, -10394, 10227, -10059, 9889, -9717
.short 9543, -9368, 9191, -9013, 8833, -8652, 8469, -8285
.short 8099, -7912, 7723, -7534, 7342, -7150, 6957, -6762
.short 6566, -6369, 6171, -5971, 5771, -5570, 5368, -5165
.short 4961, -4756, 4550, -4344, 4137, -3929, 3720, -3511
.short 3301, -3091, 2880, -2669, 2457, -2245, 2032, -1819
.short 1606, -1392, 1179, -965, 750, -536, 322, -107
@ Table kCosTab2 was removed since its data is redundant with kSinTab2.
.align 8
@ Sine table 1 in Q14
WebRtcIsacfix_kSinTab1:
_WebRtcIsacfix_kSinTab1: @ Label for iOS
.short 0, 214, 429, 643, 857, 1072, 1285, 1499
.short 1713, 1926, 2139, 2351, 2563, 2775, 2986, 3196
.short 3406, 3616, 3825, 4033, 4240, 4447, 4653, 4859
.short 5063, 5266, 5469, 5671, 5872, 6071, 6270, 6467
.short 6664, 6859, 7053, 7246, 7438, 7629, 7818, 8006
.short 8192, 8377, 8561, 8743, 8923, 9102, 9280, 9456
.short 9630, 9803, 9974, 10143, 10311, 10477, 10641, 10803
.short 10963, 11121, 11278, 11433, 11585, 11736, 11885, 12031
.short 12176, 12318, 12458, 12597, 12733, 12867, 12998, 13128
.short 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081
.short 14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879
.short 14968, 15053, 15137, 15218, 15296, 15371, 15444, 15515
.short 15582, 15647, 15709, 15769, 15826, 15880, 15931, 15980
.short 16026, 16069, 16110, 16147, 16182, 16214, 16244, 16270
.short 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383
.short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315
.short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069
.short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647
.short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053
.short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295
.short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380
.short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318
.short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121
.short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803
.short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377
.short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859
.short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266
.short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616
.short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926
.short 1713, 1499, 1285, 1072, 857, 643, 429, 214
@ void WebRtcIsacfix_Spec2TimeNeon(int16_t *inreQ7,
@ int16_t *inimQ7,
@ int32_t *outre1Q16,
@ int32_t *outre2Q16);
DEFINE_FUNCTION WebRtcIsacfix_Spec2TimeNeon
.align 2
push {r4-r11,lr}
sub sp, sp, #16
str r0, [sp] @ inreQ7
str r1, [sp, #4] @ inimQ7
str r2, [sp, #8] @ outre1Q16
str r3, [sp, #12] @ outre2Q16
mov r8, #(FRAMESAMPLES - 16)
add r12, r0, r8 @ &inreQ7[FRAMESAMPLES / 2 - 8]
add r11, r1, r8 @ &inimQ7[FRAMESAMPLES / 2 - 8]
add r4, r2, r8, lsl #1 @ &outRe1Q16[FRAMESAMPLES / 2 - 8]
add r6, r3, r8, lsl #1 @ &outRe2Q16[FRAMESAMPLES / 2 - 8]
mov r8, #(FRAMESAMPLES / 2) @ loop counter
adr r10, WebRtcIsacfix_kSinTab2
add r9, r10, #(120*2 - 16) @ &WebRtcIsacfix_kSinTab2[119 - 8]
vpush {q4-q7}
mov r5, #-32
mov r7, #-16
vmov.u32 q6, #0 @ Initialize the maximum values for tmpInIm.
vmov.u32 q7, #0 @ Initialize the maximum values for tmpInRe.
TransformAndFindMax:
@ Use ">> 5", instead of "<< 9" and then ">> 14" as in the C code.
@ Bit-exact.
subs r8, #16
vld1.16 {q0}, [r9, :64] @ kCosTab2[]
sub r9, #16
vld1.16 {q2}, [r0]! @ inreQ7[]
vneg.s16 q0, q0
vld1.16 {q3}, [r1]! @ inimQ7[]
vrev64.16 d0, d0
vrev64.16 d1, d1
vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab2[]
vswp d0, d1
vmull.s16 q8, d2, d6 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
vmull.s16 q9, d3, d7 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
vmlal.s16 q8, d0, d4 @ kCosTab2[k] * inreQ7[k]
vmlal.s16 q9, d1, d5 @ kCosTab2[k] * inreQ7[k]
vmull.s16 q12, d0, d6 @ kCosTab2[k] * inimQ7[k]
vmull.s16 q13, d1, d7 @ kCosTab2[k] * inimQ7[k]
vmlsl.s16 q12, d2, d4 @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k]
vmlsl.s16 q13, d3, d5 @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k]
vld1.16 {q2}, [r11], r7 @ inimQ7[FRAMESAMPLES / 2 - 8 + i]
vld1.16 {q3}, [r12], r7 @ inreQ7[FRAMESAMPLES / 2 - 8 + i]
vrev64.16 q2, q2 @ Reverse the order of the samples
vrev64.16 q3, q3 @ Reverse the order of the samples
vmull.s16 q14, d2, d5 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
vmull.s16 q15, d3, d4 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
vmlsl.s16 q14, d0, d7 @ q14 -= kCosTab2[k] * inreQ7[k]
vmlsl.s16 q15, d1, d6 @ q15 -= kCosTab2[k] * inreQ7[k]
vmull.s16 q10, d0, d5 @ kCosTab2[k] * inimQ7[]
vmull.s16 q11, d1, d4 @ kCosTab2[k] * inimQ7[]
vmlal.s16 q10, d2, d7 @ q10 += WebRtcIsacfix_kSinTab2[k] * inreQ7[]
vmlal.s16 q11, d3, d6 @ q11 += WebRtcIsacfix_kSinTab2[k] * inreQ7[]
vshr.s32 q8, q8, #5 @ xrQ16
vshr.s32 q9, q9, #5 @ xrQ16
vshr.s32 q12, q12, #5 @ xiQ16
vshr.s32 q13, q13, #5 @ xiQ16
vshr.s32 q14, q14, #5 @ yiQ16
vshr.s32 q15, q15, #5 @ yiQ16
vneg.s32 q10, q10
vneg.s32 q11, q11
@ xrQ16 - yiQ16
vsub.s32 q0, q8, q14
vsub.s32 q1, q9, q15
vshr.s32 q10, q10, #5 @ yrQ16
vshr.s32 q11, q11, #5 @ yrQ16
@ xrQ16 + yiQ16
vadd.s32 q3, q8, q14
vadd.s32 q2, q9, q15
@ yrQ16 + xiQ16
vadd.s32 q4, q10, q12
vadd.s32 q5, q11, q13
@ yrQ16 - xiQ16
vsub.s32 q8, q11, q13
vsub.s32 q9, q10, q12
@ Reverse the order of the samples
vrev64.32 q2, q2
vrev64.32 q3, q3
vrev64.32 q8, q8
vrev64.32 q9, q9
vswp d4, d5
vswp d6, d7
vst1.32 {q0, q1}, [r2]! @ outre1Q16[k]
vswp d16, d17
vswp d18, d19
vst1.32 {q2, q3}, [r4], r5 @ outre1Q16[FRAMESAMPLES / 2 - 1 - k]
@ Find the absolute maximum in the vectors and store them in q6 and q7.
vabs.s32 q10, q0
vabs.s32 q14, q4
vabs.s32 q11, q1
vabs.s32 q15, q5
vabs.s32 q12, q2
vmax.u32 q6, q10 @ Use u32 so we don't lose the value 0x80000000.
vmax.u32 q7, q14 @ Maximum for outre2Q16[].
vabs.s32 q0, q8
vmax.u32 q6, q11 @ Maximum for outre1Q16[].
vmax.u32 q7, q15
vabs.s32 q13, q3
vmax.u32 q6, q12
vmax.u32 q7, q0
vabs.s32 q1, q9
vst1.32 {q4, q5}, [r3]! @ outre2Q16[k]
vst1.32 {q8, q9}, [r6], r5 @ outre2Q16[FRAMESAMPLES / 2 - 1 - k]
vmax.u32 q6, q13
vmax.u32 q7, q1
bgt TransformAndFindMax
adr r10, WebRtcIsacfix_kSinTab1
#if defined(__APPLE__)
mov r2, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
#else
mov r2, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
#endif
sub r11, r10, r2 @ WebRtcIsacfix_kCosTab1
@ Find the maximum value in the Neon registers
vmax.u32 d12, d13
vmax.u32 d14, d15
vpmax.u32 d12, d12, d12 @ Both 32 bits words hold the same value tmpInIm.
vpmax.u32 d14, d14, d14 @ Both 32 bits words hold the same value tmpInRe.
vmax.s32 d0, d12, d14 @ if (tmpInIm>tmpInRe) tmpInRe = tmpInIm;
vpop {q4-q7}
ldr r4, [sp] @ inreQ7
vcls.s32 d1, d0 @ sh = WebRtcSpl_NormW32(tmpInRe);
ldr r5, [sp, #4] @ inimQ7
vmov.i32 d0, #24 @ sh = sh-24;
ldr r6, [sp, #8] @ outre1Q16
vsub.s32 d1, d1, d0
ldr r7, [sp, #12] @ outre2Q16
vdup.s32 q8, d1[0] @ sh
mov r8, #(FRAMESAMPLES / 2)
PreFftShift:
subs r8, #16
vld1.32 {q0, q1}, [r6]! @ outre1Q16[]
vld1.32 {q2, q3}, [r6]! @ outre1Q16[]
vrshl.s32 q0, q0, q8
vrshl.s32 q1, q1, q8
vrshl.s32 q2, q2, q8
vrshl.s32 q3, q3, q8
vld1.32 {q10, q11}, [r7]! @ outre2Q16[]
vld1.32 {q12, q13}, [r7]! @ outre2Q16[]
vrshl.s32 q10, q10, q8
vrshl.s32 q11, q11, q8
vrshl.s32 q12, q12, q8
vrshl.s32 q13, q13, q8
vmovn.s32 d0, q0
vmovn.s32 d1, q1
vmovn.s32 d2, q2
vmovn.s32 d3, q3
vmovn.s32 d4, q10
vmovn.s32 d5, q11
vmovn.s32 d6, q12
vmovn.s32 d7, q13
vst1.16 {q0, q1}, [r4]! @ inreQ7[]
vst1.16 {q2, q3}, [r5]! @ inimQ7[]
bgt PreFftShift
vmov.s32 r8, d16[0] @ Store value of sh.
ldr r0, [sp] @ inreQ7
ldr r1, [sp, #4] @ inimQ7
mov r2, #1
CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest
vdup.s32 q8, r8 @ sh
mov r9, r11 @ WebRtcIsacfix_kCosTab1
ldr r4, [sp] @ inreQ7
ldr r5, [sp, #4] @ inimQ7
ldr r6, [sp, #8] @ outre1Q16
ldr r7, [sp, #12] @ outre2Q16
mov r8, #(FRAMESAMPLES / 2)
vneg.s32 q15, q8 @ -sh
movw r0, #273
lsl r0, #15 @ Together with vqdmulh, net effect is ">> 16".
vdup.s32 q14, r0
PostFftShiftDivide:
subs r8, #16
vld1.16 {q0, q1}, [r4]! @ inreQ7
vmovl.s16 q10, d0
vmovl.s16 q11, d1
vld1.16 {q2, q3}, [r5]! @ inimQ7
vmovl.s16 q8, d2
vmovl.s16 q9, d3
vshl.s32 q10, q10, q15
vshl.s32 q11, q11, q15
vshl.s32 q8, q8, q15
vshl.s32 q9, q9, q15
vqdmulh.s32 q10, q10, q14
vqdmulh.s32 q11, q11, q14
vqdmulh.s32 q8, q8, q14
vqdmulh.s32 q9, q9, q14
vmovl.s16 q0, d4
vmovl.s16 q1, d5
vmovl.s16 q2, d6
vmovl.s16 q3, d7
vshl.s32 q0, q0, q15
vshl.s32 q1, q1, q15
vshl.s32 q2, q2, q15
vshl.s32 q3, q3, q15
@ WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k])
vqdmulh.s32 q0, q0, q14
vqdmulh.s32 q1, q1, q14
vst1.32 {q10, q11}, [r6]! @ outre1Q16[]
vqdmulh.s32 q2, q2, q14
vqdmulh.s32 q3, q3, q14
vst1.32 {q8, q9}, [r6]! @ outre1Q16[]
vst1.32 {q0, q1}, [r7]! @ outre2Q16[]
vst1.32 {q2, q3}, [r7]! @ outre2Q16[]
bgt PostFftShiftDivide
mov r8, #(FRAMESAMPLES / 2)
ldr r2, [sp, #8] @ outre1Q16
ldr r3, [sp, #12] @ outre2Q16
movw r0, #31727
lsl r0, #16 @ With vqdmulh and vrshrn, net effect is ">> 25".
DemodulateAndSeparate:
subs r8, #8
vld1.16 {q0}, [r9, :64]! @ WebRtcIsacfix_kCosTab1[]
vmovl.s16 q10, d0 @ WebRtcIsacfix_kCosTab1[]
vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab1[]
vmovl.s16 q11, d1 @ WebRtcIsacfix_kCosTab1[]
vld1.32 {q2, q3}, [r2] @ outre1Q16
vmovl.s16 q12, d2 @ WebRtcIsacfix_kSinTab1[]
vld1.32 {q14, q15}, [r3] @ outre2Q16
vmovl.s16 q13, d3 @ WebRtcIsacfix_kSinTab1[]
vmull.s32 q0, d20, d4 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
vmull.s32 q1, d21, d5 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
vmull.s32 q8, d22, d6 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
vmull.s32 q9, d23, d7 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
vmlsl.s32 q0, d24, d28 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
vmlsl.s32 q1, d25, d29 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
vmlsl.s32 q8, d26, d30 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
vmlsl.s32 q9, d27, d31 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
vrshrn.s64 d0, q0, #10 @ xrQ16
vrshrn.s64 d1, q1, #10 @ xrQ16
vrshrn.s64 d2, q8, #10 @ xrQ16
vrshrn.s64 d3, q9, #10 @ xrQ16
vmull.s32 q8, d20, d28 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
vmull.s32 q9, d21, d29 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
vmull.s32 q14, d22, d30 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
vmull.s32 q15, d23, d31 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
vmlal.s32 q8, d24, d4 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
vmlal.s32 q9, d25, d5 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
vmlal.s32 q14, d26, d6 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
vmlal.s32 q15, d27, d7 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
vdup.s32 q11, r0 @ generic -> Neon doesn't cost extra cycles.
vrshrn.s64 d24, q8, #10 @ xiQ16
vrshrn.s64 d25, q9, #10 @ xiQ16
vqdmulh.s32 q0, q0, q11
vrshrn.s64 d26, q14, #10 @ xiQ16
vrshrn.s64 d27, q15, #10 @ xiQ16
@ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16)
@ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16)
vqdmulh.s32 q1, q1, q11
vqdmulh.s32 q2, q12, q11
vqdmulh.s32 q3, q13, q11
vst1.16 {q0, q1}, [r2]! @ outre1Q16[]
vst1.16 {q2, q3}, [r3]! @ outre2Q16[]
bgt DemodulateAndSeparate
add sp, sp, #16
pop {r4-r11,pc}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2014 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 contains trigonometric functions look-up tables used in
* transform functions WebRtcIsacfix_Time2Spec and WebRtcIsacfix_Spec2Time.
*/
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/typedefs.h"
#if !(defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON)
/* Cosine table 1 in Q14. */
const int16_t WebRtcIsacfix_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. */
const int16_t WebRtcIsacfix_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
};
/* Sine table 2 in Q14. */
const int16_t WebRtcIsacfix_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
};
#endif
#if defined(MIPS32_LE)
/* Cosine table 2 in Q14. Used only on MIPS platforms. */
const int16_t WebRtcIsacfix_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
};
#endif

View File

@@ -0,0 +1,196 @@
/*
* 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 "gtest/gtest.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
static const int kSamples = FRAMESAMPLES/2;
static int32_t spec2time_out_expected_1[kSamples] = {-3366470, -2285227,
-3415765, -2310215, -3118030, -2222470, -3030254, -2192091, -3423170,
-2216041, -3305541, -2171936, -3195767, -2095779, -3153304, -2157560,
-3071167, -2032108, -3101190, -1972016, -3103824, -2089118, -3139811,
-1898337, -3102801, -2055082, -3029665, -1854140, -2962586, -1966454,
-3071167, -1894588, -2851743, -1917315, -2848087, -1594932, -2799242,
-1462184, -2845887, -1437599, -2691776, -1329637, -2770659, -1268491,
-2625161, -1578991, -2460299, -1186385, -2365613, -1039354, -2322608,
-958518, -2271749, -789860, -2254538, -850308, -2384436, -850959, -2133734,
-587678, -2093316, -495115, -1973364, -475177, -1801282, -173507,
-1848516, -158015, -1792018, -62648, -1643313, 214746, -1500758, 267077,
-1450193, 560521, -1521579, 675283, -1345408, 857559, -1300822, 1116332,
-1294533, 1241117, -1070027, 1263503, -983816, 1529821, -1019586,
1910421, -955420, 2073688, -836459, 2401105, -653905, 2690474, -731425,
2930131, -935234, 3299500, -875978, 3523432, -878906, 3924822, -1081630,
4561267, -1203023, 5105274, -1510983, 6052762, -2294646, 7021597,
-3108053, 8826736, -4935222, 11678789, -8442713, 18725700, -21526692,
25420577, 19589811, -28108666, 12634054, -14483066, 6263217, -9979706,
3665661, -7909736, 2531530, -6434896, 1700772, -5525393, 1479473,
-4894262, 1231760, -4353044, 1032940, -3786590, 941152, -3331614,
665090, -2851619, 830696, -2762201, 958007, -2483118, 788233, -2184965,
804825, -1967306, 1007255, -1862474, 920889, -1457506, 755406, -1405841,
890230, -1302124, 1161599, -701867, 1154163, -1083366, 1204743, -513581,
1547264, -650636, 1493384, -285543, 1771863, -277906, 1841343, -9078,
1751863, 230222, 1819578, 207170, 1978972, 398137, 2106468, 552155,
1997624, 685213, 2129520, 601078, 2238736, 944591, 2441879, 1194178,
2355280, 986124, 2393328, 1049005, 2417944, 1208368, 2489516, 1352023,
2572118, 1445283, 2856081, 1532997, 2742279, 1615877, 2915274, 1808036,
2856871, 1806936, 3241747, 1622461, 2978558, 1841297, 3010378, 1923666,
3271367, 2126700, 3070935, 1956958, 3107588, 2128405, 3288872, 2114911,
3315952, 2406651, 3344038, 2370199, 3368980, 2144361, 3305030, 2183803,
3401450, 2523102, 3405463, 2452475, 3463355, 2421678, 3551968, 2431949,
3477251, 2148125, 3244489, 2174090};
static int32_t spec2time_out_expected_2[kSamples]= {1691694, -2499988, -2035547,
1060469, 988634, -2044502, -306271, 2041000, 201454, -2289456, 93694,
2129427, -369152, -1887834, 860796, 2089102, -929424, -1673956, 1395291,
1785651, -1619673, -1380109, 1963449, 1093311, -2111007, -840456,
2372786, 578119, -2242702, 89774, 2463304, -132717, -2121480, 643634,
2277636, -1125999, -1995858, 1543748, 2227861, -1483779, -1495491,
2102642, 1833876, -1920568, -958378, 2485101, 772261, -2454257, -24942,
2918714, 136838, -2500453, 816118, 3039735, -746560, -2365815, 1586396,
2714951, -1511696, -1942334, 2571792, 2182827, -2325335, -1311543,
3055970, 1367220, -2737182, -110626, 3889222, 631008, -3280879, 853066,
4122279, -706638, -3334449, 2148311, 3993512, -1846301, -3004894,
3426779, 3329522, -3165264, -2242423, 4756866, 2557711, -4131280,
-805259, 5702711, 1120592, -4852821, 743664, 6476444, -621186, -5465828,
2815787, 6768835, -3017442, -5338409, 5658126, 6838454, -5492288,
-4682382, 8874947, 6153814, -8832561, -2649251, 12817398, 4237692,
-13000247, 1190661, 18986363, -115738, -19693978, 9908367, 30660381,
-10632635, -37962068, 47022884, 89744622, -42087632, 40279224,
-88869341, -47542383, 38572364, 10441576, -30339718, -9926740, 19896578,
28009, -18886612, -1124047, 13232498, -4150304, -12770551, 2637074,
9051831, -6162211, -8713972, 4557937, 5489716, -6862312, -5532349,
5415449, 2791310, -6999367, -2790102, 5375806, 546222, -6486452,
-821261, 4994973, -1278840, -5645501, 1060484, 3996285, -2503954,
-4653629, 2220549, 3036977, -3282133, -3318585, 2780636, 1789880,
-4004589, -2041031, 3105373, 574819, -3992722, -971004, 3001703,
-676739, -3841508, 417284, 2897970, -1427018, -3058480, 1189948,
2210960, -2268992, -2603272, 1949785, 1576172, -2720404, -1891738,
2309456, 769178, -2975646, -707150, 2424652, -88039, -2966660, -65452,
2320780, -957557, -2798978, 744640, 1879794, -1672081, -2365319,
1253309, 1366383, -2204082, -1544367, 1801452, 613828, -2531994,
-983847, 2064842, 118326, -2613790, -203220, 2219635, -730341, -2641861,
563557, 1765434, -1329916, -2272927, 1037138, 1266725, -1939220,
-1588643, 1754528, 816552, -2376303, -1099167, 1864999, 122477,
-2422762, -400027, 1889228, -579916, -2490353, 287139, 2011318,
-1176657, -2502978, 812896, 1116502, -1940211};
static int16_t time2spec_out_expected_1[kSamples]= {20342, 23889, -10063, -9419,
3242, 7280, -2012, -5029, 332, 4478, -97, -3244, -891, 3117, 773, -2204,
-1335, 2009, 1236, -1469, -1562, 1277, 1366, -815, -1619, 599, 1449, -177,
-1507, 116, 1294, 263, -1338, -244, 1059, 553, -1045, -549, 829, 826,
-731, -755, 516, 909, -427, -853, 189, 1004, -184, -828, -108, 888, 72,
-700, -280, 717, 342, -611, -534, 601, 534, -374, -646, 399, 567, -171,
-720, 234, 645, -11, -712, -26, 593, 215, -643, -172, 536, 361, -527,
-403, 388, 550, -361, -480, 208, 623, -206, -585, 41, 578, 12, -504,
-182, 583, 218, -437, -339, 499, 263, -354, -450, 347, 456, -193, -524,
212, 475, -74, -566, 94, 511, 112, -577, -201, 408, 217, -546, -295, 338,
387, -13, 4, -46, 2, -76, 103, -83, 108, -55, 100, -150, 131, -156, 141,
-171, 179, -190, 128, -227, 172, -214, 215, -189, 265, -244, 322, -335,
337, -352, 358, -368, 362, -355, 366, -381, 403, -395, 411, -392, 446,
-458, 504, -449, 507, -464, 452, -491, 481, -534, 486, -516, 560, -535,
525, -537, 559, -554, 570, -616, 591, -585, 627, -509, 588, -584, 547,
-610, 580, -614, 635, -620, 655, -554, 546, -591, 642, -590, 660, -656,
629, -604, 620, -580, 617, -645, 648, -573, 612, -604, 584, -571, 597,
-562, 627, -550, 560, -606, 529, -584, 568, -503, 532, -463, 512, -440,
399, -457, 437, -349, 278, -317, 257, -220, 163, -8, -61, 18, -161, 367,
-1306};
static int16_t time2spec_out_expected_2[kSamples]= {14283, -11552, -15335, 6626,
7554, -2150, -6309, 1307, 4523, -4, -3908, -314, 3001, 914, -2715, -1042,
2094, 1272, -1715, -1399, 1263, 1508, -1021, -1534, 735, 1595, -439, -1447,
155, 1433, 22, -1325, -268, 1205, 424, -1030, -608, 950, 643, -733, -787,
661, 861, -502, -888, 331, 852, -144, -849, 19, 833, 99, -826, -154,
771, 368, -735, -459, 645, 513, -491, -604, 431, 630, -314, -598, 183,
622, -78, -612, -48, 641, 154, -645, -257, 610, 281, -529, -444, 450,
441, -327, -506, 274, 476, -232, -570, 117, 554, -86, -531, -21, 572,
151, -606, -221, 496, 322, -407, -388, 407, 394, -268, -428, 280, 505,
-115, -588, 19, 513, -29, -539, -109, 468, 173, -501, -242, 442, 278,
-478, -680, 656, -659, 656, -669, 602, -688, 612, -667, 612, -642, 627,
-648, 653, -676, 596, -680, 655, -649, 678, -672, 587, -608, 637, -645,
637, -620, 556, -580, 553, -635, 518, -599, 583, -501, 536, -544, 473,
-552, 583, -511, 541, -532, 563, -486, 461, -453, 486, -388, 424, -416,
432, -374, 399, -462, 364, -346, 293, -329, 331, -313, 281, -247, 309,
-337, 241, -190, 207, -194, 179, -163, 155, -156, 117, -135, 107, -126,
29, -22, 81, -8, 17, -61, -10, 8, -37, 80, -44, 72, -88, 65, -89, 130,
-114, 181, -215, 189, -245, 260, -288, 294, -339, 344, -396, 407, -429,
438, -439, 485, -556, 629, -612, 637, -645, 661, -737, 829, -830, 831,
-1041};
class TransformTest : public testing::Test {
protected:
TransformTest() {
WebRtcSpl_Init();
}
// Pass a function pointer to the Tester function.
void Time2SpecTester(Time2Spec Time2SpecFunction) {
// WebRtcIsacfix_Time2Spec functions hard coded the buffer lengths. It's a
// large buffer but we have to test it here.
int16_t data_in_1[kSamples] = {0};
int16_t data_in_2[kSamples] = {0};
int16_t data_out_1[kSamples] = {0};
int16_t data_out_2[kSamples] = {0};
for(int i = 0; i < kSamples; i++) {
data_in_1[i] = i * i + 1777;
data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
}
Time2SpecFunction(data_in_1, data_in_2, data_out_1, data_out_2);
for (int i = 0; i < kSamples; i++) {
// We don't require bit-exact for ARM assembly code.
EXPECT_LE(abs(time2spec_out_expected_1[i] - data_out_1[i]), 1);
EXPECT_LE(abs(time2spec_out_expected_2[i] - data_out_2[i]), 1);
}
}
// Pass a function pointer to the Tester function.
void Spec2TimeTester(Spec2Time Spec2TimeFunction) {
// WebRtcIsacfix_Spec2Time functions hard coded the buffer lengths. It's a
// large buffer but we have to test it here.
int16_t data_in_1[kSamples] = {0};
int16_t data_in_2[kSamples] = {0};
int32_t data_out_1[kSamples] = {0};
int32_t data_out_2[kSamples] = {0};
for(int i = 0; i < kSamples; i++) {
data_in_1[i] = i * i + 1777;
data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
}
Spec2TimeFunction(data_in_1, data_in_2, data_out_1, data_out_2);
for (int i = 0; i < kSamples; i++) {
// We don't require bit-exact for ARM assembly code.
EXPECT_LE(abs(spec2time_out_expected_1[i] - data_out_1[i]), 16);
EXPECT_LE(abs(spec2time_out_expected_2[i] - data_out_2[i]), 16);
}
}
};
TEST_F(TransformTest, Time2SpecTest) {
Time2SpecTester(WebRtcIsacfix_Time2SpecC);
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
Time2SpecTester(WebRtcIsacfix_Time2SpecNeon);
}
#elif defined(WEBRTC_ARCH_ARM_NEON)
Time2SpecTester(WebRtcIsacfix_Time2SpecNeon);
#endif
}
TEST_F(TransformTest, Spec2TimeTest) {
Spec2TimeTester(WebRtcIsacfix_Spec2TimeC);
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
Spec2TimeTester(WebRtcIsacfix_Spec2TimeNeon);
}
#elif defined(WEBRTC_ARCH_ARM_NEON)
Spec2TimeTester(WebRtcIsacfix_Spec2TimeNeon);
#endif
}

View File

@@ -0,0 +1,3 @@
bottlenecks.txt
lowrates.txt
tworates.txt

View File

@@ -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

View File

@@ -0,0 +1,6 @@
DTMF_16kHz_short.pcm
ltest_speech_noisy.pcm
misc2.pcm
sinesweep.pcm
speechmusic.pcm
tone_cisco.pcm

View File

@@ -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

View File

@@ -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!

View File

@@ -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!

View File

@@ -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!

View File

@@ -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!

View File

@@ -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

View File

@@ -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!

View File

@@ -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!

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
#include "webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
using ::std::string;
namespace webrtc {
static const int kIsacBlockDurationMs = 30;
static const int kIsacInputSamplingKhz = 16;
static const int kIsacOutputSamplingKhz = 16;
class IsacSpeedTest : public AudioCodecSpeedTest {
protected:
IsacSpeedTest();
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
virtual float EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
int max_bytes, int* encoded_bytes);
virtual float DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
int16_t* out_data);
ISACFIX_MainStruct *ISACFIX_main_inst_;
};
IsacSpeedTest::IsacSpeedTest()
: AudioCodecSpeedTest(kIsacBlockDurationMs,
kIsacInputSamplingKhz,
kIsacOutputSamplingKhz),
ISACFIX_main_inst_(NULL) {
}
void IsacSpeedTest::SetUp() {
AudioCodecSpeedTest::SetUp();
// Check whether the allocated buffer for the bit stream is large enough.
EXPECT_GE(max_bytes_, STREAM_MAXW16_60MS);
// Create encoder memory.
EXPECT_EQ(0, WebRtcIsacfix_Create(&ISACFIX_main_inst_));
EXPECT_EQ(0, WebRtcIsacfix_EncoderInit(ISACFIX_main_inst_, 1));
EXPECT_EQ(0, WebRtcIsacfix_DecoderInit(ISACFIX_main_inst_));
// Set bitrate and block length.
EXPECT_EQ(0, WebRtcIsacfix_Control(ISACFIX_main_inst_, bit_rate_,
block_duration_ms_));
}
void IsacSpeedTest::TearDown() {
AudioCodecSpeedTest::TearDown();
// Free memory.
EXPECT_EQ(0, WebRtcIsacfix_Free(ISACFIX_main_inst_));
}
float IsacSpeedTest::EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
int max_bytes, int* encoded_bytes) {
// ISAC takes 10 ms everycall
const int subblocks = block_duration_ms_ / 10;
const int subblock_length = 10 * input_sampling_khz_;
int value;
clock_t clocks = clock();
size_t pointer = 0;
for (int idx = 0; idx < subblocks; idx++, pointer += subblock_length) {
value = WebRtcIsacfix_Encode(ISACFIX_main_inst_, &in_data[pointer],
reinterpret_cast<int16_t*>(bit_stream));
}
clocks = clock() - clocks;
EXPECT_GT(value, 0);
assert(value <= max_bytes);
*encoded_bytes = value;
return 1000.0 * clocks / CLOCKS_PER_SEC;
}
float IsacSpeedTest::DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
int16_t* out_data) {
int value;
int16_t audio_type;
clock_t clocks = clock();
value = WebRtcIsacfix_Decode(ISACFIX_main_inst_,
reinterpret_cast<const uint16_t*>(bit_stream),
encoded_bytes, out_data, &audio_type);
clocks = clock() - clocks;
EXPECT_EQ(output_length_sample_, value);
return 1000.0 * clocks / CLOCKS_PER_SEC;
}
TEST_P(IsacSpeedTest, IsacEncodeDecodeTest) {
size_t kDurationSec = 400; // Test audio length in second.
EncodeDecode(kDurationSec);
}
const coding_param param_set[] =
{::std::tr1::make_tuple(1, 32000, string("audio_coding/speech_mono_16kHz"),
string("pcm"), true)};
INSTANTIATE_TEST_CASE_P(AllTest, IsacSpeedTest,
::testing::ValuesIn(param_set));
} // namespace webrtc

View File

@@ -0,0 +1,826 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
#include "webrtc/test/testsupport/perf_test.h"
// TODO(kma): Clean up the code and change benchmarking the whole codec to
// separate encoder and decoder.
/* 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(int16_t *data, FILE *inp, int length) {
short k, rlen, status = 0;
rlen = fread(data, sizeof(int16_t), length, inp);
if (rlen < length) {
for (k = rlen; k < length; k++)
data[k] = 0;
status = 1;
}
return status;
}
/* Struct for bottleneck model */
typedef struct {
uint32_t send_time; /* samples */
uint32_t arrival_time; /* samples */
uint32_t sample_count; /* samples */
uint16_t 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;
int16_t CodingMode;
int16_t bottleneck;
int16_t framesize = 30; /* ms */
int cur_framesmpls, err = 0, lostPackets = 0;
/* Runtime statistics */
double starttime, runtime, length_file;
int16_t stream_len = 0;
int16_t framecnt, declen = 0;
int16_t shortdata[FRAMESAMPLES_10ms];
int16_t decoded[MAX_FRAMESAMPLES];
uint16_t streamdata[500];
int16_t speechType[1];
int16_t prevFrameSize = 1;
int16_t rateBPS = 0;
int16_t fixedFL = 0;
int16_t payloadSize = 0;
int32_t payloadRate = 0;
int setControlBWE = 0;
int readLoss;
FILE *plFile = NULL;
char version_number[20];
char tmpBit[5] = ".bit";
int totalbits =0;
int totalsmpls =0;
int16_t testNum, testCE;
FILE *fp_gns = NULL;
int gns = 0;
int cur_delay = 0;
char gns_file[100];
int nbTest = 0;
int16_t lostFrame;
float scale = (float)0.7;
/* only one structure used for ISAC encoder */
ISACFIX_MainStruct *ISAC_main_inst = NULL;
/* For fault test 10, garbage data */
FILE *seedfile;
unsigned int random_seed = (unsigned int) time(NULL);//1196764538
BottleNeckModel BN_data;
f_bn = NULL;
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 to 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 = (int16_t)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,
(int16_t*)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((int16_t*)streamdata, &bwe);
stream_len = WebRtcIsacfix_GetNewBitStream(
ISAC_main_inst,
bwe,
scale,
(int16_t*)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 = (int16_t)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);
}
}
if( readLoss == 1 ) {
if( fread( &lostFrame, sizeof(int16_t), 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((int16_t*)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(int16_t),
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;
/* 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);
}
}
}
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");
/* 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");
// Record the results with Perf test tools.
webrtc::test::PrintResult("isac", "", "time_per_10ms_frame",
(runtime * 10000) / length_file, "us", false);
fclose(inp);
fclose(outp);
fclose(outbits);
if ( testCE == 1) {
WebRtcIsacfix_FreeInternal(ISAC_main_inst);
}
WebRtcIsacfix_Free(ISAC_main_inst);
return 0;
}

View File

@@ -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(int16_t *data, FILE *inp, int length) {
short k, rlen, status = 0;
rlen = fread(data, sizeof(int16_t), length, inp);
if (rlen < length) {
for (k = rlen; k < length; k++)
data[k] = 0;
status = 1;
}
return status;
}
typedef struct {
uint32_t send_time; /* samples */
uint32_t arrival_time; /* samples */
uint32_t sample_count; /* samples */
uint16_t 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;
int16_t CodingMode;
int16_t bottleneck;
int16_t framesize = 30; /* ms */
//int16_t framesize = 60; /* To invoke cisco complexity case at frame 2252 */
int cur_framesmpls, err;
/* Runtime statistics */
double starttime;
double runtime;
double length_file;
int16_t stream_len = 0;
int16_t declen;
int16_t shortdata[FRAMESAMPLES_10ms];
int16_t decoded[MAX_FRAMESAMPLES];
uint16_t streamdata[600];
int16_t speechType[1];
// int16_t *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(int16_t), 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;
}

View File

@@ -0,0 +1,68 @@
# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
{
'targets': [
# simple kenny
{
'target_name': 'iSACtest',
'type': 'executable',
'dependencies': [
'iSAC',
],
'include_dirs': [
'./main/test',
'./main/interface',
'./main/util',
'<(webrtc_root)',
],
'sources': [
'./main/test/simpleKenny.c',
'./main/util/utility.c',
],
},
# ReleaseTest-API
{
'target_name': 'iSACAPITest',
'type': 'executable',
'dependencies': [
'iSAC',
],
'include_dirs': [
'./main/test',
'./main/interface',
'./main/util',
'<(webrtc_root)',
],
'sources': [
'./main/test/ReleaseTest-API/ReleaseTest-API.cc',
'./main/util/utility.c',
],
},
# SwitchingSampRate
{
'target_name': 'iSACSwitchSampRateTest',
'type': 'executable',
'dependencies': [
'iSAC',
],
'include_dirs': [
'./main/test',
'./main/interface',
'../../../../common_audio/signal_processing/include',
'./main/util',
'<(webrtc_root)',
],
'sources': [
'./main/test/SwitchingSampRate/SwitchingSampRate.cc',
'./main/util/utility.c',
],
},
],
}

View File

@@ -0,0 +1,35 @@
# 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': [
# kenny
{
'target_name': 'iSACFixtest',
'type': 'executable',
'dependencies': [
'iSACFix',
'<(webrtc_root)/test/test.gyp:test_support',
],
'include_dirs': [
'./fix/test',
'./fix/interface',
'<(webrtc_root)',
],
'sources': [
'./fix/test/kenny.cc',
],
# Disable warnings to enable Win64 build, issue 1323.
'msvs_disabled_warnings': [
4267, # size_t to int truncation.
],
},
],
}
# TODO(kma): Add bit-exact test for iSAC-fix.

View File

@@ -0,0 +1,718 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
/*
* Define the fixed-point numeric formats
*/
#include "webrtc/typedefs.h"
typedef struct WebRtcISACStruct ISACStruct;
#if defined(__cplusplus)
extern "C" {
#endif
/******************************************************************************
* WebRtcIsac_AssignSize(...)
*
* This function returns the size of the ISAC instance, so that the instance
* can be created outside iSAC.
*
* Input:
* - samplingRate : sampling rate of the input/output audio.
*
* Output:
* - sizeinbytes : number of bytes needed to allocate for the
* instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_AssignSize(
int* sizeinbytes);
/******************************************************************************
* WebRtcIsac_Assign(...)
*
* This function assignes the memory already created to the ISAC instance.
*
* Input:
* - *ISAC_main_inst : a pointer to the coder instance.
* - samplingRate : sampling rate of the input/output audio.
* - ISAC_inst_Addr : the already allocated memory, where we put the
* iSAC structure.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_Assign(
ISACStruct** ISAC_main_inst,
void* ISAC_inst_Addr);
/******************************************************************************
* WebRtcIsac_Create(...)
*
* This function creates an ISAC instance, which will contain the state
* information for one coding/decoding channel.
*
* Input:
* - *ISAC_main_inst : a pointer to the coder instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_Create(
ISACStruct** ISAC_main_inst);
/******************************************************************************
* WebRtcIsac_Free(...)
*
* This function frees the ISAC instance created at the beginning.
*
* Input:
* - ISAC_main_inst : an ISAC instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_Free(
ISACStruct* ISAC_main_inst);
/******************************************************************************
* WebRtcIsac_EncoderInit(...)
*
* This function initializes an ISAC instance prior to the encoder calls.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - CodingMode : 0 -> Bit rate and frame length are
* automatically adjusted to available bandwidth
* on transmission channel, just valid if codec
* is created to work in wideband mode.
* 1 -> User sets a frame length and a target bit
* rate which is taken as the maximum
* short-term average bit rate.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_EncoderInit(
ISACStruct* ISAC_main_inst,
int16_t CodingMode);
/******************************************************************************
* WebRtcIsac_Encode(...)
*
* This function encodes 10ms audio blocks and inserts it into a package.
* Input speech length has 160 samples if operating at 16 kHz sampling
* rate, or 320 if operating at 32 kHz sampling rate. The encoder buffers the
* input audio until the whole frame is buffered then proceeds with encoding.
*
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - speechIn : input speech vector.
*
* Output:
* - encoded : the encoded data vector
*
* Return value:
* : >0 - Length (in bytes) of coded data
* : 0 - The buffer didn't reach the chosen
* frame-size so it keeps buffering speech
* samples.
* : -1 - Error
*/
int16_t WebRtcIsac_Encode(
ISACStruct* ISAC_main_inst,
const int16_t* speechIn,
int16_t* encoded);
/******************************************************************************
* WebRtcIsac_DecoderInit(...)
*
* This function initializes an ISAC instance prior to the decoder calls.
*
* Input:
* - ISAC_main_inst : ISAC instance.
*
* Return value
* : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_DecoderInit(
ISACStruct* ISAC_main_inst);
/******************************************************************************
* WebRtcIsac_UpdateBwEstimate(...)
*
* This function updates the estimate of the bandwidth.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - encoded : encoded ISAC frame(s).
* - packet_size : size of the packet.
* - rtp_seq_number : the RTP number of the packet.
* - send_ts : the RTP send timestamp, given in samples
* - arr_ts : the arrival time of the packet (from NetEq)
* in samples.
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_UpdateBwEstimate(
ISACStruct* ISAC_main_inst,
const uint16_t* encoded,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts);
/******************************************************************************
* WebRtcIsac_Decode(...)
*
* This function decodes an ISAC frame. At 16 kHz sampling rate, the length
* of the output audio could be either 480 or 960 samples, equivalent to
* 30 or 60 ms respectively. At 32 kHz sampling rate, the length of the
* output audio is 960 samples, which is 30 ms.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - encoded : encoded ISAC frame(s).
* - len : bytes in encoded vector.
*
* Output:
* - decoded : The decoded vector.
*
* Return value : >0 - number of samples in decoded vector.
* -1 - Error.
*/
int16_t WebRtcIsac_Decode(
ISACStruct* ISAC_main_inst,
const uint16_t* encoded,
int16_t len,
int16_t* decoded,
int16_t* speechType);
/******************************************************************************
* WebRtcIsac_DecodePlc(...)
*
* This function conducts PLC for ISAC frame(s). Output speech length
* will be a multiple of frames, i.e. multiples of 30 ms audio. Therefore,
* the output is multiple of 480 samples if operating at 16 kHz and multiple
* of 960 if operating at 32 kHz.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - noOfLostFrames : Number of PLC frames to produce.
*
* Output:
* - decoded : The decoded vector.
*
* Return value : >0 - number of samples in decoded PLC vector
* -1 - Error
*/
int16_t WebRtcIsac_DecodePlc(
ISACStruct* ISAC_main_inst,
int16_t* decoded,
int16_t noOfLostFrames);
/******************************************************************************
* WebRtcIsac_Control(...)
*
* This function sets the limit on the short-term average bit-rate and the
* frame length. Should be used only in Instantaneous mode. At 16 kHz sampling
* rate, an average bit-rate between 10000 to 32000 bps is valid and a
* frame-size of 30 or 60 ms is acceptable. At 32 kHz, an average bit-rate
* between 10000 to 56000 is acceptable, and the valid frame-size is 30 ms.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - rate : limit on the short-term average bit rate,
* in bits/second.
* - framesize : frame-size in millisecond.
*
* Return value : 0 - ok
* -1 - Error
*/
int16_t WebRtcIsac_Control(
ISACStruct* ISAC_main_inst,
int32_t rate,
int16_t framesize);
/******************************************************************************
* WebRtcIsac_ControlBwe(...)
*
* This function sets the initial values of bottleneck and frame-size if
* iSAC is used in channel-adaptive mode. Therefore, this API is not
* applicable if the codec is created to operate in super-wideband mode.
*
* Through this API, users can enforce a frame-size for all values of
* bottleneck. Then iSAC will not automatically change the frame-size.
*
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - rateBPS : initial value of bottleneck in bits/second
* 10000 <= rateBPS <= 56000 is accepted
* For default bottleneck set rateBPS = 0
* - frameSizeMs : number of milliseconds per frame (30 or 60)
* - enforceFrameSize : 1 to enforce the given frame-size through
* out the adaptation process, 0 to let iSAC
* change the frame-size if required.
*
* Return value : 0 - ok
* -1 - Error
*/
int16_t WebRtcIsac_ControlBwe(
ISACStruct* ISAC_main_inst,
int32_t rateBPS,
int16_t frameSizeMs,
int16_t enforceFrameSize);
/******************************************************************************
* WebRtcIsac_ReadFrameLen(...)
*
* This function returns the length of the frame represented in the packet.
*
* Input:
* - encoded : Encoded bit-stream
*
* Output:
* - frameLength : Length of frame in packet (in samples)
*
*/
int16_t WebRtcIsac_ReadFrameLen(
ISACStruct* ISAC_main_inst,
const int16_t* encoded,
int16_t* frameLength);
/******************************************************************************
* WebRtcIsac_version(...)
*
* This function returns the version number.
*
* Output:
* - version : Pointer to character string
*
*/
void WebRtcIsac_version(
char *version);
/******************************************************************************
* WebRtcIsac_GetErrorCode(...)
*
* This function can be used to check the error code of an iSAC instance. When
* a function returns -1 a error code will be set for that instance. The
* function below extract the code of the last error that occurred in the
* specified instance.
*
* Input:
* - ISAC_main_inst : ISAC instance
*
* Return value : Error code
*/
int16_t WebRtcIsac_GetErrorCode(
ISACStruct* ISAC_main_inst);
/****************************************************************************
* WebRtcIsac_GetUplinkBw(...)
*
* This function outputs the target bottleneck of the codec. In
* channel-adaptive mode, the target bottleneck is specified through in-band
* signalling retreived by bandwidth estimator.
* In channel-independent, also called instantaneous mode, the target
* bottleneck is provided to the encoder by calling xxx_control(...). If
* xxx_control is never called the default values is returned. The default
* value for bottleneck at 16 kHz encoder sampling rate is 32000 bits/sec,
* and it is 56000 bits/sec for 32 kHz sampling rate.
* Note that the output is the iSAC internal operating bottleneck which might
* differ slightly from the one provided through xxx_control().
*
* Input:
* - ISAC_main_inst : iSAC instance
*
* Output:
* - *bottleneck : bottleneck in bits/sec
*
* Return value : -1 if error happens
* 0 bit-rates computed correctly.
*/
int16_t WebRtcIsac_GetUplinkBw(
ISACStruct* ISAC_main_inst,
int32_t* bottleneck);
/******************************************************************************
* WebRtcIsac_SetMaxPayloadSize(...)
*
* This function sets a limit for the maximum payload size of iSAC. The same
* value is used both for 30 and 60 ms packets. If the encoder sampling rate
* is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
* encoder sampling rate is 32 kHz the maximum payload size is between 120
* and 600 bytes.
*
* If an out of range limit is used, the function returns -1, but the closest
* valid value will be applied.
*
* ---------------
* IMPORTANT NOTES
* ---------------
* The size of a packet is limited to the minimum of 'max-payload-size' and
* 'max-rate.' For instance, let's assume the max-payload-size is set to
* 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
* translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
* frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
* i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
* 170 bytes, i.e. min(170, 300).
*
* Input:
* - ISAC_main_inst : iSAC instance
* - maxPayloadBytes : maximum size of the payload in bytes
* valid values are between 120 and 400 bytes
* if encoder sampling rate is 16 kHz. For
* 32 kHz encoder sampling rate valid values
* are between 120 and 600 bytes.
*
* Return value : 0 if successful
* -1 if error happens
*/
int16_t WebRtcIsac_SetMaxPayloadSize(
ISACStruct* ISAC_main_inst,
int16_t maxPayloadBytes);
/******************************************************************************
* WebRtcIsac_SetMaxRate(...)
*
* This function sets the maximum rate which the codec may not exceed for
* any signal packet. The maximum rate is defined and payload-size per
* frame-size in bits per second.
*
* The codec has a maximum rate of 53400 bits per second (200 bytes per 30
* ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
* if the encoder sampling rate is 32 kHz.
*
* It is possible to set a maximum rate between 32000 and 53400 bits/sec
* in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
*
* If an out of range limit is used, the function returns -1, but the closest
* valid value will be applied.
*
* ---------------
* IMPORTANT NOTES
* ---------------
* The size of a packet is limited to the minimum of 'max-payload-size' and
* 'max-rate.' For instance, let's assume the max-payload-size is set to
* 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
* translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
* frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
* i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
* 170 bytes, min(170, 300).
*
* Input:
* - ISAC_main_inst : iSAC instance
* - maxRate : maximum rate in bits per second,
* valid values are 32000 to 53400 bits/sec in
* wideband mode, and 32000 to 160000 bits/sec in
* super-wideband mode.
*
* Return value : 0 if successful
* -1 if error happens
*/
int16_t WebRtcIsac_SetMaxRate(
ISACStruct* ISAC_main_inst,
int32_t maxRate);
/******************************************************************************
* WebRtcIsac_DecSampRate()
* Return the sampling rate of the decoded audio.
*
* Input:
* - ISAC_main_inst : iSAC instance
*
* Return value : sampling frequency in Hertz.
*
*/
uint16_t WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst);
/******************************************************************************
* WebRtcIsac_EncSampRate()
*
* Input:
* - ISAC_main_inst : iSAC instance
*
* Return value : sampling rate in Hertz.
*
*/
uint16_t WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst);
/******************************************************************************
* WebRtcIsac_SetDecSampRate()
* Set the sampling rate of the decoder. Initialization of the decoder WILL
* NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
* which is set when the instance is created.
*
* Input:
* - ISAC_main_inst : iSAC instance
* - sampRate : sampling rate in Hertz.
*
* Return value : 0 if successful
* -1 if failed.
*/
int16_t WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
uint16_t samp_rate_hz);
/******************************************************************************
* WebRtcIsac_SetEncSampRate()
* Set the sampling rate of the encoder. Initialization of the encoder WILL
* NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
* which is set when the instance is created. The encoding-mode and the
* bottleneck remain unchanged by this call, however, the maximum rate and
* maximum payload-size will reset to their default value.
*
* Input:
* - ISAC_main_inst : iSAC instance
* - sampRate : sampling rate in Hertz.
*
* Return value : 0 if successful
* -1 if failed.
*/
int16_t WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
uint16_t sample_rate_hz);
/******************************************************************************
* WebRtcIsac_GetNewBitStream(...)
*
* This function returns encoded data, with the recieved bwe-index in the
* stream. If the rate is set to a value less than bottleneck of codec
* the new bistream will be re-encoded with the given target rate.
* It should always return a complete packet, i.e. only called once
* even for 60 msec frames.
*
* NOTE 1! This function does not write in the ISACStruct, it is not allowed.
* NOTE 2! Currently not implemented for SWB mode.
* NOTE 3! Rates larger than the bottleneck of the codec will be limited
* to the current bottleneck.
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - bweIndex : Index of bandwidth estimate to put in new
* bitstream
* - rate : target rate of the transcoder is bits/sec.
* Valid values are the accepted rate in iSAC,
* i.e. 10000 to 56000.
* - isRCU : if the new bit-stream is an RCU stream.
* Note that the rate parameter always indicates
* the target rate of the main payload, regardless
* of 'isRCU' value.
*
* Output:
* - encoded : The encoded data vector
*
* Return value : >0 - Length (in bytes) of coded data
* -1 - Error or called in SWB mode
* NOTE! No error code is written to
* the struct since it is only allowed to read
* the struct.
*/
int16_t WebRtcIsac_GetNewBitStream(
ISACStruct* ISAC_main_inst,
int16_t bweIndex,
int16_t jitterInfo,
int32_t rate,
int16_t* encoded,
int16_t isRCU);
/****************************************************************************
* WebRtcIsac_GetDownLinkBwIndex(...)
*
* This function returns index representing the Bandwidth estimate from
* other side to this side.
*
* Input:
* - ISAC_main_inst : iSAC struct
*
* Output:
* - bweIndex : Bandwidth estimate to transmit to other side.
*
*/
int16_t WebRtcIsac_GetDownLinkBwIndex(
ISACStruct* ISAC_main_inst,
int16_t* bweIndex,
int16_t* jitterInfo);
/****************************************************************************
* WebRtcIsac_UpdateUplinkBw(...)
*
* This function takes an index representing the Bandwidth estimate from
* this side to other side and updates BWE.
*
* Input:
* - ISAC_main_inst : iSAC struct
* - bweIndex : Bandwidth estimate from other side.
*
*/
int16_t WebRtcIsac_UpdateUplinkBw(
ISACStruct* ISAC_main_inst,
int16_t bweIndex);
/****************************************************************************
* WebRtcIsac_ReadBwIndex(...)
*
* This function returns the index of the Bandwidth estimate from the bitstream.
*
* Input:
* - encoded : Encoded bitstream
*
* Output:
* - frameLength : Length of frame in packet (in samples)
* - bweIndex : Bandwidth estimate in bitstream
*
*/
int16_t WebRtcIsac_ReadBwIndex(
const int16_t* encoded,
int16_t* bweIndex);
/*******************************************************************************
* WebRtcIsac_GetNewFrameLen(...)
*
* returns the frame lenght (in samples) of the next packet. In the case of channel-adaptive
* mode, iSAC decides on its frame lenght based on the estimated bottleneck
* this allows a user to prepare for the next packet (at the encoder)
*
* The primary usage is in CE to make the iSAC works in channel-adaptive mode
*
* Input:
* - ISAC_main_inst : iSAC struct
*
* Return Value : frame lenght in samples
*
*/
int16_t WebRtcIsac_GetNewFrameLen(
ISACStruct* ISAC_main_inst);
/****************************************************************************
* WebRtcIsac_GetRedPayload(...)
*
* Populates "encoded" with the redundant payload of the recently encoded
* frame. This function has to be called once that WebRtcIsac_Encode(...)
* returns a positive value. Regardless of the frame-size this function will
* be called only once after encoding is completed.
*
* Input:
* - ISAC_main_inst : iSAC struct
*
* Output:
* - encoded : the encoded data vector
*
*
* Return value:
* : >0 - Length (in bytes) of coded data
* : -1 - Error
*
*
*/
int16_t WebRtcIsac_GetRedPayload(
ISACStruct* ISAC_main_inst,
int16_t* encoded);
/****************************************************************************
* WebRtcIsac_DecodeRcu(...)
*
* This function decodes a redundant (RCU) iSAC frame. Function is called in
* NetEq with a stored RCU payload i case of packet loss. Output speech length
* will be a multiple of 480 samples: 480 or 960 samples,
* depending on the framesize (30 or 60 ms).
*
* Input:
* - ISAC_main_inst : ISAC instance.
* - encoded : encoded ISAC RCU frame(s)
* - len : bytes in encoded vector
*
* Output:
* - decoded : The decoded vector
*
* Return value : >0 - number of samples in decoded vector
* -1 - Error
*/
int16_t WebRtcIsac_DecodeRcu(
ISACStruct* ISAC_main_inst,
const uint16_t* encoded,
int16_t len,
int16_t* decoded,
int16_t* speechType);
#if defined(__cplusplus)
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_ */

View File

@@ -0,0 +1,5 @@
# These are for the common case of adding or renaming files. If you're doing
# structural changes, please get a review from a reviewer in this file.
per-file *.gyp=*
per-file *.gypi=*

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "arith_routines.h"
#include "settings.h"
/*
* terminate and return byte stream;
* returns the number of bytes in the stream
*/
int WebRtcIsac_EncTerminate(Bitstr *streamdata) /* in-/output struct containing bitstream */
{
uint8_t *stream_ptr;
/* point to the right place in the stream buffer */
stream_ptr = streamdata->stream + streamdata->stream_index;
/* find minimum length (determined by current interval width) */
if ( streamdata->W_upper > 0x01FFFFFF )
{
streamdata->streamval += 0x01000000;
/* add carry to buffer */
if (streamdata->streamval < 0x01000000)
{
/* propagate carry */
while ( !(++(*--stream_ptr)) );
/* put pointer back to the old value */
stream_ptr = streamdata->stream + streamdata->stream_index;
}
/* write remaining data to bitstream */
*stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
}
else
{
streamdata->streamval += 0x00010000;
/* add carry to buffer */
if (streamdata->streamval < 0x00010000)
{
/* propagate carry */
while ( !(++(*--stream_ptr)) );
/* put pointer back to the old value */
stream_ptr = streamdata->stream + streamdata->stream_index;
}
/* write remaining data to bitstream */
*stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
*stream_ptr++ = (uint8_t) ((streamdata->streamval >> 16) & 0x00FF);
}
/* calculate stream length */
return (int)(stream_ptr - streamdata->stream);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* arith_routines.h
*
* Functions for arithmetic coding.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
#include "structs.h"
int WebRtcIsac_EncLogisticMulti2(
Bitstr *streamdata, /* in-/output struct containing bitstream */
int16_t *dataQ7, /* input: data vector */
const uint16_t *env, /* input: side info vector defining the width of the pdf */
const int N, /* input: data vector length */
const int16_t isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
/* returns the number of bytes in the stream */
int WebRtcIsac_EncTerminate(Bitstr *streamdata); /* in-/output struct containing bitstream */
/* returns the number of bytes in the stream so far */
int WebRtcIsac_DecLogisticMulti2(
int16_t *data, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t *env, /* input: side info vector defining the width of the pdf */
const int16_t *dither, /* input: dither vector */
const int N, /* input: data vector length */
const int16_t isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
void WebRtcIsac_EncHistMulti(
Bitstr *streamdata, /* in-/output struct containing bitstream */
const int *data, /* input: data vector */
const uint16_t **cdf, /* input: array of cdf arrays */
const int N); /* input: data vector length */
int WebRtcIsac_DecHistBisectMulti(
int *data, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t **cdf, /* input: array of cdf arrays */
const uint16_t *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
const int N); /* input: data vector length */
int WebRtcIsac_DecHistOneStepMulti(
int *data, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t **cdf, /* input: array of cdf arrays */
const uint16_t *init_index,/* input: vector of initial cdf table search entries */
const int N); /* input: data vector length */
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_ */

View File

@@ -0,0 +1,291 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "settings.h"
#include "arith_routines.h"
/*
* code symbols into arithmetic bytestream
*/
void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
const int *data, /* input: data vector */
const uint16_t **cdf, /* input: array of cdf arrays */
const int N) /* input: data vector length */
{
uint32_t W_lower, W_upper;
uint32_t W_upper_LSB, W_upper_MSB;
uint8_t *stream_ptr;
uint8_t *stream_ptr_carry;
uint32_t cdf_lo, cdf_hi;
int k;
/* point to beginning of stream buffer */
stream_ptr = streamdata->stream + streamdata->stream_index;
W_upper = streamdata->W_upper;
for (k=N; k>0; k--)
{
/* fetch cdf_lower and cdf_upper from cdf tables */
cdf_lo = (uint32_t) *(*cdf + *data);
cdf_hi = (uint32_t) *(*cdf++ + *data++ + 1);
/* update interval */
W_upper_LSB = W_upper & 0x0000FFFF;
W_upper_MSB = W_upper >> 16;
W_lower = W_upper_MSB * cdf_lo;
W_lower += (W_upper_LSB * cdf_lo) >> 16;
W_upper = W_upper_MSB * cdf_hi;
W_upper += (W_upper_LSB * cdf_hi) >> 16;
/* shift interval such that it begins at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamdata->streamval += W_lower;
/* handle carry */
if (streamdata->streamval < W_lower)
{
/* propagate carry */
stream_ptr_carry = stream_ptr;
while (!(++(*--stream_ptr_carry)));
}
/* renormalize interval, store most significant byte of streamval and update streamval */
while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
{
W_upper <<= 8;
*stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
streamdata->streamval <<= 8;
}
}
/* calculate new stream_index */
streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
streamdata->W_upper = W_upper;
return;
}
/*
* function to decode more symbols from the arithmetic bytestream, using method of bisection
* cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
*/
int WebRtcIsac_DecHistBisectMulti(int *data, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t **cdf, /* input: array of cdf arrays */
const uint16_t *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
const int N) /* input: data vector length */
{
uint32_t W_lower, W_upper;
uint32_t W_tmp;
uint32_t W_upper_LSB, W_upper_MSB;
uint32_t streamval;
const uint8_t *stream_ptr;
const uint16_t *cdf_ptr;
int size_tmp;
int k;
W_lower = 0; //to remove warning -DH
stream_ptr = streamdata->stream + streamdata->stream_index;
W_upper = streamdata->W_upper;
if (W_upper == 0)
/* Should not be possible in normal operation */
return -2;
if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
{
/* read first word from bytestream */
streamval = *stream_ptr << 24;
streamval |= *++stream_ptr << 16;
streamval |= *++stream_ptr << 8;
streamval |= *++stream_ptr;
} else {
streamval = streamdata->streamval;
}
for (k=N; k>0; k--)
{
/* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
W_upper_LSB = W_upper & 0x0000FFFF;
W_upper_MSB = W_upper >> 16;
/* start halfway the cdf range */
size_tmp = *cdf_size++ >> 1;
cdf_ptr = *cdf + (size_tmp - 1);
/* method of bisection */
for ( ;; )
{
W_tmp = W_upper_MSB * *cdf_ptr;
W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
size_tmp >>= 1;
if (size_tmp == 0) break;
if (streamval > W_tmp)
{
W_lower = W_tmp;
cdf_ptr += size_tmp;
} else {
W_upper = W_tmp;
cdf_ptr -= size_tmp;
}
}
if (streamval > W_tmp)
{
W_lower = W_tmp;
*data++ = (int)(cdf_ptr - *cdf++);
} else {
W_upper = W_tmp;
*data++ = (int)(cdf_ptr - *cdf++ - 1);
}
/* shift interval to start at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamval -= W_lower;
/* renormalize interval and update streamval */
while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
{
/* read next byte from stream */
streamval = (streamval << 8) | *++stream_ptr;
W_upper <<= 8;
}
if (W_upper == 0)
/* Should not be possible in normal operation */
return -2;
}
streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
streamdata->W_upper = W_upper;
streamdata->streamval = streamval;
/* find number of bytes in original stream (determined by current interval width) */
if ( W_upper > 0x01FFFFFF )
return streamdata->stream_index - 2;
else
return streamdata->stream_index - 1;
}
/*
* function to decode more symbols from the arithmetic bytestream, taking single step up or
* down at a time
* cdf tables can be of arbitrary size, but large tables may take a lot of iterations
*/
int WebRtcIsac_DecHistOneStepMulti(int *data, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t **cdf, /* input: array of cdf arrays */
const uint16_t *init_index, /* input: vector of initial cdf table search entries */
const int N) /* input: data vector length */
{
uint32_t W_lower, W_upper;
uint32_t W_tmp;
uint32_t W_upper_LSB, W_upper_MSB;
uint32_t streamval;
const uint8_t *stream_ptr;
const uint16_t *cdf_ptr;
int k;
stream_ptr = streamdata->stream + streamdata->stream_index;
W_upper = streamdata->W_upper;
if (W_upper == 0)
/* Should not be possible in normal operation */
return -2;
if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
{
/* read first word from bytestream */
streamval = *stream_ptr << 24;
streamval |= *++stream_ptr << 16;
streamval |= *++stream_ptr << 8;
streamval |= *++stream_ptr;
} else {
streamval = streamdata->streamval;
}
for (k=N; k>0; k--)
{
/* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
W_upper_LSB = W_upper & 0x0000FFFF;
W_upper_MSB = W_upper >> 16;
/* start at the specified table entry */
cdf_ptr = *cdf + (*init_index++);
W_tmp = W_upper_MSB * *cdf_ptr;
W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
if (streamval > W_tmp)
{
for ( ;; )
{
W_lower = W_tmp;
if (cdf_ptr[0]==65535)
/* range check */
return -3;
W_tmp = W_upper_MSB * *++cdf_ptr;
W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
if (streamval <= W_tmp) break;
}
W_upper = W_tmp;
*data++ = (int)(cdf_ptr - *cdf++ - 1);
} else {
for ( ;; )
{
W_upper = W_tmp;
--cdf_ptr;
if (cdf_ptr<*cdf) {
/* range check */
return -3;
}
W_tmp = W_upper_MSB * *cdf_ptr;
W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
if (streamval > W_tmp) break;
}
W_lower = W_tmp;
*data++ = (int)(cdf_ptr - *cdf++);
}
/* shift interval to start at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamval -= W_lower;
/* renormalize interval and update streamval */
while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
{
/* read next byte from stream */
streamval = (streamval << 8) | *++stream_ptr;
W_upper <<= 8;
}
}
streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
streamdata->W_upper = W_upper;
streamdata->streamval = streamval;
/* find number of bytes in original stream (determined by current interval width) */
if ( W_upper > 0x01FFFFFF )
return streamdata->stream_index - 2;
else
return streamdata->stream_index - 1;
}

View File

@@ -0,0 +1,294 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* arith_routines.h
*
* This file contains functions for arithmatically encoding and
* decoding DFT coefficients.
*
*/
#include "arith_routines.h"
static const int32_t kHistEdgesQ15[51] = {
-327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
-196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
-65536, -52429, -39322, -26215, -13108, 0, 13107, 26214, 39321, 52428,
65536, 78643, 91750, 104857, 117964, 131072, 144179, 157286, 170393, 183500,
196608, 209715, 222822, 235929, 249036, 262144, 275251, 288358, 301465, 314572,
327680};
static const int kCdfSlopeQ0[51] = { /* Q0 */
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 13, 23, 47, 87, 154, 315, 700, 1088,
2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
1095, 660, 316, 145, 86, 41, 32, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 0};
static const int kCdfQ16[51] = { /* Q16 */
0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
20, 22, 24, 29, 38, 57, 92, 153, 279, 559,
994, 1983, 4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
65535};
/* function to be converted to fixed point */
static __inline uint32_t piecewise(int32_t xinQ15) {
int32_t ind, qtmp1, qtmp2, qtmp3;
uint32_t tmpUW32;
qtmp2 = xinQ15;
if (qtmp2 < kHistEdgesQ15[0]) {
qtmp2 = kHistEdgesQ15[0];
}
if (qtmp2 > kHistEdgesQ15[50]) {
qtmp2 = kHistEdgesQ15[50];
}
qtmp1 = qtmp2 - kHistEdgesQ15[0]; /* Q15 - Q15 = Q15 */
ind = (qtmp1 * 5) >> 16; /* 2^16 / 5 = 0.4 in Q15 */
/* Q15 -> Q0 */
qtmp1 = qtmp2 - kHistEdgesQ15[ind]; /* Q15 - Q15 = Q15 */
qtmp2 = kCdfSlopeQ0[ind] * qtmp1; /* Q0 * Q15 = Q15 */
qtmp3 = qtmp2>>15; /* Q15 -> Q0 */
tmpUW32 = kCdfQ16[ind] + qtmp3; /* Q0 + Q0 = Q0 */
return tmpUW32;
}
int WebRtcIsac_EncLogisticMulti2(
Bitstr *streamdata, /* in-/output struct containing bitstream */
int16_t *dataQ7, /* input: data vector */
const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
const int N, /* input: data vector length / 2 */
const int16_t isSWB12kHz)
{
uint32_t W_lower, W_upper;
uint32_t W_upper_LSB, W_upper_MSB;
uint8_t *stream_ptr;
uint8_t *maxStreamPtr;
uint8_t *stream_ptr_carry;
uint32_t cdf_lo, cdf_hi;
int k;
/* point to beginning of stream buffer */
stream_ptr = streamdata->stream + streamdata->stream_index;
W_upper = streamdata->W_upper;
maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1;
for (k = 0; k < N; k++)
{
/* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */
cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
/* test and clip if probability gets too small */
while (cdf_lo+1 >= cdf_hi) {
/* clip */
if (*dataQ7 > 0) {
*dataQ7 -= 128;
cdf_hi = cdf_lo;
cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
} else {
*dataQ7 += 128;
cdf_lo = cdf_hi;
cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
}
}
dataQ7++;
// increment only once per 4 iterations for SWB-16kHz or WB
// increment only once per 2 iterations for SWB-12kHz
envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
/* update interval */
W_upper_LSB = W_upper & 0x0000FFFF;
W_upper_MSB = W_upper >> 16;
W_lower = W_upper_MSB * cdf_lo;
W_lower += (W_upper_LSB * cdf_lo) >> 16;
W_upper = W_upper_MSB * cdf_hi;
W_upper += (W_upper_LSB * cdf_hi) >> 16;
/* shift interval such that it begins at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamdata->streamval += W_lower;
/* handle carry */
if (streamdata->streamval < W_lower)
{
/* propagate carry */
stream_ptr_carry = stream_ptr;
while (!(++(*--stream_ptr_carry)));
}
/* renormalize interval, store most significant byte of streamval and update streamval */
while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
{
W_upper <<= 8;
*stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
if(stream_ptr > maxStreamPtr)
{
return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
}
streamdata->streamval <<= 8;
}
}
/* calculate new stream_index */
streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
streamdata->W_upper = W_upper;
return 0;
}
int WebRtcIsac_DecLogisticMulti2(
int16_t *dataQ7, /* output: data vector */
Bitstr *streamdata, /* in-/output struct containing bitstream */
const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
const int16_t *ditherQ7,/* input: dither vector */
const int N, /* input: data vector length */
const int16_t isSWB12kHz)
{
uint32_t W_lower, W_upper;
uint32_t W_tmp;
uint32_t W_upper_LSB, W_upper_MSB;
uint32_t streamval;
const uint8_t *stream_ptr;
uint32_t cdf_tmp;
int16_t candQ7;
int k;
stream_ptr = streamdata->stream + streamdata->stream_index;
W_upper = streamdata->W_upper;
if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
{
/* read first word from bytestream */
streamval = *stream_ptr << 24;
streamval |= *++stream_ptr << 16;
streamval |= *++stream_ptr << 8;
streamval |= *++stream_ptr;
} else {
streamval = streamdata->streamval;
}
for (k = 0; k < N; k++)
{
/* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
W_upper_LSB = W_upper & 0x0000FFFF;
W_upper_MSB = W_upper >> 16;
/* find first candidate by inverting the logistic cdf */
candQ7 = - *ditherQ7 + 64;
cdf_tmp = piecewise(candQ7 * *envQ8);
W_tmp = W_upper_MSB * cdf_tmp;
W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
if (streamval > W_tmp)
{
W_lower = W_tmp;
candQ7 += 128;
cdf_tmp = piecewise(candQ7 * *envQ8);
W_tmp = W_upper_MSB * cdf_tmp;
W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
while (streamval > W_tmp)
{
W_lower = W_tmp;
candQ7 += 128;
cdf_tmp = piecewise(candQ7 * *envQ8);
W_tmp = W_upper_MSB * cdf_tmp;
W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
/* error check */
if (W_lower == W_tmp) return -1;
}
W_upper = W_tmp;
/* another sample decoded */
*dataQ7 = candQ7 - 64;
}
else
{
W_upper = W_tmp;
candQ7 -= 128;
cdf_tmp = piecewise(candQ7 * *envQ8);
W_tmp = W_upper_MSB * cdf_tmp;
W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
while ( !(streamval > W_tmp) )
{
W_upper = W_tmp;
candQ7 -= 128;
cdf_tmp = piecewise(candQ7 * *envQ8);
W_tmp = W_upper_MSB * cdf_tmp;
W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
/* error check */
if (W_upper == W_tmp) return -1;
}
W_lower = W_tmp;
/* another sample decoded */
*dataQ7 = candQ7 + 64;
}
ditherQ7++;
dataQ7++;
// increment only once per 4 iterations for SWB-16kHz or WB
// increment only once per 2 iterations for SWB-12kHz
envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
/* shift interval to start at zero */
W_upper -= ++W_lower;
/* add integer to bitstream */
streamval -= W_lower;
/* renormalize interval and update streamval */
while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
{
/* read next byte from stream */
streamval = (streamval << 8) | *++stream_ptr;
W_upper <<= 8;
}
}
streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
streamdata->W_upper = W_upper;
streamdata->streamval = streamval;
/* find number of bytes in original stream (determined by current interval width) */
if ( W_upper > 0x01FFFFFF )
return streamdata->stream_index - 2;
else
return streamdata->stream_index - 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* bandwidth_estimator.h
*
* This header file contains the API for the Bandwidth Estimator
* designed for iSAC.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
#include "structs.h"
#include "settings.h"
#define MIN_ISAC_BW 10000
#define MIN_ISAC_BW_LB 10000
#define MIN_ISAC_BW_UB 25000
#define MAX_ISAC_BW 56000
#define MAX_ISAC_BW_UB 32000
#define MAX_ISAC_BW_LB 32000
#define MIN_ISAC_MD 5
#define MAX_ISAC_MD 25
// assumed header size, in bytes; we don't know the exact number
// (header compression may be used)
#define HEADER_SIZE 35
// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
#define INIT_FRAME_LEN_WB 60
#define INIT_FRAME_LEN_SWB 30
// Initial Bottleneck Estimate, in bits/sec, for
// Wideband & Super-wideband mode
#define INIT_BN_EST_WB 20e3f
#define INIT_BN_EST_SWB 56e3f
// Initial Header rate (header rate depends on frame-size),
// in bits/sec, for Wideband & Super-Wideband mode.
#define INIT_HDR_RATE_WB \
((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
#define INIT_HDR_RATE_SWB \
((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
// number of packets in a row for a high rate burst
#define BURST_LEN 3
// ms, max time between two full bursts
#define BURST_INTERVAL 500
// number of packets in a row for initial high rate burst
#define INIT_BURST_LEN 5
// bits/s, rate for the first BURST_LEN packets
#define INIT_RATE_WB INIT_BN_EST_WB
#define INIT_RATE_SWB INIT_BN_EST_SWB
#if defined(__cplusplus)
extern "C" {
#endif
/* This function initializes the struct */
/* to be called before using the struct for anything else */
/* returns 0 if everything went fine, -1 otherwise */
int32_t WebRtcIsac_InitBandwidthEstimator(
BwEstimatorstr* bwest_str,
enum IsacSamplingRate encoderSampRate,
enum IsacSamplingRate decoderSampRate);
/* This function updates the receiving estimate */
/* Parameters: */
/* rtp_number - value from RTP packet, from NetEq */
/* frame length - length of signal frame in ms, from iSAC decoder */
/* send_ts - value in RTP header giving send time in samples */
/* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
/* pksize - size of packet in bytes, from NetEq */
/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
/* returns 0 if everything went fine, -1 otherwise */
int16_t WebRtcIsac_UpdateBandwidthEstimator(
BwEstimatorstr* bwest_str,
const uint16_t rtp_number,
const int32_t frame_length,
const uint32_t send_ts,
const uint32_t arr_ts,
const int32_t pksize);
/* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
int16_t WebRtcIsac_UpdateUplinkBwImpl(
BwEstimatorstr* bwest_str,
int16_t Index,
enum IsacSamplingRate encoderSamplingFreq);
/* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the sending iSAC payload */
uint16_t WebRtcIsac_GetDownlinkBwJitIndexImpl(
BwEstimatorstr* bwest_str,
int16_t* bottleneckIndex,
int16_t* jitterInfo,
enum IsacSamplingRate decoderSamplingFreq);
/* Returns the bandwidth estimation (in bps) */
int32_t WebRtcIsac_GetDownlinkBandwidth(
const BwEstimatorstr *bwest_str);
/* Returns the max delay (in ms) */
int32_t WebRtcIsac_GetDownlinkMaxDelay(
const BwEstimatorstr *bwest_str);
/* Returns the bandwidth that iSAC should send with in bps */
void WebRtcIsac_GetUplinkBandwidth(
const BwEstimatorstr* bwest_str,
int32_t* bitRate);
/* Returns the max delay value from the other side in ms */
int32_t WebRtcIsac_GetUplinkMaxDelay(
const BwEstimatorstr *bwest_str);
/*
* update amount of data in bottle neck buffer and burst handling
* returns minimum payload size (bytes)
*/
int WebRtcIsac_GetMinBytes(
RateModel* State,
int StreamSize, /* bytes in bitstream */
const int FrameLen, /* ms per frame */
const double BottleNeck, /* bottle neck rate; excl headers (bps) */
const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
enum ISACBandwidth bandwidth
/*,int16_t frequentLargePackets*/);
/*
* update long-term average bitrate and amount of data in buffer
*/
void WebRtcIsac_UpdateRateModel(
RateModel* State,
int StreamSize, /* bytes in bitstream */
const int FrameSamples, /* samples per frame */
const double BottleNeck); /* bottle neck rate; excl headers (bps) */
void WebRtcIsac_InitRateModel(
RateModel *State);
/* Returns the new framelength value (input argument: bottle_neck) */
int WebRtcIsac_GetNewFrameLength(
double bottle_neck,
int current_framelength);
/* Returns the new SNR value (input argument: bottle_neck) */
double WebRtcIsac_GetSnr(
double bottle_neck,
int new_framelength);
int16_t WebRtcIsac_UpdateUplinkJitter(
BwEstimatorstr* bwest_str,
int32_t index);
#if defined(__cplusplus)
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ */

View File

@@ -0,0 +1,217 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* codec.h
*
* This header file contains the calls to the internal encoder
* and decoder functions.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
#include "structs.h"
void WebRtcIsac_ResetBitstream(Bitstr* bit_stream);
int WebRtcIsac_EstimateBandwidth(BwEstimatorstr* bwest_str, Bitstr* streamdata,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts, uint32_t arr_ts,
enum IsacSamplingRate encoderSampRate,
enum IsacSamplingRate decoderSampRate);
int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdec_obj,
int16_t* current_framesamples,
int16_t isRCUPayload);
int WebRtcIsac_DecodeRcuLb(float* signal_out, ISACLBDecStruct* ISACdec_obj,
int16_t* current_framesamples);
int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj,
int16_t codingMode, int16_t
bottleneckIndex);
int WebRtcIsac_EncodeStoredDataLb(const ISAC_SaveEncData_t* ISACSavedEnc_obj,
Bitstr* ISACBitStr_obj, int BWnumber,
float scale);
int WebRtcIsac_EncodeStoredDataUb(
const ISACUBSaveEncDataStruct* ISACSavedEnc_obj, Bitstr* bitStream,
int32_t jitterInfo, float scale, enum ISACBandwidth bandwidth);
int16_t WebRtcIsac_GetRedPayloadUb(
const ISACUBSaveEncDataStruct* ISACSavedEncObj, Bitstr* bitStreamObj,
enum ISACBandwidth bandwidth);
/******************************************************************************
* WebRtcIsac_RateAllocation()
* Internal function to perform a rate-allocation for upper and lower-band,
* given a total rate.
*
* Input:
* - inRateBitPerSec : a total bit-rate in bits/sec.
*
* Output:
* - rateLBBitPerSec : a bit-rate allocated to the lower-band
* in bits/sec.
* - rateUBBitPerSec : a bit-rate allocated to the upper-band
* in bits/sec.
*
* Return value : 0 if rate allocation has been successful.
* -1 if failed to allocate rates.
*/
int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
double* rateLBBitPerSec,
double* rateUBBitPerSec,
enum ISACBandwidth* bandwidthKHz);
/******************************************************************************
* WebRtcIsac_DecodeUb16()
*
* Decode the upper-band if the codec is in 0-16 kHz mode.
*
* Input/Output:
* -ISACdec_obj : pointer to the upper-band decoder object. The
* bit-stream is stored inside the decoder object.
*
* Output:
* -signal_out : decoded audio, 480 samples 30 ms.
*
* Return value : >0 number of decoded bytes.
* <0 if an error occurred.
*/
int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdec_obj,
int16_t isRCUPayload);
/******************************************************************************
* WebRtcIsac_DecodeUb12()
*
* Decode the upper-band if the codec is in 0-12 kHz mode.
*
* Input/Output:
* -ISACdec_obj : pointer to the upper-band decoder object. The
* bit-stream is stored inside the decoder object.
*
* Output:
* -signal_out : decoded audio, 480 samples 30 ms.
*
* Return value : >0 number of decoded bytes.
* <0 if an error occurred.
*/
int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdec_obj,
int16_t isRCUPayload);
/******************************************************************************
* WebRtcIsac_EncodeUb16()
*
* Encode the upper-band if the codec is in 0-16 kHz mode.
*
* Input:
* -in : upper-band audio, 160 samples (10 ms).
*
* Input/Output:
* -ISACdec_obj : pointer to the upper-band encoder object. The
* bit-stream is stored inside the encoder object.
*
* Return value : >0 number of encoded bytes.
* <0 if an error occurred.
*/
int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACenc_obj,
int32_t jitterInfo);
/******************************************************************************
* WebRtcIsac_EncodeUb12()
*
* Encode the upper-band if the codec is in 0-12 kHz mode.
*
* Input:
* -in : upper-band audio, 160 samples (10 ms).
*
* Input/Output:
* -ISACdec_obj : pointer to the upper-band encoder object. The
* bit-stream is stored inside the encoder object.
*
* Return value : >0 number of encoded bytes.
* <0 if an error occurred.
*/
int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACenc_obj,
int32_t jitterInfo);
/************************** initialization functions *************************/
void WebRtcIsac_InitMasking(MaskFiltstr* maskdata);
void WebRtcIsac_InitPreFilterbank(PreFiltBankstr* prefiltdata);
void WebRtcIsac_InitPostFilterbank(PostFiltBankstr* postfiltdata);
void WebRtcIsac_InitPitchFilter(PitchFiltstr* pitchfiltdata);
void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* State);
/**************************** transform functions ****************************/
void WebRtcIsac_InitTransform();
void WebRtcIsac_Time2Spec(double* inre1, double* inre2, int16_t* outre,
int16_t* outim, FFTstr* fftstr_obj);
void WebRtcIsac_Spec2time(double* inre, double* inim, double* outre1,
double* outre2, FFTstr* fftstr_obj);
/******************************* filter functions ****************************/
void WebRtcIsac_AllPoleFilter(double* InOut, double* Coef, int lengthInOut,
int orderCoef);
void WebRtcIsac_AllZeroFilter(double* In, double* Coef, int lengthInOut,
int orderCoef, double* Out);
void WebRtcIsac_ZeroPoleFilter(double* In, double* ZeroCoef, double* PoleCoef,
int lengthInOut, int orderCoef, double* Out);
/***************************** filterbank functions **************************/
void WebRtcIsac_SplitAndFilterFloat(float* in, float* LP, float* HP,
double* LP_la, double* HP_la,
PreFiltBankstr* prefiltdata);
void WebRtcIsac_FilterAndCombineFloat(float* InLP, float* InHP, float* Out,
PostFiltBankstr* postfiltdata);
/************************* normalized lattice filters ************************/
void WebRtcIsac_NormLatticeFilterMa(int orderCoef, float* stateF, float* stateG,
float* lat_in, double* filtcoeflo,
double* lat_out);
void WebRtcIsac_NormLatticeFilterAr(int orderCoef, float* stateF, float* stateG,
double* lat_in, double* lo_filt_coef,
float* lat_out);
void WebRtcIsac_Dir2Lat(double* a, int orderCoef, float* sth, float* cth);
void WebRtcIsac_AutoCorr(double* r, const double* x, int N, int order);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_ */

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "crc.h"
#include <stdlib.h>
#include "signal_processing_library.h"
#define POLYNOMIAL 0x04c11db7L
static const uint32_t kCrcTable[256] = {
0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4,
0x808d07d, 0xcc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
/****************************************************************************
* WebRtcIsac_GetCrc(...)
*
* This function returns a 32 bit CRC checksum of a bit stream
*
* Input:
* - bitstream : payload bitstream
* - len_bitstream_in_bytes : number of 8-bit words in the bit stream
*
* Output:
* - crc : checksum
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_GetCrc(const int16_t* bitstream,
int16_t len_bitstream_in_bytes,
uint32_t* crc)
{
uint8_t* bitstream_ptr_uw8;
uint32_t crc_state;
int byte_cntr;
int crc_tbl_indx;
/* Sanity Check. */
if (bitstream == NULL) {
return -1;
}
/* cast to UWord8 pointer */
bitstream_ptr_uw8 = (uint8_t *)bitstream;
/* initialize */
crc_state = 0xFFFFFFFF;
for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
bitstream_ptr_uw8[byte_cntr]) & 0xFF;
crc_state = WEBRTC_SPL_LSHIFT_U32(crc_state, 8) ^ kCrcTable[crc_tbl_indx];
}
*crc = ~crc_state;
return 0;
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* crc.h
*
* Checksum functions
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
#include "typedefs.h"
/****************************************************************************
* WebRtcIsac_GetCrc(...)
*
* This function returns a 32 bit CRC checksum of a bit stream
*
* Input:
* - encoded : payload bit stream
* - no_of_word8s : number of 8-bit words in the bit stream
*
* Output:
* - crc : checksum
*
* Return value : 0 - Ok
* -1 - Error
*/
int16_t WebRtcIsac_GetCrc(
const int16_t* encoded,
int16_t no_of_word8s,
uint32_t* crc);
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */

View File

@@ -0,0 +1,299 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* decode_B.c
*
* This file contains definition of funtions for decoding.
* Decoding of lower-band, including normal-decoding and RCU decoding.
* Decoding of upper-band, including 8-12 kHz, when the bandwidth is
* 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
*
*/
#include "codec.h"
#include "entropy_coding.h"
#include "pitch_estimator.h"
#include "bandwidth_estimator.h"
#include "structs.h"
#include "settings.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* function to decode the bitstream
* returns the total number of bytes in the stream
*/
int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdecLB_obj,
int16_t* current_framesamples,
int16_t isRCUPayload) {
int k;
int len, err;
int16_t bandwidthInd;
float LP_dec_float[FRAMESAMPLES_HALF];
float HP_dec_float[FRAMESAMPLES_HALF];
double LPw[FRAMESAMPLES_HALF];
double HPw[FRAMESAMPLES_HALF];
double LPw_pf[FRAMESAMPLES_HALF];
double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES];
double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
double PitchLags[4];
double PitchGains[4];
double AvgPitchGain;
int16_t PitchGains_Q12[4];
int16_t AvgPitchGain_Q12;
float gain;
int frame_nb; /* counter */
int frame_mode; /* 0 30ms, 1 for 60ms */
/* Processed_samples: 480 (30, 60 ms). Cannot take other values. */
WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj));
len = 0;
/* Decode framelength and BW estimation - not used,
only for stream pointer*/
err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
current_framesamples);
if (err < 0) {
return err;
}
/* Frame_mode:
* 0: indicates 30 ms frame (480 samples)
* 1: indicates 60 ms frame (960 samples) */
frame_mode = *current_framesamples / MAX_FRAMESAMPLES;
err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
if (err < 0) {
return err;
}
/* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames
bundled together (60ms). */
for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
/* Decode & de-quantize pitch parameters */
err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj,
PitchGains_Q12);
if (err < 0) {
return err;
}
err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12,
PitchLags);
if (err < 0) {
return err;
}
AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
/* Decode & de-quantize filter coefficients. */
err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef,
hi_filt_coef);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12,
kIsacLowerBand, real_f, imag_f);
if (len < 0) {
return len;
}
/* Inverse transform. */
WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw,
&ISACdecLB_obj->fftstr_obj);
/* Convert PitchGains back to float for pitchfilter_post */
for (k = 0; k < 4; k++) {
PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
}
if (isRCUPayload) {
for (k = 0; k < 240; k++) {
LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
}
}
/* Inverse pitch filter. */
WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj,
PitchLags, PitchGains);
/* Convert AvgPitchGain back to float for computation of gain. */
AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096;
gain = 1.0f - 0.45f * (float)AvgPitchGain;
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
/* Reduce gain to compensate for pitch enhancer. */
LPw_pf[k] *= gain;
}
if (isRCUPayload) {
for (k = 0; k < FRAMESAMPLES_HALF; k++) {
/* Compensation for transcoding gain changes. */
LPw_pf[k] *= RCU_TRANSCODING_SCALE;
HPw[k] *= RCU_TRANSCODING_SCALE;
}
}
/* Perceptual post-filtering (using normalized lattice filter). */
WebRtcIsac_NormLatticeFilterAr(
ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef,
LP_dec_float);
WebRtcIsac_NormLatticeFilterAr(
ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
(ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef,
HP_dec_float);
/* Recombine the 2 bands. */
WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float,
signal_out + frame_nb * FRAMESAMPLES,
&ISACdecLB_obj->postfiltbankstr_obj);
}
return len;
}
/*
* This decode function is called when the codec is operating in 16 kHz
* bandwidth to decode the upperband, i.e. 8-16 kHz.
*
* Contrary to lower-band, the upper-band (8-16 kHz) is not split in
* frequency, but split to 12 sub-frames, i.e. twice as lower-band.
*/
int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
int16_t isRCUPayload) {
int len, err;
double halfFrameFirst[FRAMESAMPLES_HALF];
double halfFrameSecond[FRAMESAMPLES_HALF];
double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) +
(UB_LPC_ORDER + 1)];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
len = 0;
/* Decode & de-quantize filter coefficients. */
memset(percepFilterParam, 0, sizeof(percepFilterParam));
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
percepFilterParam, isac16kHz);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
kIsacUpperBand16, real_f, imag_f);
if (len < 0) {
return len;
}
if (isRCUPayload) {
int n;
for (n = 0; n < 240; n++) {
real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
}
}
/* Inverse transform. */
WebRtcIsac_Spec2time(real_f, imag_f, halfFrameFirst, halfFrameSecond,
&ISACdecUB_obj->fftstr_obj);
/* Perceptual post-filtering (using normalized lattice filter). */
WebRtcIsac_NormLatticeFilterAr(
UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
&percepFilterParam[(UB_LPC_ORDER + 1)], signal_out);
WebRtcIsac_NormLatticeFilterAr(
UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
&percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)],
&signal_out[FRAMESAMPLES_HALF]);
return len;
}
/*
* This decode function is called when the codec operates at 0-12 kHz
* bandwidth to decode the upperband, i.e. 8-12 kHz.
*
* At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
* kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
* reconstructed and 12-16 kHz replaced with zeros. Then two bands
* are combined, to reconstruct the upperband 8-16 kHz.
*/
int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
int16_t isRCUPayload) {
int len, err;
float LP_dec_float[FRAMESAMPLES_HALF];
float HP_dec_float[FRAMESAMPLES_HALF];
double LPw[FRAMESAMPLES_HALF];
double HPw[FRAMESAMPLES_HALF];
double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES];
double real_f[FRAMESAMPLES_HALF];
double imag_f[FRAMESAMPLES_HALF];
const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
len = 0;
/* Decode & dequantize filter coefficients. */
err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
percepFilterParam, isac12kHz);
if (err < 0) {
return err;
}
/* Decode & de-quantize spectrum. */
len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
kIsacUpperBand12, real_f, imag_f);
if (len < 0) {
return len;
}
if (isRCUPayload) {
int n;
for (n = 0; n < 240; n++) {
real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
}
}
/* Inverse transform. */
WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj);
/* perceptual post-filtering (using normalized lattice filter) */
WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
(ISACdecUB_obj->maskfiltstr_obj).PostStateLoG,
LPw, percepFilterParam, LP_dec_float);
/* Zero for 12-16 kHz. */
memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
/* Recombine the 2 bands. */
WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
&ISACdecUB_obj->postfiltbankstr_obj);
return len;
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "structs.h"
#include "bandwidth_estimator.h"
#include "entropy_coding.h"
#include "codec.h"
int
WebRtcIsac_EstimateBandwidth(
BwEstimatorstr* bwest_str,
Bitstr* streamdata,
int32_t packet_size,
uint16_t rtp_seq_number,
uint32_t send_ts,
uint32_t arr_ts,
enum IsacSamplingRate encoderSampRate,
enum IsacSamplingRate decoderSampRate)
{
int16_t index;
int16_t frame_samples;
uint32_t sendTimestampIn16kHz;
uint32_t arrivalTimestampIn16kHz;
uint32_t diffSendTime;
uint32_t diffArrivalTime;
int err;
/* decode framelength and BW estimation */
err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
if(err < 0) // error check
{
return err;
}
err = WebRtcIsac_DecodeSendBW(streamdata, &index);
if(err < 0) // error check
{
return err;
}
/* UPDATE ESTIMATES FROM OTHER SIDE */
err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
if(err < 0)
{
return err;
}
// We like BWE to work at 16 kHz sampling rate,
// therefore, we have to change the timestamps accordingly.
// translate the send timestamp if required
diffSendTime = (uint32_t)((uint32_t)send_ts -
(uint32_t)bwest_str->senderTimestamp);
bwest_str->senderTimestamp = send_ts;
diffArrivalTime = (uint32_t)((uint32_t)arr_ts -
(uint32_t)bwest_str->receiverTimestamp);
bwest_str->receiverTimestamp = arr_ts;
if(decoderSampRate == kIsacSuperWideband)
{
diffArrivalTime = (uint32_t)diffArrivalTime >> 1;
diffSendTime = (uint32_t)diffSendTime >> 1;
}
// arrival timestamp in 16 kHz
arrivalTimestampIn16kHz = (uint32_t)((uint32_t)
bwest_str->prev_rec_arr_ts + (uint32_t)diffArrivalTime);
// send timestamp in 16 kHz
sendTimestampIn16kHz = (uint32_t)((uint32_t)
bwest_str->prev_rec_send_ts + (uint32_t)diffSendTime);
err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
(frame_samples * 1000) / FS, sendTimestampIn16kHz,
arrivalTimestampIn16kHz, packet_size);
// error check
if(err < 0)
{
return err;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,708 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* code_LPC_UB.c
*
* This file contains definition of functions used to
* encode LPC parameters (Shape & gain) of the upper band.
*
*/
#include "encode_lpc_swb.h"
#include "typedefs.h"
#include "settings.h"
#include "lpc_shape_swb12_tables.h"
#include "lpc_shape_swb16_tables.h"
#include "lpc_gain_swb_tables.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
/******************************************************************************
* WebRtcIsac_RemoveLarMean()
*
* Remove the means from LAR coefficients.
*
* Input:
* -lar : pointer to lar vectors. LAR vectors are
* concatenated.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -lar : pointer to mean-removed LAR:s.
*
*
*/
int16_t
WebRtcIsac_RemoveLarMean(
double* lar,
int16_t bandwidth)
{
int16_t coeffCntr;
int16_t vecCntr;
int16_t numVec;
const double* meanLAR;
switch(bandwidth)
{
case isac12kHz:
{
numVec = UB_LPC_VEC_PER_FRAME;
meanLAR = WebRtcIsac_kMeanLarUb12;
break;
}
case isac16kHz:
{
numVec = UB16_LPC_VEC_PER_FRAME;
meanLAR = WebRtcIsac_kMeanLarUb16;
break;
}
default:
return -1;
}
for(vecCntr = 0; vecCntr < numVec; vecCntr++)
{
for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
{
// REMOVE MEAN
*lar++ -= meanLAR[coeffCntr];
}
}
return 0;
}
/******************************************************************************
* WebRtcIsac_DecorrelateIntraVec()
*
* Remove the correlation amonge the components of LAR vectors. If LAR vectors
* of one frame are put in a matrix where each column is a LAR vector of a
* sub-frame, then this is equivalent to multiplying the LAR matrix with
* a decorrelting mtrix from left.
*
* Input:
* -inLar : pointer to mean-removed LAR vecrtors.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : decorrelated LAR vectors.
*/
int16_t
WebRtcIsac_DecorrelateIntraVec(
const double* data,
double* out,
int16_t bandwidth)
{
const double* ptrData;
const double* ptrRow;
int16_t rowCntr;
int16_t colCntr;
int16_t larVecCntr;
int16_t numVec;
const double* decorrMat;
switch(bandwidth)
{
case isac12kHz:
{
decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
numVec = UB_LPC_VEC_PER_FRAME;
break;
}
case isac16kHz:
{
decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
numVec = UB16_LPC_VEC_PER_FRAME;
break;
}
default:
return -1;
}
//
// decorrMat * data
//
// data is assumed to contain 'numVec' of LAR
// vectors (mean removed) each of dimension 'UB_LPC_ORDER'
// concatenated one after the other.
//
ptrData = data;
for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
{
for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
{
ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
*out = 0;
for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
{
*out += ptrData[colCntr] * ptrRow[colCntr];
}
out++;
}
ptrData += UB_LPC_ORDER;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_DecorrelateInterVec()
*
* Remover the correlation among mean-removed LAR vectors. If LAR vectors
* of one frame are put in a matrix where each column is a LAR vector of a
* sub-frame, then this is equivalent to multiplying the LAR matrix with
* a decorrelting mtrix from right.
*
* Input:
* -data : pointer to matrix of LAR vectors. The matrix
* is stored column-wise.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : decorrelated LAR vectors.
*/
int16_t
WebRtcIsac_DecorrelateInterVec(
const double* data,
double* out,
int16_t bandwidth)
{
int16_t coeffCntr;
int16_t rowCntr;
int16_t colCntr;
const double* decorrMat;
int16_t interVecDim;
switch(bandwidth)
{
case isac12kHz:
{
decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
interVecDim = UB_LPC_VEC_PER_FRAME;
break;
}
case isac16kHz:
{
decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
interVecDim = UB16_LPC_VEC_PER_FRAME;
break;
}
default:
return -1;
}
//
// data * decorrMat
//
// data is of size 'interVecDim' * 'UB_LPC_ORDER'
// That is 'interVecDim' of LAR vectors (mean removed)
// in columns each of dimension 'UB_LPC_ORDER'.
// matrix is stored column-wise.
//
for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
{
for(colCntr = 0; colCntr < interVecDim; colCntr++)
{
out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
{
out[coeffCntr + colCntr * UB_LPC_ORDER] +=
data[coeffCntr + rowCntr * UB_LPC_ORDER] *
decorrMat[rowCntr * interVecDim + colCntr];
}
}
}
return 0;
}
/******************************************************************************
* WebRtcIsac_QuantizeUncorrLar()
*
* Quantize the uncorrelated parameters.
*
* Input:
* -data : uncorrelated LAR vectors.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -data : quantized version of the input.
* -idx : pointer to quantization indices.
*/
double
WebRtcIsac_QuantizeUncorrLar(
double* data,
int* recIdx,
int16_t bandwidth)
{
int16_t cntr;
int32_t idx;
int16_t interVecDim;
const double* leftRecPoint;
double quantizationStepSize;
const int16_t* numQuantCell;
switch(bandwidth)
{
case isac12kHz:
{
leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12;
interVecDim = UB_LPC_VEC_PER_FRAME;
break;
}
case isac16kHz:
{
leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16;
interVecDim = UB16_LPC_VEC_PER_FRAME;
break;
}
default:
return -1;
}
//
// Quantize the parametrs.
//
for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
{
idx = (int32_t)floor((*data - leftRecPoint[cntr]) /
quantizationStepSize + 0.5);
if(idx < 0)
{
idx = 0;
}
else if(idx >= numQuantCell[cntr])
{
idx = numQuantCell[cntr] - 1;
}
*data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
*recIdx++ = idx;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_DequantizeLpcParam()
*
* Get the quantized value of uncorrelated LARs given the quantization indices.
*
* Input:
* -idx : pointer to quantiztion indices.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : pointer to quantized values.
*/
int16_t
WebRtcIsac_DequantizeLpcParam(
const int* idx,
double* out,
int16_t bandwidth)
{
int16_t cntr;
int16_t interVecDim;
const double* leftRecPoint;
double quantizationStepSize;
switch(bandwidth)
{
case isac12kHz:
{
leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
interVecDim = UB_LPC_VEC_PER_FRAME;
break;
}
case isac16kHz:
{
leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
interVecDim = UB16_LPC_VEC_PER_FRAME;
break;
}
default:
return -1;
}
//
// Dequantize given the quantization indices
//
for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
{
*out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_CorrelateIntraVec()
*
* This is the inverse of WebRtcIsac_DecorrelateIntraVec().
*
* Input:
* -data : uncorrelated parameters.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : correlated parametrs.
*/
int16_t
WebRtcIsac_CorrelateIntraVec(
const double* data,
double* out,
int16_t bandwidth)
{
int16_t vecCntr;
int16_t rowCntr;
int16_t colCntr;
int16_t numVec;
const double* ptrData;
const double* intraVecDecorrMat;
switch(bandwidth)
{
case isac12kHz:
{
numVec = UB_LPC_VEC_PER_FRAME;
intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
break;
}
case isac16kHz:
{
numVec = UB16_LPC_VEC_PER_FRAME;
intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
break;
}
default:
return -1;
}
ptrData = data;
for(vecCntr = 0; vecCntr < numVec; vecCntr++)
{
for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
{
*out = 0;
for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
{
*out += ptrData[rowCntr] *
intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
}
out++;
}
ptrData += UB_LPC_ORDER;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_CorrelateInterVec()
*
* This is the inverse of WebRtcIsac_DecorrelateInterVec().
*
* Input:
* -data
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : correlated parametrs.
*/
int16_t
WebRtcIsac_CorrelateInterVec(
const double* data,
double* out,
int16_t bandwidth)
{
int16_t coeffCntr;
int16_t rowCntr;
int16_t colCntr;
int16_t interVecDim;
double myVec[UB16_LPC_VEC_PER_FRAME];
const double* interVecDecorrMat;
switch(bandwidth)
{
case isac12kHz:
{
interVecDim = UB_LPC_VEC_PER_FRAME;
interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
break;
}
case isac16kHz:
{
interVecDim = UB16_LPC_VEC_PER_FRAME;
interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
break;
}
default:
return -1;
}
for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
{
for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
{
myVec[rowCntr] = 0;
for(colCntr = 0; colCntr < interVecDim; colCntr++)
{
myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
interVecDecorrMat[rowCntr * interVecDim + colCntr];
//ptrData += UB_LPC_ORDER;
}
}
for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
{
out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
}
}
return 0;
}
/******************************************************************************
* WebRtcIsac_AddLarMean()
*
* This is the inverse of WebRtcIsac_RemoveLarMean()
*
* Input:
* -data : pointer to mean-removed LAR:s.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -data : pointer to LARs.
*/
int16_t
WebRtcIsac_AddLarMean(
double* data,
int16_t bandwidth)
{
int16_t coeffCntr;
int16_t vecCntr;
int16_t numVec;
const double* meanLAR;
switch(bandwidth)
{
case isac12kHz:
{
numVec = UB_LPC_VEC_PER_FRAME;
meanLAR = WebRtcIsac_kMeanLarUb12;
break;
}
case isac16kHz:
{
numVec = UB16_LPC_VEC_PER_FRAME;
meanLAR = WebRtcIsac_kMeanLarUb16;
break;
}
default:
return -1;
}
for(vecCntr = 0; vecCntr < numVec; vecCntr++)
{
for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
{
*data++ += meanLAR[coeffCntr];
}
}
return 0;
}
/******************************************************************************
* WebRtcIsac_ToLogDomainRemoveMean()
*
* Transform the LPC gain to log domain then remove the mean value.
*
* Input:
* -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
*
* Output:
* -lpcGain : mean-removed in log domain.
*/
int16_t
WebRtcIsac_ToLogDomainRemoveMean(
double* data)
{
int16_t coeffCntr;
for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
{
data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_DecorrelateLPGain()
*
* Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
* multiplying gain vector with decorrelating matrix.
*
* Input:
* -data : LPC gain in log-domain with mean removed.
*
* Output:
* -out : decorrelated parameters.
*/
int16_t WebRtcIsac_DecorrelateLPGain(
const double* data,
double* out)
{
int16_t rowCntr;
int16_t colCntr;
for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
{
*out = 0;
for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
{
*out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
}
out++;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_QuantizeLpcGain()
*
* Quantize the decorrelated log-domain gains.
*
* Input:
* -lpcGain : uncorrelated LPC gains.
*
* Output:
* -idx : quantization indices
* -lpcGain : quantized value of the inpt.
*/
double WebRtcIsac_QuantizeLpcGain(
double* data,
int* idx)
{
int16_t coeffCntr;
for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
{
*idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
WebRtcIsac_kQSizeLpcGain + 0.5);
if(*idx < 0)
{
*idx = 0;
}
else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
{
*idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
}
*data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
WebRtcIsac_kQSizeLpcGain;
data++;
idx++;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_DequantizeLpcGain()
*
* Get the quantized values given the quantization indices.
*
* Input:
* -idx : pointer to quantization indices.
*
* Output:
* -lpcGains : quantized values of the given parametes.
*/
int16_t WebRtcIsac_DequantizeLpcGain(
const int* idx,
double* out)
{
int16_t coeffCntr;
for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
{
*out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
WebRtcIsac_kQSizeLpcGain;
out++;
idx++;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_CorrelateLpcGain()
*
* This is the inverse of WebRtcIsac_DecorrelateLPGain().
*
* Input:
* -data : decorrelated parameters.
*
* Output:
* -out : correlated parameters.
*/
int16_t WebRtcIsac_CorrelateLpcGain(
const double* data,
double* out)
{
int16_t rowCntr;
int16_t colCntr;
for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
{
*out = 0;
for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
{
*out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
}
out++;
}
return 0;
}
/******************************************************************************
* WebRtcIsac_AddMeanToLinearDomain()
*
* This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
*
* Input:
* -lpcGain : LPC gain in log-domain & mean removed
*
* Output:
* -lpcGain : LPC gain in normal domain.
*/
int16_t WebRtcIsac_AddMeanToLinearDomain(
double* lpcGains)
{
int16_t coeffCntr;
for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
{
lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
}
return 0;
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* encode_lpc_swb.h
*
* This file contains declaration of functions used to
* encode LPC parameters (Shape & gain) of the upper band.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
#include "typedefs.h"
#include "settings.h"
#include "structs.h"
/******************************************************************************
* WebRtcIsac_RemoveLarMean()
*
* Remove the means from LAR coefficients.
*
* Input:
* -lar : pointer to lar vectors. LAR vectors are
* concatenated.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -lar : pointer to mean-removed LAR:s.
*
*
*/
int16_t WebRtcIsac_RemoveLarMean(
double* lar,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_DecorrelateIntraVec()
*
* Remove the correlation amonge the components of LAR vectors. If LAR vectors
* of one frame are put in a matrix where each column is a LAR vector of a
* sub-frame, then this is equivalent to multiplying the LAR matrix with
* a decorrelting mtrix from left.
*
* Input:
* -inLar : pointer to mean-removed LAR vecrtors.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : decorrelated LAR vectors.
*/
int16_t WebRtcIsac_DecorrelateIntraVec(
const double* inLAR,
double* out,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_DecorrelateInterVec()
*
* Remover the correlation among mean-removed LAR vectors. If LAR vectors
* of one frame are put in a matrix where each column is a LAR vector of a
* sub-frame, then this is equivalent to multiplying the LAR matrix with
* a decorrelting mtrix from right.
*
* Input:
* -data : pointer to matrix of LAR vectors. The matrix
* is stored column-wise.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : decorrelated LAR vectors.
*/
int16_t WebRtcIsac_DecorrelateInterVec(
const double* data,
double* out,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_QuantizeUncorrLar()
*
* Quantize the uncorrelated parameters.
*
* Input:
* -data : uncorrelated LAR vectors.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -data : quantized version of the input.
* -idx : pointer to quantization indices.
*/
double WebRtcIsac_QuantizeUncorrLar(
double* data,
int* idx,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_CorrelateIntraVec()
*
* This is the inverse of WebRtcIsac_DecorrelateIntraVec().
*
* Input:
* -data : uncorrelated parameters.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : correlated parametrs.
*/
int16_t WebRtcIsac_CorrelateIntraVec(
const double* data,
double* out,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_CorrelateInterVec()
*
* This is the inverse of WebRtcIsac_DecorrelateInterVec().
*
* Input:
* -data
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : correlated parametrs.
*/
int16_t WebRtcIsac_CorrelateInterVec(
const double* data,
double* out,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_AddLarMean()
*
* This is the inverse of WebRtcIsac_RemoveLarMean()
*
* Input:
* -data : pointer to mean-removed LAR:s.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -data : pointer to LARs.
*/
int16_t WebRtcIsac_AddLarMean(
double* data,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_DequantizeLpcParam()
*
* Get the quantized value of uncorrelated LARs given the quantization indices.
*
* Input:
* -idx : pointer to quantiztion indices.
* -bandwidth : indicates if the given LAR vectors belong
* to SWB-12kHz or SWB-16kHz.
*
* Output:
* -out : pointer to quantized values.
*/
int16_t WebRtcIsac_DequantizeLpcParam(
const int* idx,
double* out,
int16_t bandwidth);
/******************************************************************************
* WebRtcIsac_ToLogDomainRemoveMean()
*
* Transform the LPC gain to log domain then remove the mean value.
*
* Input:
* -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
*
* Output:
* -lpcGain : mean-removed in log domain.
*/
int16_t WebRtcIsac_ToLogDomainRemoveMean(
double* lpGains);
/******************************************************************************
* WebRtcIsac_DecorrelateLPGain()
*
* Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
* multiplying gain vector with decorrelating matrix.
*
* Input:
* -data : LPC gain in log-domain with mean removed.
*
* Output:
* -out : decorrelated parameters.
*/
int16_t WebRtcIsac_DecorrelateLPGain(
const double* data,
double* out);
/******************************************************************************
* WebRtcIsac_QuantizeLpcGain()
*
* Quantize the decorrelated log-domain gains.
*
* Input:
* -lpcGain : uncorrelated LPC gains.
*
* Output:
* -idx : quantization indices
* -lpcGain : quantized value of the inpt.
*/
double WebRtcIsac_QuantizeLpcGain(
double* lpGains,
int* idx);
/******************************************************************************
* WebRtcIsac_DequantizeLpcGain()
*
* Get the quantized values given the quantization indices.
*
* Input:
* -idx : pointer to quantization indices.
*
* Output:
* -lpcGains : quantized values of the given parametes.
*/
int16_t WebRtcIsac_DequantizeLpcGain(
const int* idx,
double* lpGains);
/******************************************************************************
* WebRtcIsac_CorrelateLpcGain()
*
* This is the inverse of WebRtcIsac_DecorrelateLPGain().
*
* Input:
* -data : decorrelated parameters.
*
* Output:
* -out : correlated parameters.
*/
int16_t WebRtcIsac_CorrelateLpcGain(
const double* data,
double* out);
/******************************************************************************
* WebRtcIsac_AddMeanToLinearDomain()
*
* This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
*
* Input:
* -lpcGain : LPC gain in log-domain & mean removed
*
* Output:
* -lpcGain : LPC gain in normal domain.
*/
int16_t WebRtcIsac_AddMeanToLinearDomain(
double* lpcGains);
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_

Some files were not shown because too many files have changed in this diff Show More