mirror of https://github.com/DrBeef/ioq3quest.git
Add libopus 1.0.2 and libopusfile 0.2
This commit is contained in:
parent
3dd5c5d862
commit
6d56d8bb33
|
@ -0,0 +1,175 @@
|
|||
/*Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
#ifndef KISS_FFT_GUTS_H
|
||||
#define KISS_FFT_GUTS_H
|
||||
|
||||
#define MIN(a,b) ((a)<(b) ? (a):(b))
|
||||
#define MAX(a,b) ((a)>(b) ? (a):(b))
|
||||
|
||||
/* kiss_fft.h
|
||||
defines kiss_fft_scalar as either short or a float type
|
||||
and defines
|
||||
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||
#include "kiss_fft.h"
|
||||
|
||||
/*
|
||||
Explanation of macros dealing with complex math:
|
||||
|
||||
C_MUL(m,a,b) : m = a*b
|
||||
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||
C_SUB( res, a,b) : res = a - b
|
||||
C_SUBFROM( res , a) : res -= a
|
||||
C_ADDTO( res , a) : res += a
|
||||
* */
|
||||
#ifdef FIXED_POINT
|
||||
#include "arch.h"
|
||||
|
||||
|
||||
#define SAMP_MAX 2147483647
|
||||
#define TWID_MAX 32767
|
||||
#define TRIG_UPSCALE 1
|
||||
|
||||
#define SAMP_MIN -SAMP_MAX
|
||||
|
||||
|
||||
# define S_MUL(a,b) MULT16_32_Q15(b, a)
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
|
||||
|
||||
# define C_MULC(m,a,b) \
|
||||
do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
|
||||
|
||||
# define C_MUL4(m,a,b) \
|
||||
do{ (m).r = SHR32(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \
|
||||
(m).i = SHR32(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }while(0)
|
||||
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r = S_MUL( (c).r , s ) ;\
|
||||
(c).i = S_MUL( (c).i , s ) ; }while(0)
|
||||
|
||||
# define DIVSCALAR(x,k) \
|
||||
(x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 )
|
||||
|
||||
# define C_FIXDIV(c,div) \
|
||||
do { DIVSCALAR( (c).r , div); \
|
||||
DIVSCALAR( (c).i , div); }while (0)
|
||||
|
||||
#define C_ADD( res, a,b)\
|
||||
do {(res).r=ADD32((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \
|
||||
}while(0)
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) )
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||
#define C_MULC(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
|
||||
(m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
|
||||
|
||||
#define C_MUL4(m,a,b) C_MUL(m,a,b)
|
||||
|
||||
# define C_FIXDIV(c,div) /* NOOP */
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r *= (s);\
|
||||
(c).i *= (s); }while(0)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK_OVERFLOW_OP
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||
#endif
|
||||
|
||||
#ifndef C_ADD
|
||||
#define C_ADD( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||
(res).r += (a).r; (res).i += (a).i;\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {\
|
||||
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||
(res).r -= (a).r; (res).i -= (a).i; \
|
||||
}while(0)
|
||||
#endif /* C_ADD defined */
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
/*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
|
||||
# define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
|
||||
# define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase))
|
||||
# define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase))
|
||||
# define HALF_OF(x) ((x)>>1)
|
||||
#elif defined(USE_SIMD)
|
||||
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
|
||||
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
|
||||
# define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
|
||||
#else
|
||||
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
|
||||
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
|
||||
# define HALF_OF(x) ((x)*.5f)
|
||||
#endif
|
||||
|
||||
#define kf_cexp(x,phase) \
|
||||
do{ \
|
||||
(x)->r = KISS_FFT_COS(phase);\
|
||||
(x)->i = KISS_FFT_SIN(phase);\
|
||||
}while(0)
|
||||
|
||||
#define kf_cexp2(x,phase) \
|
||||
do{ \
|
||||
(x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
|
||||
(x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
|
||||
}while(0)
|
||||
|
||||
#endif /* KISS_FFT_GUTS_H */
|
|
@ -0,0 +1,209 @@
|
|||
/* Copyright (c) 2003-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file arch.h
|
||||
@brief Various architecture definitions for CELT
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include "opus_types.h"
|
||||
|
||||
# if !defined(__GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define __GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define __GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#define CELT_SIG_SCALE 32768.f
|
||||
|
||||
#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
|
||||
#ifdef ENABLE_ASSERTIONS
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
static inline void _celt_fatal(const char *str, const char *file, int line)
|
||||
{
|
||||
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
|
||||
abort();
|
||||
}
|
||||
#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}}
|
||||
#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}}
|
||||
#else
|
||||
#define celt_assert(cond)
|
||||
#define celt_assert2(cond, message)
|
||||
#endif
|
||||
|
||||
#define IMUL32(a,b) ((a)*(b))
|
||||
|
||||
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
|
||||
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */
|
||||
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */
|
||||
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
|
||||
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */
|
||||
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */
|
||||
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
|
||||
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
|
||||
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
|
||||
#define UADD32(a,b) ((a)+(b))
|
||||
#define USUB32(a,b) ((a)-(b))
|
||||
|
||||
#define PRINT_MIPS(file)
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
typedef opus_int16 opus_val16;
|
||||
typedef opus_int32 opus_val32;
|
||||
|
||||
typedef opus_val32 celt_sig;
|
||||
typedef opus_val16 celt_norm;
|
||||
typedef opus_val32 celt_ener;
|
||||
|
||||
#define Q15ONE 32767
|
||||
|
||||
#define SIG_SHIFT 12
|
||||
|
||||
#define NORM_SCALING 16384
|
||||
|
||||
#define DB_SHIFT 10
|
||||
|
||||
#define EPSILON 1
|
||||
#define VERY_LARGE16 ((opus_val16)32767)
|
||||
#define Q15_ONE ((opus_val16)32767)
|
||||
|
||||
#define SCALEIN(a) (a)
|
||||
#define SCALEOUT(a) (a)
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
#include "fixed_debug.h"
|
||||
#else
|
||||
|
||||
#include "fixed_generic.h"
|
||||
|
||||
#ifdef ARM5E_ASM
|
||||
#include "fixed_arm5e.h"
|
||||
#elif defined (ARM4_ASM)
|
||||
#include "fixed_arm4.h"
|
||||
#elif defined (BFIN_ASM)
|
||||
#include "fixed_bfin.h"
|
||||
#elif defined (TI_C5X_ASM)
|
||||
#include "fixed_c5x.h"
|
||||
#elif defined (TI_C6X_ASM)
|
||||
#include "fixed_c6x.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#else /* FIXED_POINT */
|
||||
|
||||
typedef float opus_val16;
|
||||
typedef float opus_val32;
|
||||
|
||||
typedef float celt_sig;
|
||||
typedef float celt_norm;
|
||||
typedef float celt_ener;
|
||||
|
||||
#define Q15ONE 1.0f
|
||||
|
||||
#define NORM_SCALING 1.f
|
||||
|
||||
#define EPSILON 1e-15f
|
||||
#define VERY_LARGE16 1e15f
|
||||
#define Q15_ONE ((opus_val16)1.f)
|
||||
|
||||
#define QCONST16(x,bits) (x)
|
||||
#define QCONST32(x,bits) (x)
|
||||
|
||||
#define NEG16(x) (-(x))
|
||||
#define NEG32(x) (-(x))
|
||||
#define EXTRACT16(x) (x)
|
||||
#define EXTEND32(x) (x)
|
||||
#define SHR16(a,shift) (a)
|
||||
#define SHL16(a,shift) (a)
|
||||
#define SHR32(a,shift) (a)
|
||||
#define SHL32(a,shift) (a)
|
||||
#define PSHR32(a,shift) (a)
|
||||
#define VSHR32(a,shift) (a)
|
||||
|
||||
#define PSHR(a,shift) (a)
|
||||
#define SHR(a,shift) (a)
|
||||
#define SHL(a,shift) (a)
|
||||
#define SATURATE(x,a) (x)
|
||||
|
||||
#define ROUND16(a,shift) (a)
|
||||
#define HALF16(x) (.5f*(x))
|
||||
#define HALF32(x) (.5f*(x))
|
||||
|
||||
#define ADD16(a,b) ((a)+(b))
|
||||
#define SUB16(a,b) ((a)-(b))
|
||||
#define ADD32(a,b) ((a)+(b))
|
||||
#define SUB32(a,b) ((a)-(b))
|
||||
#define MULT16_16_16(a,b) ((a)*(b))
|
||||
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
|
||||
#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
|
||||
|
||||
#define MULT16_32_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q16(a,b) ((a)*(b))
|
||||
|
||||
#define MULT32_32_Q31(a,b) ((a)*(b))
|
||||
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MULT16_16_Q11_32(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q13(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q14(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_16_P15(a,b) ((a)*(b))
|
||||
#define MULT16_16_P13(a,b) ((a)*(b))
|
||||
#define MULT16_16_P14(a,b) ((a)*(b))
|
||||
#define MULT16_32_P16(a,b) ((a)*(b))
|
||||
|
||||
#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b))
|
||||
#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b))
|
||||
|
||||
#define SCALEIN(a) ((a)*CELT_SIG_SCALE)
|
||||
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE))
|
||||
|
||||
#endif /* !FIXED_POINT */
|
||||
|
||||
#ifndef GLOBAL_STACK_SIZE
|
||||
#ifdef FIXED_POINT
|
||||
#define GLOBAL_STACK_SIZE 100000
|
||||
#else
|
||||
#define GLOBAL_STACK_SIZE 100000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,95 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008-2009 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BANDS_H
|
||||
#define BANDS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "modes.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "rate.h"
|
||||
|
||||
/** Compute the amplitude (sqrt energy) in each of the bands
|
||||
* @param m Mode data
|
||||
* @param X Spectrum
|
||||
* @param bands Square root of the energy for each band (returned)
|
||||
*/
|
||||
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int M);
|
||||
|
||||
/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
|
||||
|
||||
/** Normalise each band of X such that the energy in each band is
|
||||
equal to 1
|
||||
* @param m Mode data
|
||||
* @param X Spectrum (returned normalised)
|
||||
* @param bands Square root of the energy for each band
|
||||
*/
|
||||
void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
|
||||
|
||||
/** Denormalise each band of X to restore full amplitude
|
||||
* @param m Mode data
|
||||
* @param X Spectrum (returned de-normalised)
|
||||
* @param bands Square root of the energy for each band
|
||||
*/
|
||||
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, celt_sig * OPUS_RESTRICT freq, const celt_ener *bandE, int end, int C, int M);
|
||||
|
||||
#define SPREAD_NONE (0)
|
||||
#define SPREAD_LIGHT (1)
|
||||
#define SPREAD_NORMAL (2)
|
||||
#define SPREAD_AGGRESSIVE (3)
|
||||
|
||||
int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
|
||||
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
|
||||
int end, int C, int M);
|
||||
|
||||
#ifdef MEASURE_NORM_MSE
|
||||
void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
|
||||
#endif
|
||||
|
||||
void haar1(celt_norm *X, int N0, int stride);
|
||||
|
||||
/** Quantisation/encoding of the residual spectrum
|
||||
* @param m Mode data
|
||||
* @param X Residual (normalised)
|
||||
* @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
|
||||
* @param enc Entropy encoder
|
||||
*/
|
||||
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
|
||||
celt_norm * X, celt_norm * Y, unsigned char *collapse_masks, const celt_ener *bandE, int *pulses,
|
||||
int time_domain, int fold, int dual_stereo, int intensity, int *tf_res,
|
||||
opus_int32 total_bits, opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed);
|
||||
|
||||
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
|
||||
int start, int end, opus_val16 *logE, opus_val16 *prev1logE,
|
||||
opus_val16 *prev2logE, int *pulses, opus_uint32 seed);
|
||||
|
||||
opus_uint32 celt_lcg_rand(opus_uint32 seed);
|
||||
|
||||
#endif /* BANDS_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,117 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/**
|
||||
@file celt.h
|
||||
@brief Contains all the functions for encoding and decoding audio
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CELT_H
|
||||
#define CELT_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
#include "opus_custom.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "arch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CELTEncoder OpusCustomEncoder
|
||||
#define CELTDecoder OpusCustomDecoder
|
||||
#define CELTMode OpusCustomMode
|
||||
|
||||
#define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
|
||||
|
||||
/* Encoder/decoder Requests */
|
||||
|
||||
#define CELT_SET_PREDICTION_REQUEST 10002
|
||||
/** Controls the use of interframe prediction.
|
||||
0=Independent frames
|
||||
1=Short term interframe prediction allowed
|
||||
2=Long term prediction allowed
|
||||
*/
|
||||
#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_INPUT_CLIPPING_REQUEST 10004
|
||||
#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_GET_AND_CLEAR_ERROR_REQUEST 10007
|
||||
#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
#define CELT_SET_CHANNELS_REQUEST 10008
|
||||
#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, __opus_check_int(x)
|
||||
|
||||
|
||||
/* Internal */
|
||||
#define CELT_SET_START_BAND_REQUEST 10010
|
||||
#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_END_BAND_REQUEST 10012
|
||||
#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_GET_MODE_REQUEST 10015
|
||||
/** Get the CELTMode used by an encoder or decoder */
|
||||
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, _celt_check_mode_ptr_ptr(x)
|
||||
|
||||
#define CELT_SET_SIGNALLING_REQUEST 10016
|
||||
#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x)
|
||||
|
||||
|
||||
|
||||
/* Encoder stuff */
|
||||
|
||||
int celt_encoder_get_size(int channels);
|
||||
|
||||
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
|
||||
|
||||
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels);
|
||||
|
||||
|
||||
|
||||
/* Decoder stuff */
|
||||
|
||||
int celt_decoder_get_size(int channels);
|
||||
|
||||
|
||||
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
|
||||
|
||||
int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec);
|
||||
|
||||
#define celt_encoder_ctl opus_custom_encoder_ctl
|
||||
#define celt_decoder_ctl opus_custom_decoder_ctl
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CELT_H */
|
|
@ -0,0 +1,188 @@
|
|||
/* Copyright (c) 2009-2010 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt_lpc.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
|
||||
void _celt_lpc(
|
||||
opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
|
||||
const opus_val32 *ac, /* in: [0...p] autocorrelation values */
|
||||
int p
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
opus_val32 r;
|
||||
opus_val32 error = ac[0];
|
||||
#ifdef FIXED_POINT
|
||||
opus_val32 lpc[LPC_ORDER];
|
||||
#else
|
||||
float *lpc = _lpc;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < p; i++)
|
||||
lpc[i] = 0;
|
||||
if (ac[0] != 0)
|
||||
{
|
||||
for (i = 0; i < p; i++) {
|
||||
/* Sum up this iteration's reflection coefficient */
|
||||
opus_val32 rr = 0;
|
||||
for (j = 0; j < i; j++)
|
||||
rr += MULT32_32_Q31(lpc[j],ac[i - j]);
|
||||
rr += SHR32(ac[i + 1],3);
|
||||
r = -frac_div32(SHL32(rr,3), error);
|
||||
/* Update LPC coefficients and total error */
|
||||
lpc[i] = SHR32(r,3);
|
||||
for (j = 0; j < (i+1)>>1; j++)
|
||||
{
|
||||
opus_val32 tmp1, tmp2;
|
||||
tmp1 = lpc[j];
|
||||
tmp2 = lpc[i-1-j];
|
||||
lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
|
||||
lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
|
||||
}
|
||||
|
||||
error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
|
||||
/* Bail out once we get 30 dB gain */
|
||||
#ifdef FIXED_POINT
|
||||
if (error<SHR32(ac[0],10))
|
||||
break;
|
||||
#else
|
||||
if (error<.001f*ac[0])
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
for (i=0;i<p;i++)
|
||||
_lpc[i] = ROUND16(lpc[i],16);
|
||||
#endif
|
||||
}
|
||||
|
||||
void celt_fir(const opus_val16 *x,
|
||||
const opus_val16 *num,
|
||||
opus_val16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
|
||||
for (j=0;j<ord;j++)
|
||||
{
|
||||
sum += MULT16_16(num[j],mem[j]);
|
||||
}
|
||||
for (j=ord-1;j>=1;j--)
|
||||
{
|
||||
mem[j]=mem[j-1];
|
||||
}
|
||||
mem[0] = x[i];
|
||||
y[i] = ROUND16(sum, SIG_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
void celt_iir(const opus_val32 *x,
|
||||
const opus_val16 *den,
|
||||
opus_val32 *y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
opus_val32 sum = x[i];
|
||||
for (j=0;j<ord;j++)
|
||||
{
|
||||
sum -= MULT16_16(den[j],mem[j]);
|
||||
}
|
||||
for (j=ord-1;j>=1;j--)
|
||||
{
|
||||
mem[j]=mem[j-1];
|
||||
}
|
||||
mem[0] = ROUND16(sum,SIG_SHIFT);
|
||||
y[i] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
void _celt_autocorr(
|
||||
const opus_val16 *x, /* in: [0...n-1] samples x */
|
||||
opus_val32 *ac, /* out: [0...lag-1] ac values */
|
||||
const opus_val16 *window,
|
||||
int overlap,
|
||||
int lag,
|
||||
int n
|
||||
)
|
||||
{
|
||||
opus_val32 d;
|
||||
int i;
|
||||
VARDECL(opus_val16, xx);
|
||||
SAVE_STACK;
|
||||
ALLOC(xx, n, opus_val16);
|
||||
celt_assert(n>0);
|
||||
celt_assert(overlap>=0);
|
||||
for (i=0;i<n;i++)
|
||||
xx[i] = x[i];
|
||||
for (i=0;i<overlap;i++)
|
||||
{
|
||||
xx[i] = MULT16_16_Q15(x[i],window[i]);
|
||||
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
opus_val32 ac0=0;
|
||||
int shift;
|
||||
for(i=0;i<n;i++)
|
||||
ac0 += SHR32(MULT16_16(xx[i],xx[i]),9);
|
||||
ac0 += 1+n;
|
||||
|
||||
shift = celt_ilog2(ac0)-30+10;
|
||||
shift = (shift+1)/2;
|
||||
for(i=0;i<n;i++)
|
||||
xx[i] = VSHR32(xx[i], shift);
|
||||
}
|
||||
#endif
|
||||
while (lag>=0)
|
||||
{
|
||||
for (i = lag, d = 0; i < n; i++)
|
||||
d += xx[i] * xx[i-lag];
|
||||
ac[lag] = d;
|
||||
/*printf ("%f ", ac[lag]);*/
|
||||
lag--;
|
||||
}
|
||||
/*printf ("\n");*/
|
||||
ac[0] += 10;
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* Copyright (c) 2009-2010 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLC_H
|
||||
#define PLC_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#define LPC_ORDER 24
|
||||
|
||||
void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
|
||||
|
||||
void celt_fir(const opus_val16 *x,
|
||||
const opus_val16 *num,
|
||||
opus_val16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem);
|
||||
|
||||
void celt_iir(const opus_val32 *x,
|
||||
const opus_val16 *den,
|
||||
opus_val32 *y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem);
|
||||
|
||||
void _celt_autocorr(const opus_val16 *x, opus_val32 *ac, const opus_val16 *window, int overlap, int lag, int n);
|
||||
|
||||
#endif /* PLC_H */
|
|
@ -0,0 +1,645 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2007-2009 Timothy B. Terriberry
|
||||
Written by Timothy B. Terriberry and Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "os_support.h"
|
||||
#include "cwrs.h"
|
||||
#include "mathops.h"
|
||||
#include "arch.h"
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
/*Guaranteed to return a conservatively large estimate of the binary logarithm
|
||||
with frac bits of fractional precision.
|
||||
Tested for all possible 32-bit inputs with frac=4, where the maximum
|
||||
overestimation is 0.06254243 bits.*/
|
||||
int log2_frac(opus_uint32 val, int frac)
|
||||
{
|
||||
int l;
|
||||
l=EC_ILOG(val);
|
||||
if(val&(val-1)){
|
||||
/*This is (val>>l-16), but guaranteed to round up, even if adding a bias
|
||||
before the shift would cause overflow (e.g., for 0xFFFFxxxx).
|
||||
Doesn't work for val=0, but that case fails the test above.*/
|
||||
if(l>16)val=((val-1)>>(l-16))+1;
|
||||
else val<<=16-l;
|
||||
l=(l-1)<<frac;
|
||||
/*Note that we always need one iteration, since the rounding up above means
|
||||
that we might need to adjust the integer part of the logarithm.*/
|
||||
do{
|
||||
int b;
|
||||
b=(int)(val>>16);
|
||||
l+=b<<frac;
|
||||
val=(val+b)>>b;
|
||||
val=(val*val+0x7FFF)>>15;
|
||||
}
|
||||
while(frac-->0);
|
||||
/*If val is not exactly 0x8000, then we have to round up the remainder.*/
|
||||
return l+(val>0x8000);
|
||||
}
|
||||
/*Exact powers of two require no rounding.*/
|
||||
else return (l-1)<<frac;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
#define MASK32 (0xFFFFFFFF)
|
||||
|
||||
/*INV_TABLE[i] holds the multiplicative inverse of (2*i+1) mod 2**32.*/
|
||||
static const opus_uint32 INV_TABLE[53]={
|
||||
0x00000001,0xAAAAAAAB,0xCCCCCCCD,0xB6DB6DB7,
|
||||
0x38E38E39,0xBA2E8BA3,0xC4EC4EC5,0xEEEEEEEF,
|
||||
0xF0F0F0F1,0x286BCA1B,0x3CF3CF3D,0xE9BD37A7,
|
||||
0xC28F5C29,0x684BDA13,0x4F72C235,0xBDEF7BDF,
|
||||
0x3E0F83E1,0x8AF8AF8B,0x914C1BAD,0x96F96F97,
|
||||
0xC18F9C19,0x2FA0BE83,0xA4FA4FA5,0x677D46CF,
|
||||
0x1A1F58D1,0xFAFAFAFB,0x8C13521D,0x586FB587,
|
||||
0xB823EE09,0xA08AD8F3,0xC10C9715,0xBEFBEFBF,
|
||||
0xC0FC0FC1,0x07A44C6B,0xA33F128D,0xE327A977,
|
||||
0xC7E3F1F9,0x962FC963,0x3F2B3885,0x613716AF,
|
||||
0x781948B1,0x2B2E43DB,0xFCFCFCFD,0x6FD0EB67,
|
||||
0xFA3F47E9,0xD2FD2FD3,0x3F4FD3F5,0xD4E25B9F,
|
||||
0x5F02A3A1,0xBF5A814B,0x7C32B16D,0xD3431B57,
|
||||
0xD8FD8FD9,
|
||||
};
|
||||
|
||||
/*Computes (_a*_b-_c)/(2*_d+1) when the quotient is known to be exact.
|
||||
_a, _b, _c, and _d may be arbitrary so long as the arbitrary precision result
|
||||
fits in 32 bits, but currently the table for multiplicative inverses is only
|
||||
valid for _d<=52.*/
|
||||
static inline opus_uint32 imusdiv32odd(opus_uint32 _a,opus_uint32 _b,
|
||||
opus_uint32 _c,int _d){
|
||||
celt_assert(_d<=52);
|
||||
return (_a*_b-_c)*INV_TABLE[_d]&MASK32;
|
||||
}
|
||||
|
||||
/*Computes (_a*_b-_c)/_d when the quotient is known to be exact.
|
||||
_d does not actually have to be even, but imusdiv32odd will be faster when
|
||||
it's odd, so you should use that instead.
|
||||
_a and _d are assumed to be small (e.g., _a*_d fits in 32 bits; currently the
|
||||
table for multiplicative inverses is only valid for _d<=54).
|
||||
_b and _c may be arbitrary so long as the arbitrary precision reuslt fits in
|
||||
32 bits.*/
|
||||
static inline opus_uint32 imusdiv32even(opus_uint32 _a,opus_uint32 _b,
|
||||
opus_uint32 _c,int _d){
|
||||
opus_uint32 inv;
|
||||
int mask;
|
||||
int shift;
|
||||
int one;
|
||||
celt_assert(_d>0);
|
||||
celt_assert(_d<=54);
|
||||
shift=EC_ILOG(_d^(_d-1));
|
||||
inv=INV_TABLE[(_d-1)>>shift];
|
||||
shift--;
|
||||
one=1<<shift;
|
||||
mask=one-1;
|
||||
return (_a*(_b>>shift)-(_c>>shift)+
|
||||
((_a*(_b&mask)+one-(_c&mask))>>shift)-1)*inv&MASK32;
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*Although derived separately, the pulse vector coding scheme is equivalent to
|
||||
a Pyramid Vector Quantizer \cite{Fis86}.
|
||||
Some additional notes about an early version appear at
|
||||
http://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
|
||||
and the definitions of some terms have evolved since that was written.
|
||||
|
||||
The conversion from a pulse vector to an integer index (encoding) and back
|
||||
(decoding) is governed by two related functions, V(N,K) and U(N,K).
|
||||
|
||||
V(N,K) = the number of combinations, with replacement, of N items, taken K
|
||||
at a time, when a sign bit is added to each item taken at least once (i.e.,
|
||||
the number of N-dimensional unit pulse vectors with K pulses).
|
||||
One way to compute this is via
|
||||
V(N,K) = K>0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1,
|
||||
where choose() is the binomial function.
|
||||
A table of values for N<10 and K<10 looks like:
|
||||
V[10][10] = {
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{1, 2, 2, 2, 2, 2, 2, 2, 2, 2},
|
||||
{1, 4, 8, 12, 16, 20, 24, 28, 32, 36},
|
||||
{1, 6, 18, 38, 66, 102, 146, 198, 258, 326},
|
||||
{1, 8, 32, 88, 192, 360, 608, 952, 1408, 1992},
|
||||
{1, 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290},
|
||||
{1, 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436},
|
||||
{1, 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598},
|
||||
{1, 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688},
|
||||
{1, 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146}
|
||||
};
|
||||
|
||||
U(N,K) = the number of such combinations wherein N-1 objects are taken at
|
||||
most K-1 at a time.
|
||||
This is given by
|
||||
U(N,K) = sum(k=0...K-1,V(N-1,k))
|
||||
= K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0.
|
||||
The latter expression also makes clear that U(N,K) is half the number of such
|
||||
combinations wherein the first object is taken at least once.
|
||||
Although it may not be clear from either of these definitions, U(N,K) is the
|
||||
natural function to work with when enumerating the pulse vector codebooks,
|
||||
not V(N,K).
|
||||
U(N,K) is not well-defined for N=0, but with the extension
|
||||
U(0,K) = K>0 ? 0 : 1,
|
||||
the function becomes symmetric: U(N,K) = U(K,N), with a similar table:
|
||||
U[10][10] = {
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||
{0, 1, 3, 5, 7, 9, 11, 13, 15, 17},
|
||||
{0, 1, 5, 13, 25, 41, 61, 85, 113, 145},
|
||||
{0, 1, 7, 25, 63, 129, 231, 377, 575, 833},
|
||||
{0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649},
|
||||
{0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073},
|
||||
{0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081},
|
||||
{0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545},
|
||||
{0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729}
|
||||
};
|
||||
|
||||
With this extension, V(N,K) may be written in terms of U(N,K):
|
||||
V(N,K) = U(N,K) + U(N,K+1)
|
||||
for all N>=0, K>=0.
|
||||
Thus U(N,K+1) represents the number of combinations where the first element
|
||||
is positive or zero, and U(N,K) represents the number of combinations where
|
||||
it is negative.
|
||||
With a large enough table of U(N,K) values, we could write O(N) encoding
|
||||
and O(min(N*log(K),N+K)) decoding routines, but such a table would be
|
||||
prohibitively large for small embedded devices (K may be as large as 32767
|
||||
for small N, and N may be as large as 200).
|
||||
|
||||
Both functions obey the same recurrence relation:
|
||||
V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1),
|
||||
U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1),
|
||||
for all N>0, K>0, with different initial conditions at N=0 or K=0.
|
||||
This allows us to construct a row of one of the tables above given the
|
||||
previous row or the next row.
|
||||
Thus we can derive O(NK) encoding and decoding routines with O(K) memory
|
||||
using only addition and subtraction.
|
||||
|
||||
When encoding, we build up from the U(2,K) row and work our way forwards.
|
||||
When decoding, we need to start at the U(N,K) row and work our way backwards,
|
||||
which requires a means of computing U(N,K).
|
||||
U(N,K) may be computed from two previous values with the same N:
|
||||
U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2)
|
||||
for all N>1, and since U(N,K) is symmetric, a similar relation holds for two
|
||||
previous values with the same K:
|
||||
U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K)
|
||||
for all K>1.
|
||||
This allows us to construct an arbitrary row of the U(N,K) table by starting
|
||||
with the first two values, which are constants.
|
||||
This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K)
|
||||
multiplications.
|
||||
Similar relations can be derived for V(N,K), but are not used here.
|
||||
|
||||
For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree
|
||||
polynomial for fixed N.
|
||||
The first few are
|
||||
U(1,K) = 1,
|
||||
U(2,K) = 2*K-1,
|
||||
U(3,K) = (2*K-2)*K+1,
|
||||
U(4,K) = (((4*K-6)*K+8)*K-3)/3,
|
||||
U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3,
|
||||
and
|
||||
V(1,K) = 2,
|
||||
V(2,K) = 4*K,
|
||||
V(3,K) = 4*K*K+2,
|
||||
V(4,K) = 8*(K*K+2)*K/3,
|
||||
V(5,K) = ((4*K*K+20)*K*K+6)/3,
|
||||
for all K>0.
|
||||
This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for
|
||||
small N (and indeed decoding is also O(N) for N<3).
|
||||
|
||||
@ARTICLE{Fis86,
|
||||
author="Thomas R. Fischer",
|
||||
title="A Pyramid Vector Quantizer",
|
||||
journal="IEEE Transactions on Information Theory",
|
||||
volume="IT-32",
|
||||
number=4,
|
||||
pages="568--583",
|
||||
month=Jul,
|
||||
year=1986
|
||||
}*/
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
/*Compute U(2,_k).
|
||||
Note that this may be called with _k=32768 (maxK[2]+1).*/
|
||||
static inline unsigned ucwrs2(unsigned _k){
|
||||
celt_assert(_k>0);
|
||||
return _k+(_k-1);
|
||||
}
|
||||
|
||||
/*Compute V(2,_k).*/
|
||||
static inline opus_uint32 ncwrs2(int _k){
|
||||
celt_assert(_k>0);
|
||||
return 4*(opus_uint32)_k;
|
||||
}
|
||||
|
||||
/*Compute U(3,_k).
|
||||
Note that this may be called with _k=32768 (maxK[3]+1).*/
|
||||
static inline opus_uint32 ucwrs3(unsigned _k){
|
||||
celt_assert(_k>0);
|
||||
return (2*(opus_uint32)_k-2)*_k+1;
|
||||
}
|
||||
|
||||
/*Compute V(3,_k).*/
|
||||
static inline opus_uint32 ncwrs3(int _k){
|
||||
celt_assert(_k>0);
|
||||
return 2*(2*(unsigned)_k*(opus_uint32)_k+1);
|
||||
}
|
||||
|
||||
/*Compute U(4,_k).*/
|
||||
static inline opus_uint32 ucwrs4(int _k){
|
||||
celt_assert(_k>0);
|
||||
return imusdiv32odd(2*_k,(2*_k-3)*(opus_uint32)_k+4,3,1);
|
||||
}
|
||||
|
||||
/*Compute V(4,_k).*/
|
||||
static inline opus_uint32 ncwrs4(int _k){
|
||||
celt_assert(_k>0);
|
||||
return ((_k*(opus_uint32)_k+2)*_k)/3<<3;
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*Computes the next row/column of any recurrence that obeys the relation
|
||||
u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
|
||||
_ui0 is the base case for the new row/column.*/
|
||||
static inline void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){
|
||||
opus_uint32 ui1;
|
||||
unsigned j;
|
||||
/*This do-while will overrun the array if we don't have storage for at least
|
||||
2 values.*/
|
||||
j=1; do {
|
||||
ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
|
||||
_ui[j-1]=_ui0;
|
||||
_ui0=ui1;
|
||||
} while (++j<_len);
|
||||
_ui[j-1]=_ui0;
|
||||
}
|
||||
|
||||
/*Computes the previous row/column of any recurrence that obeys the relation
|
||||
u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
|
||||
_ui0 is the base case for the new row/column.*/
|
||||
static inline void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){
|
||||
opus_uint32 ui1;
|
||||
unsigned j;
|
||||
/*This do-while will overrun the array if we don't have storage for at least
|
||||
2 values.*/
|
||||
j=1; do {
|
||||
ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
|
||||
_ui[j-1]=_ui0;
|
||||
_ui0=ui1;
|
||||
} while (++j<_n);
|
||||
_ui[j-1]=_ui0;
|
||||
}
|
||||
|
||||
/*Compute V(_n,_k), as well as U(_n,0..._k+1).
|
||||
_u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/
|
||||
static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){
|
||||
opus_uint32 um2;
|
||||
unsigned len;
|
||||
unsigned k;
|
||||
len=_k+2;
|
||||
/*We require storage at least 3 values (e.g., _k>0).*/
|
||||
celt_assert(len>=3);
|
||||
_u[0]=0;
|
||||
_u[1]=um2=1;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
/*_k>52 doesn't work in the false branch due to the limits of INV_TABLE,
|
||||
but _k isn't tested here because k<=52 for n=7*/
|
||||
if(_n<=6)
|
||||
#endif
|
||||
{
|
||||
/*If _n==0, _u[0] should be 1 and the rest should be 0.*/
|
||||
/*If _n==1, _u[i] should be 1 for i>1.*/
|
||||
celt_assert(_n>=2);
|
||||
/*If _k==0, the following do-while loop will overflow the buffer.*/
|
||||
celt_assert(_k>0);
|
||||
k=2;
|
||||
do _u[k]=(k<<1)-1;
|
||||
while(++k<len);
|
||||
for(k=2;k<_n;k++)unext(_u+1,_k+1,1);
|
||||
}
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
else{
|
||||
opus_uint32 um1;
|
||||
opus_uint32 n2m1;
|
||||
_u[2]=n2m1=um1=(_n<<1)-1;
|
||||
for(k=3;k<len;k++){
|
||||
/*U(N,K) = ((2*N-1)*U(N,K-1)-U(N,K-2))/(K-1) + U(N,K-2)*/
|
||||
_u[k]=um2=imusdiv32even(n2m1,um1,um2,k-1)+um2;
|
||||
if(++k>=len)break;
|
||||
_u[k]=um1=imusdiv32odd(n2m1,um2,um1,(k-1)>>1)+um1;
|
||||
}
|
||||
}
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
return _u[_k]+_u[_k+1];
|
||||
}
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 1 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static inline void cwrsi1(int _k,opus_uint32 _i,int *_y){
|
||||
int s;
|
||||
s=-(int)_i;
|
||||
_y[0]=(_k+s)^s;
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 2 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static inline void cwrsi2(int _k,opus_uint32 _i,int *_y){
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=ucwrs2(_k+1U);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
_k=(_i+1)>>1;
|
||||
p=_k?ucwrs2(_k):0;
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=(yj+s)^s;
|
||||
cwrsi1(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 3 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static void cwrsi3(int _k,opus_uint32 _i,int *_y){
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=ucwrs3(_k+1U);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
/*Finds the maximum _k such that ucwrs3(_k)<=_i (tested for all
|
||||
_i<2147418113=U(3,32768)).*/
|
||||
_k=_i>0?(isqrt32(2*_i-1)+1)>>1:0;
|
||||
p=_k?ucwrs3(_k):0;
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=(yj+s)^s;
|
||||
cwrsi2(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 1172) chosen from a set
|
||||
of size 4 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static void cwrsi4(int _k,opus_uint32 _i,int *_y){
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
int kl;
|
||||
int kr;
|
||||
p=ucwrs4(_k+1);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
/*We could solve a cubic for k here, but the form of the direct solution does
|
||||
not lend itself well to exact integer arithmetic.
|
||||
Instead we do a binary search on U(4,K).*/
|
||||
kl=0;
|
||||
kr=_k;
|
||||
for(;;){
|
||||
_k=(kl+kr)>>1;
|
||||
p=_k?ucwrs4(_k):0;
|
||||
if(p<_i){
|
||||
if(_k>=kr)break;
|
||||
kl=_k+1;
|
||||
}
|
||||
else if(p>_i)kr=_k-1;
|
||||
else break;
|
||||
}
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=(yj+s)^s;
|
||||
cwrsi3(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*Returns the _i'th combination of _k elements chosen from a set of size _n
|
||||
with associated sign bits.
|
||||
_y: Returns the vector of pulses.
|
||||
_u: Must contain entries [0..._k+1] of row _n of U() on input.
|
||||
Its contents will be destructively modified.*/
|
||||
static void cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){
|
||||
int j;
|
||||
celt_assert(_n>0);
|
||||
j=0;
|
||||
do{
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=_u[_k+1];
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
p=_u[_k];
|
||||
while(p>_i)p=_u[--_k];
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[j]=(yj+s)^s;
|
||||
uprev(_u,_k+2,0);
|
||||
}
|
||||
while(++j<_n);
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 1 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline opus_uint32 icwrs1(const int *_y,int *_k){
|
||||
*_k=abs(_y[0]);
|
||||
return _y[0]<0;
|
||||
}
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 2 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline opus_uint32 icwrs2(const int *_y,int *_k){
|
||||
opus_uint32 i;
|
||||
int k;
|
||||
i=icwrs1(_y+1,&k);
|
||||
i+=k?ucwrs2(k):0;
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs2(k+1U);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 3 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline opus_uint32 icwrs3(const int *_y,int *_k){
|
||||
opus_uint32 i;
|
||||
int k;
|
||||
i=icwrs2(_y+1,&k);
|
||||
i+=k?ucwrs3(k):0;
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs3(k+1U);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 4 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline opus_uint32 icwrs4(const int *_y,int *_k){
|
||||
opus_uint32 i;
|
||||
int k;
|
||||
i=icwrs3(_y+1,&k);
|
||||
i+=k?ucwrs4(k):0;
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs4(k+1);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size _n with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values must be _k.
|
||||
_nc: Returns V(_n,_k).*/
|
||||
static inline opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y,
|
||||
opus_uint32 *_u){
|
||||
opus_uint32 i;
|
||||
int j;
|
||||
int k;
|
||||
/*We can't unroll the first two iterations of the loop unless _n>=2.*/
|
||||
celt_assert(_n>=2);
|
||||
_u[0]=0;
|
||||
for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1;
|
||||
i=icwrs1(_y+_n-1,&k);
|
||||
j=_n-2;
|
||||
i+=_u[k];
|
||||
k+=abs(_y[j]);
|
||||
if(_y[j]<0)i+=_u[k+1];
|
||||
while(j-->0){
|
||||
unext(_u,_k+2,0);
|
||||
i+=_u[k];
|
||||
k+=abs(_y[j]);
|
||||
if(_y[j]<0)i+=_u[k+1];
|
||||
}
|
||||
*_nc=_u[k]+_u[k+1];
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
|
||||
int k;
|
||||
/*_maxk==0 => there's nothing to do.*/
|
||||
celt_assert(_maxk>0);
|
||||
_bits[0]=0;
|
||||
if (_n==1)
|
||||
{
|
||||
for (k=1;k<=_maxk;k++)
|
||||
_bits[k] = 1<<_frac;
|
||||
}
|
||||
else {
|
||||
VARDECL(opus_uint32,u);
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_maxk+2U,opus_uint32);
|
||||
ncwrs_urow(_n,_maxk,u);
|
||||
for(k=1;k<=_maxk;k++)
|
||||
_bits[k]=log2_frac(u[k]+u[k+1],_frac);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
|
||||
opus_uint32 i;
|
||||
celt_assert(_k>0);
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
switch(_n){
|
||||
case 2:{
|
||||
i=icwrs2(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs2(_k));
|
||||
}break;
|
||||
case 3:{
|
||||
i=icwrs3(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs3(_k));
|
||||
}break;
|
||||
case 4:{
|
||||
i=icwrs4(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs4(_k));
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
#endif
|
||||
VARDECL(opus_uint32,u);
|
||||
opus_uint32 nc;
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_k+2U,opus_uint32);
|
||||
i=icwrs(_n,_k,&nc,_y,u);
|
||||
ec_enc_uint(_enc,i,nc);
|
||||
RESTORE_STACK;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec)
|
||||
{
|
||||
celt_assert(_k>0);
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
switch(_n){
|
||||
case 2:cwrsi2(_k,ec_dec_uint(_dec,ncwrs2(_k)),_y);break;
|
||||
case 3:cwrsi3(_k,ec_dec_uint(_dec,ncwrs3(_k)),_y);break;
|
||||
case 4:cwrsi4(_k,ec_dec_uint(_dec,ncwrs4(_k)),_y);break;
|
||||
default:
|
||||
{
|
||||
#endif
|
||||
VARDECL(opus_uint32,u);
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_k+2U,opus_uint32);
|
||||
cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
|
||||
RESTORE_STACK;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2007-2009 Timothy B. Terriberry
|
||||
Written by Timothy B. Terriberry and Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CWRS_H
|
||||
#define CWRS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
int log2_frac(opus_uint32 val, int frac);
|
||||
#endif
|
||||
|
||||
void get_required_bits(opus_int16 *bits, int N, int K, int frac);
|
||||
|
||||
void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
|
||||
|
||||
void decode_pulses(int *_y, int N, int K, ec_dec *dec);
|
||||
|
||||
#endif /* CWRS_H */
|
|
@ -0,0 +1,87 @@
|
|||
/* Copyright (c) 2003-2008 Timothy B. Terriberry
|
||||
Copyright (c) 2008 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*Some common macros for potential platform-specific optimization.*/
|
||||
#include "opus_types.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include "arch.h"
|
||||
#if !defined(_ecintrin_H)
|
||||
# define _ecintrin_H (1)
|
||||
|
||||
/*Some specific platforms may have optimized intrinsic or inline assembly
|
||||
versions of these functions which can substantially improve performance.
|
||||
We define macros for them to allow easy incorporation of these non-ANSI
|
||||
features.*/
|
||||
|
||||
/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
|
||||
given an appropriate architecture, but the branchless bit-twiddling versions
|
||||
are just as fast, and do not require any special target architecture.
|
||||
Earlier gcc versions (3.x) compiled both code to the same assembly
|
||||
instructions, because of the way they represented ((_b)>(_a)) internally.*/
|
||||
# define EC_MINI(_a,_b) ((_a)+(((_b)-(_a))&-((_b)<(_a))))
|
||||
|
||||
/*Count leading zeros.
|
||||
This macro should only be used for implementing ec_ilog(), if it is defined.
|
||||
All other code should use EC_ILOG() instead.*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
# include <intrin.h>
|
||||
/*In _DEBUG mode this is not an intrinsic by default.*/
|
||||
# pragma intrinsic(_BitScanReverse)
|
||||
|
||||
static __inline int ec_bsr(unsigned long _x){
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret,_x);
|
||||
return (int)ret;
|
||||
}
|
||||
# define EC_CLZ0 (1)
|
||||
# define EC_CLZ(_x) (-ec_bsr(_x))
|
||||
#elif defined(ENABLE_TI_DSPLIB)
|
||||
# include "dsplib.h"
|
||||
# define EC_CLZ0 (31)
|
||||
# define EC_CLZ(_x) (_lnorm(_x))
|
||||
#elif __GNUC_PREREQ(3,4)
|
||||
# if INT_MAX>=2147483647
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clz(_x))
|
||||
# elif LONG_MAX>=2147483647L
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clzl(_x))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(EC_CLZ)
|
||||
/*Note that __builtin_clz is not defined when _x==0, according to the gcc
|
||||
documentation (and that of the BSR instruction that implements it on x86).
|
||||
The majority of the time we can never pass it zero.
|
||||
When we need to, it can be special cased.*/
|
||||
# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
|
||||
#else
|
||||
int ec_ilog(opus_uint32 _v);
|
||||
# define EC_ILOG(_x) (ec_ilog(_x))
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "entcode.h"
|
||||
#include "arch.h"
|
||||
|
||||
#if !defined(EC_CLZ)
|
||||
/*This is a fallback for systems where we don't know how to access
|
||||
a BSR or CLZ instruction (see ecintrin.h).
|
||||
If you are optimizing Opus on a new platform and it has a native CLZ or
|
||||
BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be
|
||||
an easy performance win.*/
|
||||
int ec_ilog(opus_uint32 _v){
|
||||
/*On a Pentium M, this branchless version tested as the fastest on
|
||||
1,000,000,000 random 32-bit integers, edging out a similar version with
|
||||
branches, and a 256-entry LUT version.*/
|
||||
int ret;
|
||||
int m;
|
||||
ret=!!_v;
|
||||
m=!!(_v&0xFFFF0000)<<4;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xFF00)<<3;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xF0)<<2;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xC)<<1;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
ret+=!!(_v&0x2);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
opus_uint32 ec_tell_frac(ec_ctx *_this){
|
||||
opus_uint32 nbits;
|
||||
opus_uint32 r;
|
||||
int l;
|
||||
int i;
|
||||
/*To handle the non-integral number of bits still left in the encoder/decoder
|
||||
state, we compute the worst-case number of bits of val that must be
|
||||
encoded to ensure that the value is inside the range for any possible
|
||||
subsequent bits.
|
||||
The computation here is independent of val itself (the decoder does not
|
||||
even track that value), even though the real number of bits used after
|
||||
ec_enc_done() may be 1 smaller if rng is a power of two and the
|
||||
corresponding trailing bits of val are all zeros.
|
||||
If we did try to track that special case, then coding a value with a
|
||||
probability of 1/(1<<n) might sometimes appear to use more than n bits.
|
||||
This may help explain the surprising result that a newly initialized
|
||||
encoder or decoder claims to have used 1 bit.*/
|
||||
nbits=_this->nbits_total<<BITRES;
|
||||
l=EC_ILOG(_this->rng);
|
||||
r=_this->rng>>(l-16);
|
||||
for(i=BITRES;i-->0;){
|
||||
int b;
|
||||
r=r*r>>15;
|
||||
b=(int)(r>>16);
|
||||
l=l<<1|b;
|
||||
r>>=b;
|
||||
}
|
||||
return nbits-l;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opus_types.h"
|
||||
|
||||
#if !defined(_entcode_H)
|
||||
# define _entcode_H (1)
|
||||
# include <limits.h>
|
||||
# include <stddef.h>
|
||||
# include "ecintrin.h"
|
||||
|
||||
/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a
|
||||
larger type, you can speed up the decoder by using it here.*/
|
||||
typedef opus_uint32 ec_window;
|
||||
typedef struct ec_ctx ec_ctx;
|
||||
typedef struct ec_ctx ec_enc;
|
||||
typedef struct ec_ctx ec_dec;
|
||||
|
||||
# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
|
||||
|
||||
/*The number of bits to use for the range-coded part of unsigned integers.*/
|
||||
# define EC_UINT_BITS (8)
|
||||
|
||||
/*The resolution of fractional-precision bit usage measurements, i.e.,
|
||||
3 => 1/8th bits.*/
|
||||
# define BITRES 3
|
||||
|
||||
/*The entropy encoder/decoder context.
|
||||
We use the same structure for both, so that common functions like ec_tell()
|
||||
can be used on either one.*/
|
||||
struct ec_ctx{
|
||||
/*Buffered input/output.*/
|
||||
unsigned char *buf;
|
||||
/*The size of the buffer.*/
|
||||
opus_uint32 storage;
|
||||
/*The offset at which the last byte containing raw bits was read/written.*/
|
||||
opus_uint32 end_offs;
|
||||
/*Bits that will be read from/written at the end.*/
|
||||
ec_window end_window;
|
||||
/*Number of valid bits in end_window.*/
|
||||
int nend_bits;
|
||||
/*The total number of whole bits read/written.
|
||||
This does not include partial bits currently in the range coder.*/
|
||||
int nbits_total;
|
||||
/*The offset at which the next range coder byte will be read/written.*/
|
||||
opus_uint32 offs;
|
||||
/*The number of values in the current range.*/
|
||||
opus_uint32 rng;
|
||||
/*In the decoder: the difference between the top of the current range and
|
||||
the input value, minus one.
|
||||
In the encoder: the low end of the current range.*/
|
||||
opus_uint32 val;
|
||||
/*In the decoder: the saved normalization factor from ec_decode().
|
||||
In the encoder: the number of oustanding carry propagating symbols.*/
|
||||
opus_uint32 ext;
|
||||
/*A buffered input/output symbol, awaiting carry propagation.*/
|
||||
int rem;
|
||||
/*Nonzero if an error occurred.*/
|
||||
int error;
|
||||
};
|
||||
|
||||
static inline opus_uint32 ec_range_bytes(ec_ctx *_this){
|
||||
return _this->offs;
|
||||
}
|
||||
|
||||
static inline unsigned char *ec_get_buffer(ec_ctx *_this){
|
||||
return _this->buf;
|
||||
}
|
||||
|
||||
static inline int ec_get_error(ec_ctx *_this){
|
||||
return _this->error;
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
static inline int ec_tell(ec_ctx *_this){
|
||||
return _this->nbits_total-EC_ILOG(_this->rng);
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits scaled by 2**BITRES.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
opus_uint32 ec_tell_frac(ec_ctx *_this);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,245 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "os_support.h"
|
||||
#include "arch.h"
|
||||
#include "entdec.h"
|
||||
#include "mfrngcod.h"
|
||||
|
||||
/*A range decoder.
|
||||
This is an entropy decoder based upon \cite{Mar79}, which is itself a
|
||||
rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
|
||||
It is very similar to arithmetic encoding, except that encoding is done with
|
||||
digits in any base, instead of with bits, and so it is faster when using
|
||||
larger bases (i.e.: a byte).
|
||||
The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
|
||||
is the base, longer than the theoretical optimum, but to my knowledge there
|
||||
is no published justification for this claim.
|
||||
This only seems true when using near-infinite precision arithmetic so that
|
||||
the process is carried out with no rounding errors.
|
||||
|
||||
An excellent description of implementation details is available at
|
||||
http://www.arturocampos.com/ac_range.html
|
||||
A recent work \cite{MNW98} which proposes several changes to arithmetic
|
||||
encoding for efficiency actually re-discovers many of the principles
|
||||
behind range encoding, and presents a good theoretical analysis of them.
|
||||
|
||||
End of stream is handled by writing out the smallest number of bits that
|
||||
ensures that the stream will be correctly decoded regardless of the value of
|
||||
any subsequent bits.
|
||||
ec_tell() can be used to determine how many bits were needed to decode
|
||||
all the symbols thus far; other data can be packed in the remaining bits of
|
||||
the input buffer.
|
||||
@PHDTHESIS{Pas76,
|
||||
author="Richard Clark Pasco",
|
||||
title="Source coding algorithms for fast data compression",
|
||||
school="Dept. of Electrical Engineering, Stanford University",
|
||||
address="Stanford, CA",
|
||||
month=May,
|
||||
year=1976
|
||||
}
|
||||
@INPROCEEDINGS{Mar79,
|
||||
author="Martin, G.N.N.",
|
||||
title="Range encoding: an algorithm for removing redundancy from a digitised
|
||||
message",
|
||||
booktitle="Video & Data Recording Conference",
|
||||
year=1979,
|
||||
address="Southampton",
|
||||
month=Jul
|
||||
}
|
||||
@ARTICLE{MNW98,
|
||||
author="Alistair Moffat and Radford Neal and Ian H. Witten",
|
||||
title="Arithmetic Coding Revisited",
|
||||
journal="{ACM} Transactions on Information Systems",
|
||||
year=1998,
|
||||
volume=16,
|
||||
number=3,
|
||||
pages="256--294",
|
||||
month=Jul,
|
||||
URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
|
||||
}*/
|
||||
|
||||
static int ec_read_byte(ec_dec *_this){
|
||||
return _this->offs<_this->storage?_this->buf[_this->offs++]:0;
|
||||
}
|
||||
|
||||
static int ec_read_byte_from_end(ec_dec *_this){
|
||||
return _this->end_offs<_this->storage?
|
||||
_this->buf[_this->storage-++(_this->end_offs)]:0;
|
||||
}
|
||||
|
||||
/*Normalizes the contents of val and rng so that rng lies entirely in the
|
||||
high-order symbol.*/
|
||||
static void ec_dec_normalize(ec_dec *_this){
|
||||
/*If the range is too small, rescale it and input some bits.*/
|
||||
while(_this->rng<=EC_CODE_BOT){
|
||||
int sym;
|
||||
_this->nbits_total+=EC_SYM_BITS;
|
||||
_this->rng<<=EC_SYM_BITS;
|
||||
/*Use up the remaining bits from our last symbol.*/
|
||||
sym=_this->rem;
|
||||
/*Read the next value from the input.*/
|
||||
_this->rem=ec_read_byte(_this);
|
||||
/*Take the rest of the bits we need from this new symbol.*/
|
||||
sym=(sym<<EC_SYM_BITS|_this->rem)>>(EC_SYM_BITS-EC_CODE_EXTRA);
|
||||
/*And subtract them from val, capped to be less than EC_CODE_TOP.*/
|
||||
_this->val=((_this->val<<EC_SYM_BITS)+(EC_SYM_MAX&~sym))&(EC_CODE_TOP-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage){
|
||||
_this->buf=_buf;
|
||||
_this->storage=_storage;
|
||||
_this->end_offs=0;
|
||||
_this->end_window=0;
|
||||
_this->nend_bits=0;
|
||||
/*This is the offset from which ec_tell() will subtract partial bits.
|
||||
The final value after the ec_dec_normalize() call will be the same as in
|
||||
the encoder, but we have to compensate for the bits that are added there.*/
|
||||
_this->nbits_total=EC_CODE_BITS+1
|
||||
-((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS;
|
||||
_this->offs=0;
|
||||
_this->rng=1U<<EC_CODE_EXTRA;
|
||||
_this->rem=ec_read_byte(_this);
|
||||
_this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA));
|
||||
_this->error=0;
|
||||
/*Normalize the interval.*/
|
||||
ec_dec_normalize(_this);
|
||||
}
|
||||
|
||||
unsigned ec_decode(ec_dec *_this,unsigned _ft){
|
||||
unsigned s;
|
||||
_this->ext=_this->rng/_ft;
|
||||
s=(unsigned)(_this->val/_this->ext);
|
||||
return _ft-EC_MINI(s+1,_ft);
|
||||
}
|
||||
|
||||
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){
|
||||
unsigned s;
|
||||
_this->ext=_this->rng>>_bits;
|
||||
s=(unsigned)(_this->val/_this->ext);
|
||||
return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits);
|
||||
}
|
||||
|
||||
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||
opus_uint32 s;
|
||||
s=IMUL32(_this->ext,_ft-_fh);
|
||||
_this->val-=s;
|
||||
_this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s;
|
||||
ec_dec_normalize(_this);
|
||||
}
|
||||
|
||||
/*The probability of having a "one" is 1/(1<<_logp).*/
|
||||
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
int ret;
|
||||
r=_this->rng;
|
||||
d=_this->val;
|
||||
s=r>>_logp;
|
||||
ret=d<s;
|
||||
if(!ret)_this->val=d-s;
|
||||
_this->rng=ret?s:r-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
opus_uint32 t;
|
||||
int ret;
|
||||
s=_this->rng;
|
||||
d=_this->val;
|
||||
r=s>>_ftb;
|
||||
ret=-1;
|
||||
do{
|
||||
t=s;
|
||||
s=IMUL32(r,_icdf[++ret]);
|
||||
}
|
||||
while(d<s);
|
||||
_this->val=d-s;
|
||||
_this->rng=t-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
|
||||
unsigned ft;
|
||||
unsigned s;
|
||||
int ftb;
|
||||
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
|
||||
celt_assert(_ft>1);
|
||||
_ft--;
|
||||
ftb=EC_ILOG(_ft);
|
||||
if(ftb>EC_UINT_BITS){
|
||||
opus_uint32 t;
|
||||
ftb-=EC_UINT_BITS;
|
||||
ft=(unsigned)(_ft>>ftb)+1;
|
||||
s=ec_decode(_this,ft);
|
||||
ec_dec_update(_this,s,s+1,ft);
|
||||
t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb);
|
||||
if(t<=_ft)return t;
|
||||
_this->error=1;
|
||||
return _ft;
|
||||
}
|
||||
else{
|
||||
_ft++;
|
||||
s=ec_decode(_this,(unsigned)_ft);
|
||||
ec_dec_update(_this,s,s+1,(unsigned)_ft);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
|
||||
ec_window window;
|
||||
int available;
|
||||
opus_uint32 ret;
|
||||
window=_this->end_window;
|
||||
available=_this->nend_bits;
|
||||
if((unsigned)available<_bits){
|
||||
do{
|
||||
window|=(ec_window)ec_read_byte_from_end(_this)<<available;
|
||||
available+=EC_SYM_BITS;
|
||||
}
|
||||
while(available<=EC_WINDOW_SIZE-EC_SYM_BITS);
|
||||
}
|
||||
ret=(opus_uint32)window&(((opus_uint32)1<<_bits)-1U);
|
||||
window>>=_bits;
|
||||
available-=_bits;
|
||||
_this->end_window=window;
|
||||
_this->nend_bits=available;
|
||||
_this->nbits_total+=_bits;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_entdec_H)
|
||||
# define _entdec_H (1)
|
||||
# include <limits.h>
|
||||
# include "entcode.h"
|
||||
|
||||
/*Initializes the decoder.
|
||||
_buf: The input buffer to use.
|
||||
Return: 0 on success, or a negative value on error.*/
|
||||
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage);
|
||||
|
||||
/*Calculates the cumulative frequency for the next symbol.
|
||||
This can then be fed into the probability model to determine what that
|
||||
symbol is, and the additional frequency information required to advance to
|
||||
the next symbol.
|
||||
This function cannot be called more than once without a corresponding call to
|
||||
ec_dec_update(), or decoding will not proceed correctly.
|
||||
_ft: The total frequency of the symbols in the alphabet the next symbol was
|
||||
encoded with.
|
||||
Return: A cumulative frequency representing the encoded symbol.
|
||||
If the cumulative frequency of all the symbols before the one that
|
||||
was encoded was fl, and the cumulative frequency of all the symbols
|
||||
up to and including the one encoded is fh, then the returned value
|
||||
will fall in the range [fl,fh).*/
|
||||
unsigned ec_decode(ec_dec *_this,unsigned _ft);
|
||||
|
||||
/*Equivalent to ec_decode() with _ft==1<<_bits.*/
|
||||
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits);
|
||||
|
||||
/*Advance the decoder past the next symbol using the frequency information the
|
||||
symbol was encoded with.
|
||||
Exactly one call to ec_decode() must have been made so that all necessary
|
||||
intermediate calculations are performed.
|
||||
_fl: The cumulative frequency of all symbols that come before the symbol
|
||||
decoded.
|
||||
_fh: The cumulative frequency of all symbols up to and including the symbol
|
||||
decoded.
|
||||
Together with _fl, this defines the range [_fl,_fh) in which the value
|
||||
returned above must fall.
|
||||
_ft: The total frequency of the symbols in the alphabet the symbol decoded
|
||||
was encoded in.
|
||||
This must be the same as passed to the preceding call to ec_decode().*/
|
||||
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft);
|
||||
|
||||
/* Decode a bit that has a 1/(1<<_logp) probability of being a one */
|
||||
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
|
||||
|
||||
/*Decodes a symbol given an "inverse" CDF table.
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_icdf: The "inverse" CDF, such that symbol s falls in the range
|
||||
[s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.
|
||||
Return: The decoded symbol s.*/
|
||||
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
|
||||
|
||||
/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
|
||||
The bits must have been encoded with ec_enc_uint().
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_ft: The number of integers that can be decoded (one more than the max).
|
||||
This must be at least one, and no more than 2**32-1.
|
||||
Return: The decoded bits.*/
|
||||
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
|
||||
|
||||
/*Extracts a sequence of raw bits from the stream.
|
||||
The bits must have been encoded with ec_enc_bits().
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_ftb: The number of bits to extract.
|
||||
This must be between 0 and 25, inclusive.
|
||||
Return: The decoded bits.*/
|
||||
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,294 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "os_support.h"
|
||||
#include "arch.h"
|
||||
#include "entenc.h"
|
||||
#include "mfrngcod.h"
|
||||
|
||||
/*A range encoder.
|
||||
See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
|
||||
|
||||
@INPROCEEDINGS{Mar79,
|
||||
author="Martin, G.N.N.",
|
||||
title="Range encoding: an algorithm for removing redundancy from a digitised
|
||||
message",
|
||||
booktitle="Video \& Data Recording Conference",
|
||||
year=1979,
|
||||
address="Southampton",
|
||||
month=Jul
|
||||
}
|
||||
@ARTICLE{MNW98,
|
||||
author="Alistair Moffat and Radford Neal and Ian H. Witten",
|
||||
title="Arithmetic Coding Revisited",
|
||||
journal="{ACM} Transactions on Information Systems",
|
||||
year=1998,
|
||||
volume=16,
|
||||
number=3,
|
||||
pages="256--294",
|
||||
month=Jul,
|
||||
URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
|
||||
}*/
|
||||
|
||||
static int ec_write_byte(ec_enc *_this,unsigned _value){
|
||||
if(_this->offs+_this->end_offs>=_this->storage)return -1;
|
||||
_this->buf[_this->offs++]=(unsigned char)_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ec_write_byte_at_end(ec_enc *_this,unsigned _value){
|
||||
if(_this->offs+_this->end_offs>=_this->storage)return -1;
|
||||
_this->buf[_this->storage-++(_this->end_offs)]=(unsigned char)_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Outputs a symbol, with a carry bit.
|
||||
If there is a potential to propagate a carry over several symbols, they are
|
||||
buffered until it can be determined whether or not an actual carry will
|
||||
occur.
|
||||
If the counter for the buffered symbols overflows, then the stream becomes
|
||||
undecodable.
|
||||
This gives a theoretical limit of a few billion symbols in a single packet on
|
||||
32-bit systems.
|
||||
The alternative is to truncate the range in order to force a carry, but
|
||||
requires similar carry tracking in the decoder, needlessly slowing it down.*/
|
||||
static void ec_enc_carry_out(ec_enc *_this,int _c){
|
||||
if(_c!=EC_SYM_MAX){
|
||||
/*No further carry propagation possible, flush buffer.*/
|
||||
int carry;
|
||||
carry=_c>>EC_SYM_BITS;
|
||||
/*Don't output a byte on the first write.
|
||||
This compare should be taken care of by branch-prediction thereafter.*/
|
||||
if(_this->rem>=0)_this->error|=ec_write_byte(_this,_this->rem+carry);
|
||||
if(_this->ext>0){
|
||||
unsigned sym;
|
||||
sym=(EC_SYM_MAX+carry)&EC_SYM_MAX;
|
||||
do _this->error|=ec_write_byte(_this,sym);
|
||||
while(--(_this->ext)>0);
|
||||
}
|
||||
_this->rem=_c&EC_SYM_MAX;
|
||||
}
|
||||
else _this->ext++;
|
||||
}
|
||||
|
||||
static void ec_enc_normalize(ec_enc *_this){
|
||||
/*If the range is too small, output some bits and rescale it.*/
|
||||
while(_this->rng<=EC_CODE_BOT){
|
||||
ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT));
|
||||
/*Move the next-to-high-order symbol into the high-order position.*/
|
||||
_this->val=(_this->val<<EC_SYM_BITS)&(EC_CODE_TOP-1);
|
||||
_this->rng<<=EC_SYM_BITS;
|
||||
_this->nbits_total+=EC_SYM_BITS;
|
||||
}
|
||||
}
|
||||
|
||||
void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size){
|
||||
_this->buf=_buf;
|
||||
_this->end_offs=0;
|
||||
_this->end_window=0;
|
||||
_this->nend_bits=0;
|
||||
/*This is the offset from which ec_tell() will subtract partial bits.*/
|
||||
_this->nbits_total=EC_CODE_BITS+1;
|
||||
_this->offs=0;
|
||||
_this->rng=EC_CODE_TOP;
|
||||
_this->rem=-1;
|
||||
_this->val=0;
|
||||
_this->ext=0;
|
||||
_this->storage=_size;
|
||||
_this->error=0;
|
||||
}
|
||||
|
||||
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||
opus_uint32 r;
|
||||
r=_this->rng/_ft;
|
||||
if(_fl>0){
|
||||
_this->val+=_this->rng-IMUL32(r,(_ft-_fl));
|
||||
_this->rng=IMUL32(r,(_fh-_fl));
|
||||
}
|
||||
else _this->rng-=IMUL32(r,(_ft-_fh));
|
||||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits){
|
||||
opus_uint32 r;
|
||||
r=_this->rng>>_bits;
|
||||
if(_fl>0){
|
||||
_this->val+=_this->rng-IMUL32(r,((1U<<_bits)-_fl));
|
||||
_this->rng=IMUL32(r,(_fh-_fl));
|
||||
}
|
||||
else _this->rng-=IMUL32(r,((1U<<_bits)-_fh));
|
||||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
/*The probability of having a "one" is 1/(1<<_logp).*/
|
||||
void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){
|
||||
opus_uint32 r;
|
||||
opus_uint32 s;
|
||||
opus_uint32 l;
|
||||
r=_this->rng;
|
||||
l=_this->val;
|
||||
s=r>>_logp;
|
||||
r-=s;
|
||||
if(_val)_this->val=l+r;
|
||||
_this->rng=_val?s:r;
|
||||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
r=_this->rng>>_ftb;
|
||||
if(_s>0){
|
||||
_this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
|
||||
_this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
|
||||
}
|
||||
else _this->rng-=IMUL32(r,_icdf[_s]);
|
||||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){
|
||||
unsigned ft;
|
||||
unsigned fl;
|
||||
int ftb;
|
||||
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
|
||||
celt_assert(_ft>1);
|
||||
_ft--;
|
||||
ftb=EC_ILOG(_ft);
|
||||
if(ftb>EC_UINT_BITS){
|
||||
ftb-=EC_UINT_BITS;
|
||||
ft=(_ft>>ftb)+1;
|
||||
fl=(unsigned)(_fl>>ftb);
|
||||
ec_encode(_this,fl,fl+1,ft);
|
||||
ec_enc_bits(_this,_fl&(((opus_uint32)1<<ftb)-1U),ftb);
|
||||
}
|
||||
else ec_encode(_this,_fl,_fl+1,_ft+1);
|
||||
}
|
||||
|
||||
void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _bits){
|
||||
ec_window window;
|
||||
int used;
|
||||
window=_this->end_window;
|
||||
used=_this->nend_bits;
|
||||
celt_assert(_bits>0);
|
||||
if(used+_bits>EC_WINDOW_SIZE){
|
||||
do{
|
||||
_this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
|
||||
window>>=EC_SYM_BITS;
|
||||
used-=EC_SYM_BITS;
|
||||
}
|
||||
while(used>=EC_SYM_BITS);
|
||||
}
|
||||
window|=(ec_window)_fl<<used;
|
||||
used+=_bits;
|
||||
_this->end_window=window;
|
||||
_this->nend_bits=used;
|
||||
_this->nbits_total+=_bits;
|
||||
}
|
||||
|
||||
void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits){
|
||||
int shift;
|
||||
unsigned mask;
|
||||
celt_assert(_nbits<=EC_SYM_BITS);
|
||||
shift=EC_SYM_BITS-_nbits;
|
||||
mask=((1<<_nbits)-1)<<shift;
|
||||
if(_this->offs>0){
|
||||
/*The first byte has been finalized.*/
|
||||
_this->buf[0]=(unsigned char)((_this->buf[0]&~mask)|_val<<shift);
|
||||
}
|
||||
else if(_this->rem>=0){
|
||||
/*The first byte is still awaiting carry propagation.*/
|
||||
_this->rem=(_this->rem&~mask)|_val<<shift;
|
||||
}
|
||||
else if(_this->rng<=(EC_CODE_TOP>>_nbits)){
|
||||
/*The renormalization loop has never been run.*/
|
||||
_this->val=(_this->val&~((opus_uint32)mask<<EC_CODE_SHIFT))|
|
||||
(opus_uint32)_val<<(EC_CODE_SHIFT+shift);
|
||||
}
|
||||
/*The encoder hasn't even encoded _nbits of data yet.*/
|
||||
else _this->error=-1;
|
||||
}
|
||||
|
||||
void ec_enc_shrink(ec_enc *_this,opus_uint32 _size){
|
||||
celt_assert(_this->offs+_this->end_offs<=_size);
|
||||
OPUS_MOVE(_this->buf+_size-_this->end_offs,
|
||||
_this->buf+_this->storage-_this->end_offs,_this->end_offs);
|
||||
_this->storage=_size;
|
||||
}
|
||||
|
||||
void ec_enc_done(ec_enc *_this){
|
||||
ec_window window;
|
||||
int used;
|
||||
opus_uint32 msk;
|
||||
opus_uint32 end;
|
||||
int l;
|
||||
/*We output the minimum number of bits that ensures that the symbols encoded
|
||||
thus far will be decoded correctly regardless of the bits that follow.*/
|
||||
l=EC_CODE_BITS-EC_ILOG(_this->rng);
|
||||
msk=(EC_CODE_TOP-1)>>l;
|
||||
end=(_this->val+msk)&~msk;
|
||||
if((end|msk)>=_this->val+_this->rng){
|
||||
l++;
|
||||
msk>>=1;
|
||||
end=(_this->val+msk)&~msk;
|
||||
}
|
||||
while(l>0){
|
||||
ec_enc_carry_out(_this,(int)(end>>EC_CODE_SHIFT));
|
||||
end=(end<<EC_SYM_BITS)&(EC_CODE_TOP-1);
|
||||
l-=EC_SYM_BITS;
|
||||
}
|
||||
/*If we have a buffered byte flush it into the output buffer.*/
|
||||
if(_this->rem>=0||_this->ext>0)ec_enc_carry_out(_this,0);
|
||||
/*If we have buffered extra bits, flush them as well.*/
|
||||
window=_this->end_window;
|
||||
used=_this->nend_bits;
|
||||
while(used>=EC_SYM_BITS){
|
||||
_this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
|
||||
window>>=EC_SYM_BITS;
|
||||
used-=EC_SYM_BITS;
|
||||
}
|
||||
/*Clear any excess space and add any remaining extra bits to the last byte.*/
|
||||
if(!_this->error){
|
||||
OPUS_CLEAR(_this->buf+_this->offs,
|
||||
_this->storage-_this->offs-_this->end_offs);
|
||||
if(used>0){
|
||||
/*If there's no range coder data at all, give up.*/
|
||||
if(_this->end_offs>=_this->storage)_this->error=-1;
|
||||
else{
|
||||
l=-l;
|
||||
/*If we've busted, don't add too many extra bits to the last byte; it
|
||||
would corrupt the range coder data, and that's more important.*/
|
||||
if(_this->offs+_this->end_offs>=_this->storage&&l<used){
|
||||
window&=(1<<l)-1;
|
||||
_this->error=-1;
|
||||
}
|
||||
_this->buf[_this->storage-_this->end_offs-1]|=(unsigned char)window;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_entenc_H)
|
||||
# define _entenc_H (1)
|
||||
# include <stddef.h>
|
||||
# include "entcode.h"
|
||||
|
||||
/*Initializes the encoder.
|
||||
_buf: The buffer to store output bytes in.
|
||||
_size: The size of the buffer, in chars.*/
|
||||
void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size);
|
||||
/*Encodes a symbol given its frequency information.
|
||||
The frequency information must be discernable by the decoder, assuming it
|
||||
has read only the previous symbols from the stream.
|
||||
It is allowable to change the frequency information, or even the entire
|
||||
source alphabet, so long as the decoder can tell from the context of the
|
||||
previously encoded information that it is supposed to do so as well.
|
||||
_fl: The cumulative frequency of all symbols that come before the one to be
|
||||
encoded.
|
||||
_fh: The cumulative frequency of all symbols up to and including the one to
|
||||
be encoded.
|
||||
Together with _fl, this defines the range [_fl,_fh) in which the
|
||||
decoded value will fall.
|
||||
_ft: The sum of the frequencies of all the symbols*/
|
||||
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft);
|
||||
|
||||
/*Equivalent to ec_encode() with _ft==1<<_bits.*/
|
||||
void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits);
|
||||
|
||||
/* Encode a bit that has a 1/(1<<_logp) probability of being a one */
|
||||
void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp);
|
||||
|
||||
/*Encodes a symbol given an "inverse" CDF table.
|
||||
_s: The index of the symbol to encode.
|
||||
_icdf: The "inverse" CDF, such that symbol _s falls in the range
|
||||
[_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.*/
|
||||
void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
|
||||
|
||||
/*Encodes a raw unsigned integer in the stream.
|
||||
_fl: The integer to encode.
|
||||
_ft: The number of integers that can be encoded (one more than the max).
|
||||
This must be at least one, and no more than 2**32-1.*/
|
||||
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
|
||||
|
||||
/*Encodes a sequence of raw bits in the stream.
|
||||
_fl: The bits to encode.
|
||||
_ftb: The number of bits to encode.
|
||||
This must be between 1 and 25, inclusive.*/
|
||||
void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _ftb);
|
||||
|
||||
/*Overwrites a few bits at the very start of an existing stream, after they
|
||||
have already been encoded.
|
||||
This makes it possible to have a few flags up front, where it is easy for
|
||||
decoders to access them without parsing the whole stream, even if their
|
||||
values are not determined until late in the encoding process, without having
|
||||
to buffer all the intermediate symbols in the encoder.
|
||||
In order for this to work, at least _nbits bits must have already been
|
||||
encoded using probabilities that are an exact power of two.
|
||||
The encoder can verify the number of encoded bits is sufficient, but cannot
|
||||
check this latter condition.
|
||||
_val: The bits to encode (in the least _nbits significant bits).
|
||||
They will be decoded in order from most-significant to least.
|
||||
_nbits: The number of bits to overwrite.
|
||||
This must be no more than 8.*/
|
||||
void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits);
|
||||
|
||||
/*Compacts the data to fit in the target size.
|
||||
This moves up the raw bits at the end of the current buffer so they are at
|
||||
the end of the new buffer size.
|
||||
The caller must ensure that the amount of data that's already been written
|
||||
will fit in the new size.
|
||||
_size: The number of bytes in the new buffer.
|
||||
This must be large enough to contain the bits already written, and
|
||||
must be no larger than the existing size.*/
|
||||
void ec_enc_shrink(ec_enc *_this,opus_uint32 _size);
|
||||
|
||||
/*Indicates that there are no more symbols to encode.
|
||||
All reamining output bytes are flushed to the output buffer.
|
||||
ec_enc_init() must be called before the encoder can be used again.*/
|
||||
void ec_enc_done(ec_enc *_this);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,763 @@
|
|||
/* Copyright (C) 2003-2008 Jean-Marc Valin
|
||||
Copyright (C) 2007-2012 Xiph.Org Foundation */
|
||||
/**
|
||||
@file fixed_debug.h
|
||||
@brief Fixed-point operations with debugging
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_DEBUG_H
|
||||
#define FIXED_DEBUG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef CELT_C
|
||||
#include "opus_defines.h"
|
||||
OPUS_EXPORT opus_int64 celt_mips=0;
|
||||
#else
|
||||
extern opus_int64 celt_mips;
|
||||
#endif
|
||||
|
||||
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
|
||||
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
|
||||
|
||||
#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
|
||||
|
||||
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
|
||||
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
|
||||
|
||||
#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
|
||||
#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
|
||||
#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
|
||||
|
||||
#define SHR(a,b) SHR32(a,b)
|
||||
#define PSHR(a,b) PSHR32(a,b)
|
||||
|
||||
static inline short NEG16(int x)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(x))
|
||||
{
|
||||
fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = -x;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
static inline int NEG32(opus_int64 x)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_INT(x))
|
||||
{
|
||||
fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = -x;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
|
||||
static inline short EXTRACT16_(int x, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(x))
|
||||
{
|
||||
fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = x;
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
|
||||
static inline int EXTEND32_(int x, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(x))
|
||||
{
|
||||
fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = x;
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
|
||||
static inline short SHR16_(int a, int shift, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a>>shift;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
#define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
|
||||
static inline short SHL16_(int a, int shift, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a<<shift;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int SHR32(opus_int64 a, int shift)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a>>shift;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
|
||||
static inline int SHL32_(opus_int64 a, int shift, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a<<shift;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
|
||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||
|
||||
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
|
||||
#define HALF16(x) (SHR16(x,1))
|
||||
#define HALF32(x) (SHR32(x,1))
|
||||
|
||||
//#define SHR(a,shift) ((a) >> (shift))
|
||||
//#define SHL(a,shift) ((a) << (shift))
|
||||
|
||||
#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
|
||||
static inline short ADD16_(int a, int b, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a+b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
|
||||
static inline short SUB16_(int a, int b, char *file, int line)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
|
||||
static inline int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a+b;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
|
||||
static inline int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef UADD32
|
||||
#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
|
||||
static inline unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
|
||||
{
|
||||
opus_uint64 res;
|
||||
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
|
||||
{
|
||||
fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a+b;
|
||||
if (!VERIFY_UINT(res))
|
||||
{
|
||||
fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef USUB32
|
||||
#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
|
||||
static inline unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
|
||||
{
|
||||
opus_uint64 res;
|
||||
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
|
||||
{
|
||||
fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
if (a<b)
|
||||
{
|
||||
fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_UINT(res))
|
||||
{
|
||||
fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* result fits in 16 bits */
|
||||
static inline short MULT16_16_16(int a, int b)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a*b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
|
||||
static inline int MULT16_16_(int a, int b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
|
||||
|
||||
#define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
|
||||
static inline int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
if (ABS32(b)>=((opus_val32)(1)<<(15+Q)))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = (((opus_int64)a)*(opus_int64)b) >> Q;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
if (Q==15)
|
||||
celt_mips+=3;
|
||||
else
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
|
||||
static inline int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
if (ABS32(b)>=((opus_int64)(1)<<(15+Q)))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
if (Q==15)
|
||||
celt_mips+=4;
|
||||
else
|
||||
celt_mips+=5;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
|
||||
#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
|
||||
|
||||
static inline int SATURATE(int a, int b)
|
||||
{
|
||||
if (a>b)
|
||||
a=b;
|
||||
if (a<-b)
|
||||
a = -b;
|
||||
celt_mips+=3;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline int MULT16_16_Q11_32(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res >>= 11;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_Q13(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res >>= 13;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_Q14(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res >>= 14;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
|
||||
static inline short MULT16_16_Q15_(int a, int b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res >>= 15;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=1;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline short MULT16_16_P13(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res += 4096;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res >>= 13;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_P14(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res += 8192;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res >>= 14;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_P15(int a, int b)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = ((opus_int64)a)*b;
|
||||
res += 16384;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res >>= 15;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
|
||||
|
||||
static inline int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (b==0)
|
||||
{
|
||||
fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a/b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
{
|
||||
fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
|
||||
if (res>32767)
|
||||
res = 32767;
|
||||
if (res<-32768)
|
||||
res = -32768;
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=35;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
|
||||
static inline int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
|
||||
{
|
||||
opus_int64 res;
|
||||
if (b==0)
|
||||
{
|
||||
fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!VERIFY_INT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
res = a/b;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
celt_assert(0);
|
||||
#endif
|
||||
}
|
||||
celt_mips+=70;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef PRINT_MIPS
|
||||
#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,129 @@
|
|||
/* Copyright (C) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (C) 2003-2008 Jean-Marc Valin
|
||||
Copyright (C) 2007-2008 CSIRO */
|
||||
/**
|
||||
@file fixed_generic.h
|
||||
@brief Generic fixed-point operations
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_GENERIC_H
|
||||
#define FIXED_GENERIC_H
|
||||
|
||||
/** Multiply a 16-bit signed value by a 16-bit unsigned value. The result is a 32-bit signed value */
|
||||
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */
|
||||
#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16((a),((b)&0x0000ffff)),16))
|
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
|
||||
|
||||
/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
|
||||
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15))
|
||||
|
||||
/** Compile-time conversion of float constant to 16-bit value */
|
||||
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
|
||||
|
||||
/** Compile-time conversion of float constant to 32-bit value */
|
||||
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
|
||||
|
||||
/** Negate a 16-bit value */
|
||||
#define NEG16(x) (-(x))
|
||||
/** Negate a 32-bit value */
|
||||
#define NEG32(x) (-(x))
|
||||
|
||||
/** Change a 32-bit value into a 16-bit value. The value is assumed to fit in 16-bit, otherwise the result is undefined */
|
||||
#define EXTRACT16(x) ((opus_val16)(x))
|
||||
/** Change a 16-bit value into a 32-bit value */
|
||||
#define EXTEND32(x) ((opus_val32)(x))
|
||||
|
||||
/** Arithmetic shift-right of a 16-bit value */
|
||||
#define SHR16(a,shift) ((a) >> (shift))
|
||||
/** Arithmetic shift-left of a 16-bit value */
|
||||
#define SHL16(a,shift) ((opus_int16)((opus_uint16)(a)<<(shift)))
|
||||
/** Arithmetic shift-right of a 32-bit value */
|
||||
#define SHR32(a,shift) ((a) >> (shift))
|
||||
/** Arithmetic shift-left of a 32-bit value */
|
||||
#define SHL32(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
|
||||
|
||||
/** 32-bit arithmetic shift right with rounding-to-nearest instead of rounding down */
|
||||
#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||
/** 32-bit arithmetic shift right where the argument can be negative */
|
||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||
|
||||
/** "RAW" macros, should not be used outside of this header file */
|
||||
#define SHR(a,shift) ((a) >> (shift))
|
||||
#define SHL(a,shift) SHL32(a,shift)
|
||||
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||
|
||||
/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
|
||||
#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
|
||||
/** Divide by two */
|
||||
#define HALF16(x) (SHR16(x,1))
|
||||
#define HALF32(x) (SHR32(x,1))
|
||||
|
||||
/** Add two 16-bit values */
|
||||
#define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b)))
|
||||
/** Subtract two 16-bit values */
|
||||
#define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b))
|
||||
/** Add two 32-bit values */
|
||||
#define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b))
|
||||
/** Subtract two 32-bit values */
|
||||
#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
|
||||
|
||||
/** 16x16 multiplication where the result fits in 16 bits */
|
||||
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))
|
||||
|
||||
/* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */
|
||||
/** 16x16 multiplication where the result fits in 32 bits */
|
||||
#define MULT16_16(a,b) (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b)))
|
||||
|
||||
/** 16x16 multiply-add where the result fits in 32 bits */
|
||||
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
|
||||
/** 16x32 multiply-add, followed by a 15-bit shift right. Results fits in 32 bits */
|
||||
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
|
||||
|
||||
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
|
||||
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
|
||||
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
|
||||
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
|
||||
|
||||
#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
|
||||
#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
|
||||
#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
|
||||
|
||||
/** Divide a 32-bit value by a 16-bit value. Result fits in 16 bits */
|
||||
#define DIV32_16(a,b) ((opus_val16)(((opus_val32)(a))/((opus_val16)(b))))
|
||||
|
||||
/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */
|
||||
#define DIV32(a,b) (((opus_val32)(a))/((opus_val32)(b)))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,140 @@
|
|||
/* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Version 1.1 */
|
||||
|
||||
#ifndef FLOAT_CAST_H
|
||||
#define FLOAT_CAST_H
|
||||
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
/*============================================================================
|
||||
** On Intel Pentium processors (especially PIII and probably P4), converting
|
||||
** from float to int is very slow. To meet the C specs, the code produced by
|
||||
** most C compilers targeting Pentium needs to change the FPU rounding mode
|
||||
** before the float to int conversion is performed.
|
||||
**
|
||||
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
|
||||
** is this flushing of the pipeline which is so slow.
|
||||
**
|
||||
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
|
||||
** llrint and llrintf which fix this problem as a side effect.
|
||||
**
|
||||
** On Unix-like systems, the configure process should have detected the
|
||||
** presence of these functions. If they weren't found we have to replace them
|
||||
** here with a standard C cast.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The C99 prototypes for lrint and lrintf are as follows:
|
||||
**
|
||||
** long int lrintf (float x) ;
|
||||
** long int lrint (double x) ;
|
||||
*/
|
||||
|
||||
/* The presence of the required functions are detected during the configure
|
||||
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
|
||||
** the config.h file.
|
||||
*/
|
||||
|
||||
#if (HAVE_LRINTF)
|
||||
|
||||
/* These defines enable functionality introduced with the 1999 ISO C
|
||||
** standard. They must be defined before the inclusion of math.h to
|
||||
** engage them. If optimisation is enabled, these functions will be
|
||||
** inlined. With optimisation switched off, you have to link in the
|
||||
** maths library using -lm.
|
||||
*/
|
||||
|
||||
#define _ISOC9X_SOURCE 1
|
||||
#define _ISOC99_SOURCE 1
|
||||
|
||||
#define __USE_ISOC9X 1
|
||||
#define __USE_ISOC99 1
|
||||
|
||||
#include <math.h>
|
||||
#define float2int(x) lrintf(x)
|
||||
|
||||
#elif (defined(HAVE_LRINT))
|
||||
|
||||
#define _ISOC9X_SOURCE 1
|
||||
#define _ISOC99_SOURCE 1
|
||||
|
||||
#define __USE_ISOC9X 1
|
||||
#define __USE_ISOC99 1
|
||||
|
||||
#include <math.h>
|
||||
#define float2int(x) lrint(x)
|
||||
|
||||
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64))
|
||||
#include <xmmintrin.h>
|
||||
|
||||
__inline long int float2int(float value)
|
||||
{
|
||||
return _mm_cvtss_si32(_mm_load_ss(&value));
|
||||
}
|
||||
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32))
|
||||
#include <math.h>
|
||||
|
||||
/* Win32 doesn't seem to have these functions.
|
||||
** Therefore implement inline versions of these functions here.
|
||||
*/
|
||||
|
||||
__inline long int
|
||||
float2int (float flt)
|
||||
{ int intgr;
|
||||
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
|
||||
return intgr ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
|
||||
/* supported by gcc in C99 mode, but not by all other compilers */
|
||||
#warning "Don't have the functions lrint() and lrintf ()."
|
||||
#warning "Replacing these functions with a standard C cast."
|
||||
#endif /* __STDC_VERSION__ >= 199901L */
|
||||
#include <math.h>
|
||||
#define float2int(flt) ((int)(floor(.5+flt)))
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
static inline opus_int16 FLOAT2INT16(float x)
|
||||
{
|
||||
x = x*CELT_SIG_SCALE;
|
||||
x = MAX32(x, -32768);
|
||||
x = MIN32(x, 32767);
|
||||
return (opus_int16)float2int(x);
|
||||
}
|
||||
#endif /* DISABLE_FLOAT_API */
|
||||
|
||||
#endif /* FLOAT_CAST_H */
|
|
@ -0,0 +1,722 @@
|
|||
/*Copyright (c) 2003-2004, Mark Borgerding
|
||||
Lots of modifications by Jean-Marc Valin
|
||||
Copyright (c) 2005-2007, Xiph.Org Foundation
|
||||
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/* This code is originally from Mark Borgerding's KISS-FFT but has been
|
||||
heavily modified to better suit Opus */
|
||||
|
||||
#ifndef SKIP_CONFIG_H
|
||||
# ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "_kiss_fft_guts.h"
|
||||
#include "arch.h"
|
||||
#include "os_support.h"
|
||||
#include "mathops.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "os_support.h"
|
||||
|
||||
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||
complex numbers. It also delares the kf_ internal functions.
|
||||
*/
|
||||
|
||||
static void kf_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
const kiss_twiddle_cpx * tw1;
|
||||
int i,j;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout2 = Fout + m;
|
||||
tw1 = st->twiddles;
|
||||
for(j=0;j<m;j++)
|
||||
{
|
||||
kiss_fft_cpx t;
|
||||
Fout->r = SHR32(Fout->r, 1);Fout->i = SHR32(Fout->i, 1);
|
||||
Fout2->r = SHR32(Fout2->r, 1);Fout2->i = SHR32(Fout2->i, 1);
|
||||
C_MUL (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
const kiss_twiddle_cpx * tw1;
|
||||
kiss_fft_cpx t;
|
||||
int i,j;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout2 = Fout + m;
|
||||
tw1 = st->twiddles;
|
||||
for(j=0;j<m;j++)
|
||||
{
|
||||
C_MULC (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kf_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
const kiss_twiddle_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
int i, j;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
for (j=0;j<m;j++)
|
||||
{
|
||||
C_MUL4(scratch[0],Fout[m] , *tw1 );
|
||||
C_MUL4(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MUL4(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
Fout->r = PSHR32(Fout->r, 2);
|
||||
Fout->i = PSHR32(Fout->i, 2);
|
||||
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||
C_ADDTO(*Fout, scratch[1]);
|
||||
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||
Fout[m2].r = PSHR32(Fout[m2].r, 2);
|
||||
Fout[m2].i = PSHR32(Fout[m2].i, 2);
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
const kiss_twiddle_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
int i, j;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
for (j=0;j<m;j++)
|
||||
{
|
||||
C_MULC(scratch[0],Fout[m] , *tw1 );
|
||||
C_MULC(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MULC(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||
C_ADDTO(*Fout, scratch[1]);
|
||||
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
Fout[m].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i - scratch[4].r;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
|
||||
static void kf_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
int i;
|
||||
size_t k;
|
||||
const size_t m2 = 2*m;
|
||||
const kiss_twiddle_cpx *tw1,*tw2;
|
||||
kiss_fft_cpx scratch[5];
|
||||
kiss_twiddle_cpx epi3;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw1=tw2=st->twiddles;
|
||||
k=m;
|
||||
do {
|
||||
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||
|
||||
C_MUL(scratch[1],Fout[m] , *tw1);
|
||||
C_MUL(scratch[2],Fout[m2] , *tw2);
|
||||
|
||||
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
} while(--k);
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
int i, k;
|
||||
const size_t m2 = 2*m;
|
||||
const kiss_twiddle_cpx *tw1,*tw2;
|
||||
kiss_fft_cpx scratch[5];
|
||||
kiss_twiddle_cpx epi3;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw1=tw2=st->twiddles;
|
||||
k=m;
|
||||
do{
|
||||
|
||||
C_MULC(scratch[1],Fout[m] , *tw1);
|
||||
C_MULC(scratch[2],Fout[m2] , *tw2);
|
||||
|
||||
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , -epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
}
|
||||
|
||||
static void kf_bfly5(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
int i, u;
|
||||
kiss_fft_cpx scratch[13];
|
||||
const kiss_twiddle_cpx * twiddles = st->twiddles;
|
||||
const kiss_twiddle_cpx *tw;
|
||||
kiss_twiddle_cpx ya,yb;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
tw=st->twiddles;
|
||||
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
for ( u=0; u<m; ++u ) {
|
||||
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||
|
||||
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||
|
||||
Fout0->r += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
||||
|
||||
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||
|
||||
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
||||
|
||||
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||
|
||||
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly5(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
int i, u;
|
||||
kiss_fft_cpx scratch[13];
|
||||
const kiss_twiddle_cpx * twiddles = st->twiddles;
|
||||
const kiss_twiddle_cpx *tw;
|
||||
kiss_twiddle_cpx ya,yb;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
tw=st->twiddles;
|
||||
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
for ( u=0; u<m; ++u ) {
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MULC(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MULC(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MULC(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MULC(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||
|
||||
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||
|
||||
Fout0->r += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = -S_MUL(scratch[10].i,ya.i) - S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = S_MUL(scratch[10].r,ya.i) + S_MUL(scratch[9].r,yb.i);
|
||||
|
||||
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||
|
||||
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = S_MUL(scratch[10].i,yb.i) - S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = -S_MUL(scratch[10].r,yb.i) + S_MUL(scratch[9].r,ya.i);
|
||||
|
||||
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||
|
||||
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
static
|
||||
void compute_bitrev_table(
|
||||
int Fout,
|
||||
opus_int16 *f,
|
||||
const size_t fstride,
|
||||
int in_stride,
|
||||
opus_int16 * factors,
|
||||
const kiss_fft_state *st
|
||||
)
|
||||
{
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
|
||||
/*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
|
||||
if (m==1)
|
||||
{
|
||||
int j;
|
||||
for (j=0;j<p;j++)
|
||||
{
|
||||
*f = Fout+j;
|
||||
f += fstride*in_stride;
|
||||
}
|
||||
} else {
|
||||
int j;
|
||||
for (j=0;j<p;j++)
|
||||
{
|
||||
compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
|
||||
f += fstride*in_stride;
|
||||
Fout += m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* facbuf is populated by p1,m1,p2,m2, ...
|
||||
where
|
||||
p[i] * m[i] = m[i-1]
|
||||
m0 = n */
|
||||
static
|
||||
int kf_factor(int n,opus_int16 * facbuf)
|
||||
{
|
||||
int p=4;
|
||||
|
||||
/*factor out powers of 4, powers of 2, then any remaining primes */
|
||||
do {
|
||||
while (n % p) {
|
||||
switch (p) {
|
||||
case 4: p = 2; break;
|
||||
case 2: p = 3; break;
|
||||
default: p += 2; break;
|
||||
}
|
||||
if (p>32000 || (opus_int32)p*(opus_int32)p > n)
|
||||
p = n; /* no more factors, skip to end */
|
||||
}
|
||||
n /= p;
|
||||
#ifdef RADIX_TWO_ONLY
|
||||
if (p!=2 && p != 4)
|
||||
#else
|
||||
if (p>5)
|
||||
#endif
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*facbuf++ = p;
|
||||
*facbuf++ = n;
|
||||
} while (n > 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
for (i=0;i<nfft;++i) {
|
||||
opus_val32 phase = -i;
|
||||
kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
|
||||
}
|
||||
#else
|
||||
for (i=0;i<nfft;++i) {
|
||||
const double pi=3.14159265358979323846264338327;
|
||||
double phase = ( -2*pi /nfft ) * i;
|
||||
kf_cexp(twiddles+i, phase );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Allocates all necessary storage space for the fft and ifft.
|
||||
* The return value is a contiguous block of memory. As such,
|
||||
* It can be freed with free().
|
||||
* */
|
||||
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base)
|
||||
{
|
||||
kiss_fft_state *st=NULL;
|
||||
size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
|
||||
|
||||
if ( lenmem==NULL ) {
|
||||
st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
|
||||
}else{
|
||||
if (mem != NULL && *lenmem >= memneeded)
|
||||
st = (kiss_fft_state*)mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (st) {
|
||||
opus_int16 *bitrev;
|
||||
kiss_twiddle_cpx *twiddles;
|
||||
|
||||
st->nfft=nfft;
|
||||
#ifndef FIXED_POINT
|
||||
st->scale = 1.f/nfft;
|
||||
#endif
|
||||
if (base != NULL)
|
||||
{
|
||||
st->twiddles = base->twiddles;
|
||||
st->shift = 0;
|
||||
while (nfft<<st->shift != base->nfft && st->shift < 32)
|
||||
st->shift++;
|
||||
if (st->shift>=32)
|
||||
goto fail;
|
||||
} else {
|
||||
st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
|
||||
compute_twiddles(twiddles, nfft);
|
||||
st->shift = -1;
|
||||
}
|
||||
if (!kf_factor(nfft,st->factors))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitrev */
|
||||
st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
|
||||
if (st->bitrev==NULL)
|
||||
goto fail;
|
||||
compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
|
||||
}
|
||||
return st;
|
||||
fail:
|
||||
opus_fft_free(st);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem )
|
||||
{
|
||||
return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL);
|
||||
}
|
||||
|
||||
void opus_fft_free(const kiss_fft_state *cfg)
|
||||
{
|
||||
if (cfg)
|
||||
{
|
||||
opus_free((opus_int16*)cfg->bitrev);
|
||||
if (cfg->shift < 0)
|
||||
opus_free((kiss_twiddle_cpx*)cfg->twiddles);
|
||||
opus_free((kiss_fft_state*)cfg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
void opus_fft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
int m2, m;
|
||||
int p;
|
||||
int L;
|
||||
int fstride[MAXFACTORS];
|
||||
int i;
|
||||
int shift;
|
||||
|
||||
/* st->shift can be -1 */
|
||||
shift = st->shift>0 ? st->shift : 0;
|
||||
|
||||
celt_assert2 (fin != fout, "In-place FFT not supported");
|
||||
/* Bit-reverse the input */
|
||||
for (i=0;i<st->nfft;i++)
|
||||
{
|
||||
fout[st->bitrev[i]] = fin[i];
|
||||
#ifndef FIXED_POINT
|
||||
fout[st->bitrev[i]].r *= st->scale;
|
||||
fout[st->bitrev[i]].i *= st->scale;
|
||||
#endif
|
||||
}
|
||||
|
||||
fstride[0] = 1;
|
||||
L=0;
|
||||
do {
|
||||
p = st->factors[2*L];
|
||||
m = st->factors[2*L+1];
|
||||
fstride[L+1] = fstride[L]*p;
|
||||
L++;
|
||||
} while(m!=1);
|
||||
m = st->factors[2*L-1];
|
||||
for (i=L-1;i>=0;i--)
|
||||
{
|
||||
if (i!=0)
|
||||
m2 = st->factors[2*i-1];
|
||||
else
|
||||
m2 = 1;
|
||||
switch (st->factors[2*i])
|
||||
{
|
||||
case 2:
|
||||
kf_bfly2(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
case 4:
|
||||
kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
case 3:
|
||||
kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
case 5:
|
||||
kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
m = m2;
|
||||
}
|
||||
}
|
||||
|
||||
void opus_ifft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
int m2, m;
|
||||
int p;
|
||||
int L;
|
||||
int fstride[MAXFACTORS];
|
||||
int i;
|
||||
int shift;
|
||||
|
||||
/* st->shift can be -1 */
|
||||
shift = st->shift>0 ? st->shift : 0;
|
||||
celt_assert2 (fin != fout, "In-place FFT not supported");
|
||||
/* Bit-reverse the input */
|
||||
for (i=0;i<st->nfft;i++)
|
||||
fout[st->bitrev[i]] = fin[i];
|
||||
|
||||
fstride[0] = 1;
|
||||
L=0;
|
||||
do {
|
||||
p = st->factors[2*L];
|
||||
m = st->factors[2*L+1];
|
||||
fstride[L+1] = fstride[L]*p;
|
||||
L++;
|
||||
} while(m!=1);
|
||||
m = st->factors[2*L-1];
|
||||
for (i=L-1;i>=0;i--)
|
||||
{
|
||||
if (i!=0)
|
||||
m2 = st->factors[2*i-1];
|
||||
else
|
||||
m2 = 1;
|
||||
switch (st->factors[2*i])
|
||||
{
|
||||
case 2:
|
||||
ki_bfly2(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
case 4:
|
||||
ki_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
case 3:
|
||||
ki_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
case 5:
|
||||
ki_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
m = m2;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*Copyright (c) 2003-2004, Mark Borgerding
|
||||
Lots of modifications by Jean-Marc Valin
|
||||
Copyright (c) 2005-2007, Xiph.Org Foundation
|
||||
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
#ifndef KISS_FFT_H
|
||||
#define KISS_FFT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "arch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIMD
|
||||
# include <xmmintrin.h>
|
||||
# define kiss_fft_scalar __m128
|
||||
#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
|
||||
#else
|
||||
#define KISS_FFT_MALLOC opus_alloc
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#include "arch.h"
|
||||
|
||||
# define kiss_fft_scalar opus_int32
|
||||
# define kiss_twiddle_scalar opus_int16
|
||||
|
||||
|
||||
#else
|
||||
# ifndef kiss_fft_scalar
|
||||
/* default is float */
|
||||
# define kiss_fft_scalar float
|
||||
# define kiss_twiddle_scalar float
|
||||
# define KF_SUFFIX _celt_single
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kiss_fft_scalar r;
|
||||
kiss_fft_scalar i;
|
||||
}kiss_fft_cpx;
|
||||
|
||||
typedef struct {
|
||||
kiss_twiddle_scalar r;
|
||||
kiss_twiddle_scalar i;
|
||||
}kiss_twiddle_cpx;
|
||||
|
||||
#define MAXFACTORS 8
|
||||
/* e.g. an fft of length 128 has 4 factors
|
||||
as far as kissfft is concerned
|
||||
4*4*4*2
|
||||
*/
|
||||
|
||||
typedef struct kiss_fft_state{
|
||||
int nfft;
|
||||
#ifndef FIXED_POINT
|
||||
kiss_fft_scalar scale;
|
||||
#endif
|
||||
int shift;
|
||||
opus_int16 factors[2*MAXFACTORS];
|
||||
const opus_int16 *bitrev;
|
||||
const kiss_twiddle_cpx *twiddles;
|
||||
} kiss_fft_state;
|
||||
|
||||
/*typedef struct kiss_fft_state* kiss_fft_cfg;*/
|
||||
|
||||
/**
|
||||
* opus_fft_alloc
|
||||
*
|
||||
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||
*
|
||||
* typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL);
|
||||
*
|
||||
* The return value from fft_alloc is a cfg buffer used internally
|
||||
* by the fft routine or NULL.
|
||||
*
|
||||
* If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc.
|
||||
* The returned value should be free()d when done to avoid memory leaks.
|
||||
*
|
||||
* The state can be placed in a user supplied buffer 'mem':
|
||||
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
|
||||
* then the function places the cfg in mem and the size used in *lenmem
|
||||
* and returns mem.
|
||||
*
|
||||
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
|
||||
* then the function returns NULL and places the minimum cfg
|
||||
* buffer size in *lenmem.
|
||||
* */
|
||||
|
||||
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base);
|
||||
|
||||
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem);
|
||||
|
||||
/**
|
||||
* opus_fft(cfg,in_out_buf)
|
||||
*
|
||||
* Perform an FFT on a complex input buffer.
|
||||
* for a forward FFT,
|
||||
* fin should be f[0] , f[1] , ... ,f[nfft-1]
|
||||
* fout will be F[0] , F[1] , ... ,F[nfft-1]
|
||||
* Note that each element is complex and can be accessed like
|
||||
f[k].r and f[k].i
|
||||
* */
|
||||
void opus_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
void opus_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
void opus_fft_free(const kiss_fft_state *cfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/* Copyright (c) 2007 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "laplace.h"
|
||||
#include "mathops.h"
|
||||
|
||||
/* The minimum probability of an energy delta (out of 32768). */
|
||||
#define LAPLACE_LOG_MINP (0)
|
||||
#define LAPLACE_MINP (1<<LAPLACE_LOG_MINP)
|
||||
/* The minimum number of guaranteed representable energy deltas (in one
|
||||
direction). */
|
||||
#define LAPLACE_NMIN (16)
|
||||
|
||||
/* When called, decay is positive and at most 11456. */
|
||||
static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
|
||||
{
|
||||
unsigned ft;
|
||||
ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
|
||||
return ft*(opus_int32)(16384-decay)>>15;
|
||||
}
|
||||
|
||||
void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
|
||||
{
|
||||
unsigned fl;
|
||||
int val = *value;
|
||||
fl = 0;
|
||||
if (val)
|
||||
{
|
||||
int s;
|
||||
int i;
|
||||
s = -(val<0);
|
||||
val = (val+s)^s;
|
||||
fl = fs;
|
||||
fs = ec_laplace_get_freq1(fs, decay);
|
||||
/* Search the decaying part of the PDF.*/
|
||||
for (i=1; fs > 0 && i < val; i++)
|
||||
{
|
||||
fs *= 2;
|
||||
fl += fs+2*LAPLACE_MINP;
|
||||
fs = (fs*(opus_int32)decay)>>15;
|
||||
}
|
||||
/* Everything beyond that has probability LAPLACE_MINP. */
|
||||
if (!fs)
|
||||
{
|
||||
int di;
|
||||
int ndi_max;
|
||||
ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
|
||||
ndi_max = (ndi_max-s)>>1;
|
||||
di = IMIN(val - i, ndi_max - 1);
|
||||
fl += (2*di+1+s)*LAPLACE_MINP;
|
||||
fs = IMIN(LAPLACE_MINP, 32768-fl);
|
||||
*value = (i+di+s)^s;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs += LAPLACE_MINP;
|
||||
fl += fs&~s;
|
||||
}
|
||||
celt_assert(fl+fs<=32768);
|
||||
celt_assert(fs>0);
|
||||
}
|
||||
ec_encode_bin(enc, fl, fl+fs, 15);
|
||||
}
|
||||
|
||||
int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
|
||||
{
|
||||
int val=0;
|
||||
unsigned fl;
|
||||
unsigned fm;
|
||||
fm = ec_decode_bin(dec, 15);
|
||||
fl = 0;
|
||||
if (fm >= fs)
|
||||
{
|
||||
val++;
|
||||
fl = fs;
|
||||
fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP;
|
||||
/* Search the decaying part of the PDF.*/
|
||||
while(fs > LAPLACE_MINP && fm >= fl+2*fs)
|
||||
{
|
||||
fs *= 2;
|
||||
fl += fs;
|
||||
fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15;
|
||||
fs += LAPLACE_MINP;
|
||||
val++;
|
||||
}
|
||||
/* Everything beyond that has probability LAPLACE_MINP. */
|
||||
if (fs <= LAPLACE_MINP)
|
||||
{
|
||||
int di;
|
||||
di = (fm-fl)>>(LAPLACE_LOG_MINP+1);
|
||||
val += di;
|
||||
fl += 2*di*LAPLACE_MINP;
|
||||
}
|
||||
if (fm < fl+fs)
|
||||
val = -val;
|
||||
else
|
||||
fl += fs;
|
||||
}
|
||||
celt_assert(fl<32768);
|
||||
celt_assert(fs>0);
|
||||
celt_assert(fl<=fm);
|
||||
celt_assert(fm<IMIN(fl+fs,32768));
|
||||
ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
|
||||
return val;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2007 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
/** Encode a value that is assumed to be the realisation of a
|
||||
Laplace-distributed random process
|
||||
@param enc Entropy encoder state
|
||||
@param value Value to encode
|
||||
@param fs Probability of 0, multiplied by 32768
|
||||
@param decay Probability of the value +/- 1, multiplied by 16384
|
||||
*/
|
||||
void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay);
|
||||
|
||||
/** Decode a value that is assumed to be the realisation of a
|
||||
Laplace-distributed random process
|
||||
@param dec Entropy decoder state
|
||||
@param fs Probability of 0, multiplied by 32768
|
||||
@param decay Probability of the value +/- 1, multiplied by 16384
|
||||
@return Value decoded
|
||||
*/
|
||||
int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay);
|
|
@ -0,0 +1,206 @@
|
|||
/* Copyright (c) 2002-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file mathops.h
|
||||
@brief Various math functions
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mathops.h"
|
||||
|
||||
/*Compute floor(sqrt(_val)) with exact arithmetic.
|
||||
This has been tested on all possible 32-bit inputs.*/
|
||||
unsigned isqrt32(opus_uint32 _val){
|
||||
unsigned b;
|
||||
unsigned g;
|
||||
int bshift;
|
||||
/*Uses the second method from
|
||||
http://www.azillionmonkeys.com/qed/sqroot.html
|
||||
The main idea is to search for the largest binary digit b such that
|
||||
(g+b)*(g+b) <= _val, and add it to the solution g.*/
|
||||
g=0;
|
||||
bshift=(EC_ILOG(_val)-1)>>1;
|
||||
b=1U<<bshift;
|
||||
do{
|
||||
opus_uint32 t;
|
||||
t=(((opus_uint32)g<<1)+b)<<bshift;
|
||||
if(t<=_val){
|
||||
g+=b;
|
||||
_val-=t;
|
||||
}
|
||||
b>>=1;
|
||||
bshift--;
|
||||
}
|
||||
while(bshift>=0);
|
||||
return g;
|
||||
}
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
opus_val32 frac_div32(opus_val32 a, opus_val32 b)
|
||||
{
|
||||
opus_val16 rcp;
|
||||
opus_val32 result, rem;
|
||||
int shift = celt_ilog2(b)-29;
|
||||
a = VSHR32(a,shift);
|
||||
b = VSHR32(b,shift);
|
||||
/* 16-bit reciprocal */
|
||||
rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
|
||||
result = MULT16_32_Q15(rcp, a);
|
||||
rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
|
||||
result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
|
||||
if (result >= 536870912) /* 2^29 */
|
||||
return 2147483647; /* 2^31 - 1 */
|
||||
else if (result <= -536870912) /* -2^29 */
|
||||
return -2147483647; /* -2^31 */
|
||||
else
|
||||
return SHL32(result, 2);
|
||||
}
|
||||
|
||||
/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */
|
||||
opus_val16 celt_rsqrt_norm(opus_val32 x)
|
||||
{
|
||||
opus_val16 n;
|
||||
opus_val16 r;
|
||||
opus_val16 r2;
|
||||
opus_val16 y;
|
||||
/* Range of n is [-16384,32767] ([-0.5,1) in Q15). */
|
||||
n = x-32768;
|
||||
/* Get a rough initial guess for the root.
|
||||
The optimal minimax quadratic approximation (using relative error) is
|
||||
r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485).
|
||||
Coefficients here, and the final result r, are Q14.*/
|
||||
r = ADD16(23557, MULT16_16_Q15(n, ADD16(-13490, MULT16_16_Q15(n, 6713))));
|
||||
/* We want y = x*r*r-1 in Q15, but x is 32-bit Q16 and r is Q14.
|
||||
We can compute the result from n and r using Q15 multiplies with some
|
||||
adjustment, carefully done to avoid overflow.
|
||||
Range of y is [-1564,1594]. */
|
||||
r2 = MULT16_16_Q15(r, r);
|
||||
y = SHL16(SUB16(ADD16(MULT16_16_Q15(r2, n), r2), 16384), 1);
|
||||
/* Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5).
|
||||
This yields the Q14 reciprocal square root of the Q16 x, with a maximum
|
||||
relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a
|
||||
peak absolute error of 2.26591/16384. */
|
||||
return ADD16(r, MULT16_16_Q15(r, MULT16_16_Q15(y,
|
||||
SUB16(MULT16_16_Q15(y, 12288), 16384))));
|
||||
}
|
||||
|
||||
/** Sqrt approximation (QX input, QX/2 output) */
|
||||
opus_val32 celt_sqrt(opus_val32 x)
|
||||
{
|
||||
int k;
|
||||
opus_val16 n;
|
||||
opus_val32 rt;
|
||||
static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664};
|
||||
if (x==0)
|
||||
return 0;
|
||||
k = (celt_ilog2(x)>>1)-7;
|
||||
x = VSHR32(x, 2*k);
|
||||
n = x-32768;
|
||||
rt = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2],
|
||||
MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, (C[4])))))))));
|
||||
rt = VSHR32(rt,7-k);
|
||||
return rt;
|
||||
}
|
||||
|
||||
#define L1 32767
|
||||
#define L2 -7651
|
||||
#define L3 8277
|
||||
#define L4 -626
|
||||
|
||||
static inline opus_val16 _celt_cos_pi_2(opus_val16 x)
|
||||
{
|
||||
opus_val16 x2;
|
||||
|
||||
x2 = MULT16_16_P15(x,x);
|
||||
return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2
|
||||
))))))));
|
||||
}
|
||||
|
||||
#undef L1
|
||||
#undef L2
|
||||
#undef L3
|
||||
#undef L4
|
||||
|
||||
opus_val16 celt_cos_norm(opus_val32 x)
|
||||
{
|
||||
x = x&0x0001ffff;
|
||||
if (x>SHL32(EXTEND32(1), 16))
|
||||
x = SUB32(SHL32(EXTEND32(1), 17),x);
|
||||
if (x&0x00007fff)
|
||||
{
|
||||
if (x<SHL32(EXTEND32(1), 15))
|
||||
{
|
||||
return _celt_cos_pi_2(EXTRACT16(x));
|
||||
} else {
|
||||
return NEG32(_celt_cos_pi_2(EXTRACT16(65536-x)));
|
||||
}
|
||||
} else {
|
||||
if (x&0x0000ffff)
|
||||
return 0;
|
||||
else if (x&0x0001ffff)
|
||||
return -32767;
|
||||
else
|
||||
return 32767;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reciprocal approximation (Q15 input, Q16 output) */
|
||||
opus_val32 celt_rcp(opus_val32 x)
|
||||
{
|
||||
int i;
|
||||
opus_val16 n;
|
||||
opus_val16 r;
|
||||
celt_assert2(x>0, "celt_rcp() only defined for positive values");
|
||||
i = celt_ilog2(x);
|
||||
/* n is Q15 with range [0,1). */
|
||||
n = VSHR32(x,i-15)-32768;
|
||||
/* Start with a linear approximation:
|
||||
r = 1.8823529411764706-0.9411764705882353*n.
|
||||
The coefficients and the result are Q14 in the range [15420,30840].*/
|
||||
r = ADD16(30840, MULT16_16_Q15(-15420, n));
|
||||
/* Perform two Newton iterations:
|
||||
r -= r*((r*n)-1.Q15)
|
||||
= r*((r*n)+(r-1.Q15)). */
|
||||
r = SUB16(r, MULT16_16_Q15(r,
|
||||
ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768))));
|
||||
/* We subtract an extra 1 in the second iteration to avoid overflow; it also
|
||||
neatly compensates for truncation error in the rest of the process. */
|
||||
r = SUB16(r, ADD16(1, MULT16_16_Q15(r,
|
||||
ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768)))));
|
||||
/* r is now the Q15 solution to 2/(n+1), with a maximum relative error
|
||||
of 7.05346E-5, a (relative) RMSE of 2.14418E-5, and a peak absolute
|
||||
error of 1.24665/32768. */
|
||||
return VSHR32(EXTEND32(r),i-16);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,237 @@
|
|||
/* Copyright (c) 2002-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file mathops.h
|
||||
@brief Various math functions
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MATHOPS_H
|
||||
#define MATHOPS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "entcode.h"
|
||||
#include "os_support.h"
|
||||
|
||||
/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
|
||||
#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
|
||||
|
||||
unsigned isqrt32(opus_uint32 _val);
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
|
||||
#define PI 3.141592653f
|
||||
#define celt_sqrt(x) ((float)sqrt(x))
|
||||
#define celt_rsqrt(x) (1.f/celt_sqrt(x))
|
||||
#define celt_rsqrt_norm(x) (celt_rsqrt(x))
|
||||
#define celt_cos_norm(x) ((float)cos((.5f*PI)*(x)))
|
||||
#define celt_rcp(x) (1.f/(x))
|
||||
#define celt_div(a,b) ((a)/(b))
|
||||
#define frac_div32(a,b) ((float)(a)/(b))
|
||||
|
||||
#ifdef FLOAT_APPROX
|
||||
|
||||
/* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127
|
||||
denorm, +/- inf and NaN are *not* handled */
|
||||
|
||||
/** Base-2 log approximation (log2(x)). */
|
||||
static inline float celt_log2(float x)
|
||||
{
|
||||
int integer;
|
||||
float frac;
|
||||
union {
|
||||
float f;
|
||||
opus_uint32 i;
|
||||
} in;
|
||||
in.f = x;
|
||||
integer = (in.i>>23)-127;
|
||||
in.i -= integer<<23;
|
||||
frac = in.f - 1.5f;
|
||||
frac = -0.41445418f + frac*(0.95909232f
|
||||
+ frac*(-0.33951290f + frac*0.16541097f));
|
||||
return 1+integer+frac;
|
||||
}
|
||||
|
||||
/** Base-2 exponential approximation (2^x). */
|
||||
static inline float celt_exp2(float x)
|
||||
{
|
||||
int integer;
|
||||
float frac;
|
||||
union {
|
||||
float f;
|
||||
opus_uint32 i;
|
||||
} res;
|
||||
integer = floor(x);
|
||||
if (integer < -50)
|
||||
return 0;
|
||||
frac = x-integer;
|
||||
/* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */
|
||||
res.f = 0.99992522f + frac * (0.69583354f
|
||||
+ frac * (0.22606716f + 0.078024523f*frac));
|
||||
res.i = (res.i + (integer<<23)) & 0x7fffffff;
|
||||
return res.f;
|
||||
}
|
||||
|
||||
#else
|
||||
#define celt_log2(x) ((float)(1.442695040888963387*log(x)))
|
||||
#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
#include "os_support.h"
|
||||
|
||||
#ifndef OVERRIDE_CELT_ILOG2
|
||||
/** Integer log in base2. Undefined for zero and negative numbers */
|
||||
static inline opus_int16 celt_ilog2(opus_int32 x)
|
||||
{
|
||||
celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers");
|
||||
return EC_ILOG(x)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS16
|
||||
static inline opus_val16 celt_maxabs16(opus_val16 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val16 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX16(maxval, ABS16(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS32
|
||||
static inline opus_val32 celt_maxabs32(opus_val32 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val32 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX32(maxval, ABS32(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Integer log in base2. Defined for zero, but not for negative numbers */
|
||||
static inline opus_int16 celt_zlog2(opus_val32 x)
|
||||
{
|
||||
return x <= 0 ? 0 : celt_ilog2(x);
|
||||
}
|
||||
|
||||
opus_val16 celt_rsqrt_norm(opus_val32 x);
|
||||
|
||||
opus_val32 celt_sqrt(opus_val32 x);
|
||||
|
||||
opus_val16 celt_cos_norm(opus_val32 x);
|
||||
|
||||
static inline opus_val16 celt_log2(opus_val32 x)
|
||||
{
|
||||
int i;
|
||||
opus_val16 n, frac;
|
||||
/* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
|
||||
0.15530808010959576, -0.08556153059057618 */
|
||||
static const opus_val16 C[5] = {-6801+(1<<(13-DB_SHIFT)), 15746, -5217, 2545, -1401};
|
||||
if (x==0)
|
||||
return -32767;
|
||||
i = celt_ilog2(x);
|
||||
n = VSHR32(x,i-15)-32768-16384;
|
||||
frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
|
||||
return SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
K0 = 1
|
||||
K1 = log(2)
|
||||
K2 = 3-4*log(2)
|
||||
K3 = 3*log(2) - 2
|
||||
*/
|
||||
#define D0 16383
|
||||
#define D1 22804
|
||||
#define D2 14819
|
||||
#define D3 10204
|
||||
/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
|
||||
static inline opus_val32 celt_exp2(opus_val16 x)
|
||||
{
|
||||
int integer;
|
||||
opus_val16 frac;
|
||||
integer = SHR16(x,10);
|
||||
if (integer>14)
|
||||
return 0x7f000000;
|
||||
else if (integer < -15)
|
||||
return 0;
|
||||
frac = SHL16(x-SHL16(integer,10),4);
|
||||
frac = ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
|
||||
return VSHR32(EXTEND32(frac), -integer-2);
|
||||
}
|
||||
|
||||
opus_val32 celt_rcp(opus_val32 x);
|
||||
|
||||
#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b))
|
||||
|
||||
opus_val32 frac_div32(opus_val32 a, opus_val32 b);
|
||||
|
||||
#define M1 32767
|
||||
#define M2 -21
|
||||
#define M3 -11943
|
||||
#define M4 4936
|
||||
|
||||
/* Atan approximation using a 4th order polynomial. Input is in Q15 format
|
||||
and normalized by pi/4. Output is in Q15 format */
|
||||
static inline opus_val16 celt_atan01(opus_val16 x)
|
||||
{
|
||||
return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
|
||||
}
|
||||
|
||||
#undef M1
|
||||
#undef M2
|
||||
#undef M3
|
||||
#undef M4
|
||||
|
||||
/* atan2() approximation valid for positive input values */
|
||||
static inline opus_val16 celt_atan2p(opus_val16 y, opus_val16 x)
|
||||
{
|
||||
if (y < x)
|
||||
{
|
||||
opus_val32 arg;
|
||||
arg = celt_div(SHL32(EXTEND32(y),15),x);
|
||||
if (arg >= 32767)
|
||||
arg = 32767;
|
||||
return SHR16(celt_atan01(EXTRACT16(arg)),1);
|
||||
} else {
|
||||
opus_val32 arg;
|
||||
arg = celt_div(SHL32(EXTEND32(x),15),y);
|
||||
if (arg >= 32767)
|
||||
arg = 32767;
|
||||
return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT */
|
||||
#endif /* MATHOPS_H */
|
|
@ -0,0 +1,332 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2008 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is a simple MDCT implementation that uses a N/4 complex FFT
|
||||
to do most of the work. It should be relatively straightforward to
|
||||
plug in pretty much and FFT here.
|
||||
|
||||
This replaces the Vorbis FFT (and uses the exact same API), which
|
||||
was a bit too messy and that was ending up duplicating code
|
||||
(might as well use the same FFT everywhere).
|
||||
|
||||
The algorithm is similar to (and inspired from) Fabrice Bellard's
|
||||
MDCT implementation in FFMPEG, but has differences in signs, ordering
|
||||
and scaling in many places.
|
||||
*/
|
||||
|
||||
#ifndef SKIP_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mdct.h"
|
||||
#include "kiss_fft.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
#include <math.h>
|
||||
#include "os_support.h"
|
||||
#include "mathops.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
int clt_mdct_init(mdct_lookup *l,int N, int maxshift)
|
||||
{
|
||||
int i;
|
||||
int N4;
|
||||
kiss_twiddle_scalar *trig;
|
||||
#if defined(FIXED_POINT)
|
||||
int N2=N>>1;
|
||||
#endif
|
||||
l->n = N;
|
||||
N4 = N>>2;
|
||||
l->maxshift = maxshift;
|
||||
for (i=0;i<=maxshift;i++)
|
||||
{
|
||||
if (i==0)
|
||||
l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0);
|
||||
else
|
||||
l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0]);
|
||||
#ifndef ENABLE_TI_DSPLIB55
|
||||
if (l->kfft[i]==NULL)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N4+1)*sizeof(kiss_twiddle_scalar));
|
||||
if (l->trig==NULL)
|
||||
return 0;
|
||||
/* We have enough points that sine isn't necessary */
|
||||
#if defined(FIXED_POINT)
|
||||
for (i=0;i<=N4;i++)
|
||||
trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2),N));
|
||||
#else
|
||||
for (i=0;i<=N4;i++)
|
||||
trig[i] = (kiss_twiddle_scalar)cos(2*PI*i/N);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void clt_mdct_clear(mdct_lookup *l)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<=l->maxshift;i++)
|
||||
opus_fft_free(l->kfft[i]);
|
||||
opus_free((kiss_twiddle_scalar*)l->trig);
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
/* Forward MDCT trashes the input array */
|
||||
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window, int overlap, int shift, int stride)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
kiss_twiddle_scalar sine;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
SAVE_STACK;
|
||||
N = l->n;
|
||||
N >>= shift;
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
/* sin(x) ~= x here */
|
||||
#ifdef FIXED_POINT
|
||||
sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N;
|
||||
#else
|
||||
sine = (kiss_twiddle_scalar)2*PI*(.125f)/N;
|
||||
#endif
|
||||
|
||||
/* Consider the input to be composed of four blocks: [a, b, c, d] */
|
||||
/* Window, shuffle, fold */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f;
|
||||
const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
|
||||
const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
|
||||
for(i=0;i<(overlap>>2);i++)
|
||||
{
|
||||
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
|
||||
*yp++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2);
|
||||
*yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]);
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
wp1+=2;
|
||||
wp2-=2;
|
||||
}
|
||||
wp1 = window;
|
||||
wp2 = window+overlap-1;
|
||||
for(;i<N4-(overlap>>2);i++)
|
||||
{
|
||||
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
|
||||
*yp++ = *xp2;
|
||||
*yp++ = *xp1;
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
}
|
||||
for(;i<N4;i++)
|
||||
{
|
||||
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
|
||||
*yp++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2);
|
||||
*yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]);
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
wp1+=2;
|
||||
wp2-=2;
|
||||
}
|
||||
}
|
||||
/* Pre-rotation */
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
re = yp[0];
|
||||
im = yp[1];
|
||||
yr = -S_MUL(re,t[i<<shift]) - S_MUL(im,t[(N4-i)<<shift]);
|
||||
yi = -S_MUL(im,t[i<<shift]) + S_MUL(re,t[(N4-i)<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp++ = yr + S_MUL(yi,sine);
|
||||
*yp++ = yi - S_MUL(yr,sine);
|
||||
}
|
||||
}
|
||||
|
||||
/* N/4 complex FFT, down-scales by 4/N */
|
||||
opus_fft(l->kfft[shift], (kiss_fft_cpx *)f, (kiss_fft_cpx *)in);
|
||||
|
||||
/* Post-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * OPUS_RESTRICT fp = in;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar yr, yi;
|
||||
yr = S_MUL(fp[1],t[(N4-i)<<shift]) + S_MUL(fp[0],t[i<<shift]);
|
||||
yi = S_MUL(fp[0],t[(N4-i)<<shift]) - S_MUL(fp[1],t[i<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp1 = yr - S_MUL(yi,sine);
|
||||
*yp2 = yi + S_MUL(yr,sine);;
|
||||
fp += 2;
|
||||
yp1 += 2*stride;
|
||||
yp2 -= 2*stride;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
kiss_twiddle_scalar sine;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
VARDECL(kiss_fft_scalar, f2);
|
||||
SAVE_STACK;
|
||||
N = l->n;
|
||||
N >>= shift;
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
ALLOC(f2, N2, kiss_fft_scalar);
|
||||
/* sin(x) ~= x here */
|
||||
#ifdef FIXED_POINT
|
||||
sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N;
|
||||
#else
|
||||
sine = (kiss_twiddle_scalar)2*PI*(.125f)/N;
|
||||
#endif
|
||||
|
||||
/* Pre-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f2;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar yr, yi;
|
||||
yr = -S_MUL(*xp2, t[i<<shift]) + S_MUL(*xp1,t[(N4-i)<<shift]);
|
||||
yi = -S_MUL(*xp2, t[(N4-i)<<shift]) - S_MUL(*xp1,t[i<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp++ = yr - S_MUL(yi,sine);
|
||||
*yp++ = yi + S_MUL(yr,sine);
|
||||
xp1+=2*stride;
|
||||
xp2-=2*stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inverse N/4 complex FFT. This one should *not* downscale even in fixed-point */
|
||||
opus_ifft(l->kfft[shift], (kiss_fft_cpx *)f2, (kiss_fft_cpx *)f);
|
||||
|
||||
/* Post-rotate */
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT fp = f;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
re = fp[0];
|
||||
im = fp[1];
|
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
|
||||
yr = S_MUL(re,t[i<<shift]) - S_MUL(im,t[(N4-i)<<shift]);
|
||||
yi = S_MUL(im,t[i<<shift]) + S_MUL(re,t[(N4-i)<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*fp++ = yr - S_MUL(yi,sine);
|
||||
*fp++ = yi + S_MUL(yr,sine);
|
||||
}
|
||||
}
|
||||
/* De-shuffle the components for the middle of the window only */
|
||||
{
|
||||
const kiss_fft_scalar * OPUS_RESTRICT fp1 = f;
|
||||
const kiss_fft_scalar * OPUS_RESTRICT fp2 = f+N2-1;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f2;
|
||||
for(i = 0; i < N4; i++)
|
||||
{
|
||||
*yp++ =-*fp1;
|
||||
*yp++ = *fp2;
|
||||
fp1 += 2;
|
||||
fp2 -= 2;
|
||||
}
|
||||
}
|
||||
out -= (N2-overlap)>>1;
|
||||
/* Mirror on both sides for TDAC */
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT fp1 = f2+N4-1;
|
||||
kiss_fft_scalar * OPUS_RESTRICT xp1 = out+N2-1;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out+N4-overlap/2;
|
||||
const opus_val16 * OPUS_RESTRICT wp1 = window;
|
||||
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
|
||||
for(i = 0; i< N4-overlap/2; i++)
|
||||
{
|
||||
*xp1 = *fp1;
|
||||
xp1--;
|
||||
fp1--;
|
||||
}
|
||||
for(; i < N4; i++)
|
||||
{
|
||||
kiss_fft_scalar x1;
|
||||
x1 = *fp1--;
|
||||
*yp1++ +=-MULT16_32_Q15(*wp1, x1);
|
||||
*xp1-- += MULT16_32_Q15(*wp2, x1);
|
||||
wp1++;
|
||||
wp2--;
|
||||
}
|
||||
}
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT fp2 = f2+N4;
|
||||
kiss_fft_scalar * OPUS_RESTRICT xp2 = out+N2;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp2 = out+N-1-(N4-overlap/2);
|
||||
const opus_val16 * OPUS_RESTRICT wp1 = window;
|
||||
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
|
||||
for(i = 0; i< N4-overlap/2; i++)
|
||||
{
|
||||
*xp2 = *fp2;
|
||||
xp2++;
|
||||
fp2++;
|
||||
}
|
||||
for(; i < N4; i++)
|
||||
{
|
||||
kiss_fft_scalar x2;
|
||||
x2 = *fp2++;
|
||||
*yp2-- = MULT16_32_Q15(*wp1, x2);
|
||||
*xp2++ = MULT16_32_Q15(*wp2, x2);
|
||||
wp1++;
|
||||
wp2--;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2008 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is a simple MDCT implementation that uses a N/4 complex FFT
|
||||
to do most of the work. It should be relatively straightforward to
|
||||
plug in pretty much and FFT here.
|
||||
|
||||
This replaces the Vorbis FFT (and uses the exact same API), which
|
||||
was a bit too messy and that was ending up duplicating code
|
||||
(might as well use the same FFT everywhere).
|
||||
|
||||
The algorithm is similar to (and inspired from) Fabrice Bellard's
|
||||
MDCT implementation in FFMPEG, but has differences in signs, ordering
|
||||
and scaling in many places.
|
||||
*/
|
||||
|
||||
#ifndef MDCT_H
|
||||
#define MDCT_H
|
||||
|
||||
#include "opus_defines.h"
|
||||
#include "kiss_fft.h"
|
||||
#include "arch.h"
|
||||
|
||||
typedef struct {
|
||||
int n;
|
||||
int maxshift;
|
||||
const kiss_fft_state *kfft[4];
|
||||
const kiss_twiddle_scalar * OPUS_RESTRICT trig;
|
||||
} mdct_lookup;
|
||||
|
||||
int clt_mdct_init(mdct_lookup *l,int N, int maxshift);
|
||||
void clt_mdct_clear(mdct_lookup *l);
|
||||
|
||||
/** Compute a forward MDCT and scale by 4/N, trashes the input array */
|
||||
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window, int overlap, int shift, int stride);
|
||||
|
||||
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
|
||||
(scales implicitly by 1/2) */
|
||||
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2001-2008 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_mfrngcode_H)
|
||||
# define _mfrngcode_H (1)
|
||||
# include "entcode.h"
|
||||
|
||||
/*Constants used by the entropy encoder/decoder.*/
|
||||
|
||||
/*The number of bits to output at a time.*/
|
||||
# define EC_SYM_BITS (8)
|
||||
/*The total number of bits in each of the state registers.*/
|
||||
# define EC_CODE_BITS (32)
|
||||
/*The maximum symbol value.*/
|
||||
# define EC_SYM_MAX ((1U<<EC_SYM_BITS)-1)
|
||||
/*Bits to shift by to move a symbol into the high-order position.*/
|
||||
# define EC_CODE_SHIFT (EC_CODE_BITS-EC_SYM_BITS-1)
|
||||
/*Carry bit of the high-order range symbol.*/
|
||||
# define EC_CODE_TOP (((opus_uint32)1U)<<(EC_CODE_BITS-1))
|
||||
/*Low-order bit of the high-order range symbol.*/
|
||||
# define EC_CODE_BOT (EC_CODE_TOP>>EC_SYM_BITS)
|
||||
/*The number of bits available for the last, partial symbol in the code field.*/
|
||||
# define EC_CODE_EXTRA ((EC_CODE_BITS-2)%EC_SYM_BITS+1)
|
||||
#endif
|
|
@ -0,0 +1,430 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt.h"
|
||||
#include "modes.h"
|
||||
#include "rate.h"
|
||||
#include "os_support.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "quant_bands.h"
|
||||
|
||||
static const opus_int16 eband5ms[] = {
|
||||
/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
|
||||
};
|
||||
|
||||
/* Alternate tuning (partially derived from Vorbis) */
|
||||
#define BITALLOC_SIZE 11
|
||||
/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
|
||||
static const unsigned char band_allocation[] = {
|
||||
/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0,
|
||||
118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0,
|
||||
126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0,
|
||||
134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1,
|
||||
144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1,
|
||||
152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1,
|
||||
162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1,
|
||||
172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
|
||||
200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,
|
||||
};
|
||||
|
||||
#ifndef CUSTOM_MODES_ONLY
|
||||
#ifdef FIXED_POINT
|
||||
#include "static_modes_fixed.h"
|
||||
#else
|
||||
#include "static_modes_float.h"
|
||||
#endif
|
||||
#endif /* CUSTOM_MODES_ONLY */
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.141592653
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
|
||||
Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
|
||||
#define BARK_BANDS 25
|
||||
static const opus_int16 bark_freq[BARK_BANDS+1] = {
|
||||
0, 100, 200, 300, 400,
|
||||
510, 630, 770, 920, 1080,
|
||||
1270, 1480, 1720, 2000, 2320,
|
||||
2700, 3150, 3700, 4400, 5300,
|
||||
6400, 7700, 9500, 12000, 15500,
|
||||
20000};
|
||||
|
||||
static opus_int16 *compute_ebands(opus_int32 Fs, int frame_size, int res, int *nbEBands)
|
||||
{
|
||||
opus_int16 *eBands;
|
||||
int i, j, lin, low, high, nBark, offset=0;
|
||||
|
||||
/* All modes that have 2.5 ms short blocks use the same definition */
|
||||
if (Fs == 400*(opus_int32)frame_size)
|
||||
{
|
||||
*nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
|
||||
eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+1));
|
||||
for (i=0;i<*nbEBands+1;i++)
|
||||
eBands[i] = eband5ms[i];
|
||||
return eBands;
|
||||
}
|
||||
/* Find the number of critical bands supported by our sampling rate */
|
||||
for (nBark=1;nBark<BARK_BANDS;nBark++)
|
||||
if (bark_freq[nBark+1]*2 >= Fs)
|
||||
break;
|
||||
|
||||
/* Find where the linear part ends (i.e. where the spacing is more than min_width */
|
||||
for (lin=0;lin<nBark;lin++)
|
||||
if (bark_freq[lin+1]-bark_freq[lin] >= res)
|
||||
break;
|
||||
|
||||
low = (bark_freq[lin]+res/2)/res;
|
||||
high = nBark-lin;
|
||||
*nbEBands = low+high;
|
||||
eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+2));
|
||||
|
||||
if (eBands==NULL)
|
||||
return NULL;
|
||||
|
||||
/* Linear spacing (min_width) */
|
||||
for (i=0;i<low;i++)
|
||||
eBands[i] = i;
|
||||
if (low>0)
|
||||
offset = eBands[low-1]*res - bark_freq[lin-1];
|
||||
/* Spacing follows critical bands */
|
||||
for (i=0;i<high;i++)
|
||||
{
|
||||
int target = bark_freq[lin+i];
|
||||
/* Round to an even value */
|
||||
eBands[i+low] = (target+offset/2+res)/(2*res)*2;
|
||||
offset = eBands[i+low]*res - target;
|
||||
}
|
||||
/* Enforce the minimum spacing at the boundary */
|
||||
for (i=0;i<*nbEBands;i++)
|
||||
if (eBands[i] < i)
|
||||
eBands[i] = i;
|
||||
/* Round to an even value */
|
||||
eBands[*nbEBands] = (bark_freq[nBark]+res)/(2*res)*2;
|
||||
if (eBands[*nbEBands] > frame_size)
|
||||
eBands[*nbEBands] = frame_size;
|
||||
for (i=1;i<*nbEBands-1;i++)
|
||||
{
|
||||
if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
|
||||
{
|
||||
eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
|
||||
}
|
||||
}
|
||||
/* Remove any empty bands. */
|
||||
for (i=j=0;i<*nbEBands;i++)
|
||||
if(eBands[i+1]>eBands[j])
|
||||
eBands[++j]=eBands[i+1];
|
||||
*nbEBands=j;
|
||||
|
||||
for (i=1;i<*nbEBands;i++)
|
||||
{
|
||||
/* Every band must be smaller than the last band. */
|
||||
celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]);
|
||||
/* Each band must be no larger than twice the size of the previous one. */
|
||||
celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1]));
|
||||
}
|
||||
|
||||
return eBands;
|
||||
}
|
||||
|
||||
static void compute_allocation_table(CELTMode *mode)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *allocVectors;
|
||||
int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
|
||||
|
||||
mode->nbAllocVectors = BITALLOC_SIZE;
|
||||
allocVectors = opus_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
|
||||
if (allocVectors==NULL)
|
||||
return;
|
||||
|
||||
/* Check for standard mode */
|
||||
if (mode->Fs == 400*(opus_int32)mode->shortMdctSize)
|
||||
{
|
||||
for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
|
||||
allocVectors[i] = band_allocation[i];
|
||||
mode->allocVectors = allocVectors;
|
||||
return;
|
||||
}
|
||||
/* If not the standard mode, interpolate */
|
||||
/* Compute per-codec-band allocation from per-critical-band matrix */
|
||||
for (i=0;i<BITALLOC_SIZE;i++)
|
||||
{
|
||||
for (j=0;j<mode->nbEBands;j++)
|
||||
{
|
||||
int k;
|
||||
for (k=0;k<maxBands;k++)
|
||||
{
|
||||
if (400*(opus_int32)eband5ms[k] > mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize)
|
||||
break;
|
||||
}
|
||||
if (k>maxBands-1)
|
||||
allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
|
||||
else {
|
||||
opus_int32 a0, a1;
|
||||
a1 = mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize - 400*(opus_int32)eband5ms[k-1];
|
||||
a0 = 400*(opus_int32)eband5ms[k] - mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize;
|
||||
allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
|
||||
+ a1*band_allocation[i*maxBands+k])/(a0+a1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*printf ("\n");
|
||||
for (i=0;i<BITALLOC_SIZE;i++)
|
||||
{
|
||||
for (j=0;j<mode->nbEBands;j++)
|
||||
printf ("%d ", allocVectors[i*mode->nbEBands+j]);
|
||||
printf ("\n");
|
||||
}
|
||||
exit(0);*/
|
||||
|
||||
mode->allocVectors = allocVectors;
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
|
||||
{
|
||||
int i;
|
||||
#ifdef CUSTOM_MODES
|
||||
CELTMode *mode=NULL;
|
||||
int res;
|
||||
opus_val16 *window;
|
||||
opus_int16 *logN;
|
||||
int LM;
|
||||
ALLOC_STACK;
|
||||
#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
|
||||
if (global_stack==NULL)
|
||||
goto failure;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_MODES_ONLY
|
||||
for (i=0;i<TOTAL_MODES;i++)
|
||||
{
|
||||
int j;
|
||||
for (j=0;j<4;j++)
|
||||
{
|
||||
if (Fs == static_mode_list[i]->Fs &&
|
||||
(frame_size<<j) == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
|
||||
{
|
||||
if (error)
|
||||
*error = OPUS_OK;
|
||||
return (CELTMode*)static_mode_list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES_ONLY */
|
||||
|
||||
#ifndef CUSTOM_MODES
|
||||
if (error)
|
||||
*error = OPUS_BAD_ARG;
|
||||
return NULL;
|
||||
#else
|
||||
|
||||
/* The good thing here is that permutation of the arguments will automatically be invalid */
|
||||
|
||||
if (Fs < 8000 || Fs > 96000)
|
||||
{
|
||||
if (error)
|
||||
*error = OPUS_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
|
||||
{
|
||||
if (error)
|
||||
*error = OPUS_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
/* Frames of less than 1ms are not supported. */
|
||||
if ((opus_int32)frame_size*1000 < Fs)
|
||||
{
|
||||
if (error)
|
||||
*error = OPUS_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((opus_int32)frame_size*75 >= Fs && (frame_size%16)==0)
|
||||
{
|
||||
LM = 3;
|
||||
} else if ((opus_int32)frame_size*150 >= Fs && (frame_size%8)==0)
|
||||
{
|
||||
LM = 2;
|
||||
} else if ((opus_int32)frame_size*300 >= Fs && (frame_size%4)==0)
|
||||
{
|
||||
LM = 1;
|
||||
} else
|
||||
{
|
||||
LM = 0;
|
||||
}
|
||||
|
||||
/* Shorts longer than 3.3ms are not supported. */
|
||||
if ((opus_int32)(frame_size>>LM)*300 > Fs)
|
||||
{
|
||||
if (error)
|
||||
*error = OPUS_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = opus_alloc(sizeof(CELTMode));
|
||||
if (mode==NULL)
|
||||
goto failure;
|
||||
mode->Fs = Fs;
|
||||
|
||||
/* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
|
||||
is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
|
||||
approximate that. */
|
||||
if(Fs < 12000) /* 8 kHz */
|
||||
{
|
||||
mode->preemph[0] = QCONST16(0.3500061035f, 15);
|
||||
mode->preemph[1] = -QCONST16(0.1799926758f, 15);
|
||||
mode->preemph[2] = QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */
|
||||
mode->preemph[3] = QCONST16(3.6765136719f, 13);
|
||||
} else if(Fs < 24000) /* 16 kHz */
|
||||
{
|
||||
mode->preemph[0] = QCONST16(0.6000061035f, 15);
|
||||
mode->preemph[1] = -QCONST16(0.1799926758f, 15);
|
||||
mode->preemph[2] = QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */
|
||||
mode->preemph[3] = QCONST16(2.2598876953f, 13);
|
||||
} else if(Fs < 40000) /* 32 kHz */
|
||||
{
|
||||
mode->preemph[0] = QCONST16(0.7799987793f, 15);
|
||||
mode->preemph[1] = -QCONST16(0.1000061035f, 15);
|
||||
mode->preemph[2] = QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */
|
||||
mode->preemph[3] = QCONST16(1.3333740234f, 13);
|
||||
} else /* 48 kHz */
|
||||
{
|
||||
mode->preemph[0] = QCONST16(0.8500061035f, 15);
|
||||
mode->preemph[1] = QCONST16(0.0f, 15);
|
||||
mode->preemph[2] = QCONST16(1.f, SIG_SHIFT);
|
||||
mode->preemph[3] = QCONST16(1.f, 13);
|
||||
}
|
||||
|
||||
mode->maxLM = LM;
|
||||
mode->nbShortMdcts = 1<<LM;
|
||||
mode->shortMdctSize = frame_size/mode->nbShortMdcts;
|
||||
res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
|
||||
|
||||
mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
|
||||
if (mode->eBands==NULL)
|
||||
goto failure;
|
||||
|
||||
mode->effEBands = mode->nbEBands;
|
||||
while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
|
||||
mode->effEBands--;
|
||||
|
||||
/* Overlap must be divisible by 4 */
|
||||
mode->overlap = ((mode->shortMdctSize>>2)<<2);
|
||||
|
||||
compute_allocation_table(mode);
|
||||
if (mode->allocVectors==NULL)
|
||||
goto failure;
|
||||
|
||||
window = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16));
|
||||
if (window==NULL)
|
||||
goto failure;
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
for (i=0;i<mode->overlap;i++)
|
||||
window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
|
||||
#else
|
||||
for (i=0;i<mode->overlap;i++)
|
||||
window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
|
||||
#endif
|
||||
mode->window = window;
|
||||
|
||||
logN = (opus_int16*)opus_alloc(mode->nbEBands*sizeof(opus_int16));
|
||||
if (logN==NULL)
|
||||
goto failure;
|
||||
|
||||
for (i=0;i<mode->nbEBands;i++)
|
||||
logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
|
||||
mode->logN = logN;
|
||||
|
||||
compute_pulse_cache(mode, mode->maxLM);
|
||||
|
||||
if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts,
|
||||
mode->maxLM) == 0)
|
||||
goto failure;
|
||||
|
||||
if (error)
|
||||
*error = OPUS_OK;
|
||||
|
||||
return mode;
|
||||
failure:
|
||||
if (error)
|
||||
*error = OPUS_ALLOC_FAIL;
|
||||
if (mode!=NULL)
|
||||
opus_custom_mode_destroy(mode);
|
||||
return NULL;
|
||||
#endif /* !CUSTOM_MODES */
|
||||
}
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
void opus_custom_mode_destroy(CELTMode *mode)
|
||||
{
|
||||
if (mode == NULL)
|
||||
return;
|
||||
#ifndef CUSTOM_MODES_ONLY
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<TOTAL_MODES;i++)
|
||||
{
|
||||
if (mode == static_mode_list[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES_ONLY */
|
||||
opus_free((opus_int16*)mode->eBands);
|
||||
opus_free((opus_int16*)mode->allocVectors);
|
||||
|
||||
opus_free((opus_val16*)mode->window);
|
||||
opus_free((opus_int16*)mode->logN);
|
||||
|
||||
opus_free((opus_int16*)mode->cache.index);
|
||||
opus_free((unsigned char*)mode->cache.bits);
|
||||
opus_free((unsigned char*)mode->cache.caps);
|
||||
clt_mdct_clear(&mode->mdct);
|
||||
|
||||
opus_free((CELTMode *)mode);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MODES_H
|
||||
#define MODES_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "celt.h"
|
||||
#include "arch.h"
|
||||
#include "mdct.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
#define MAX_PERIOD 1024
|
||||
|
||||
#ifndef OVERLAP
|
||||
#define OVERLAP(mode) ((mode)->overlap)
|
||||
#endif
|
||||
|
||||
#ifndef FRAMESIZE
|
||||
#define FRAMESIZE(mode) ((mode)->mdctSize)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
const opus_int16 *index;
|
||||
const unsigned char *bits;
|
||||
const unsigned char *caps;
|
||||
} PulseCache;
|
||||
|
||||
/** Mode definition (opaque)
|
||||
@brief Mode definition
|
||||
*/
|
||||
struct OpusCustomMode {
|
||||
opus_int32 Fs;
|
||||
int overlap;
|
||||
|
||||
int nbEBands;
|
||||
int effEBands;
|
||||
opus_val16 preemph[4];
|
||||
const opus_int16 *eBands; /**< Definition for each "pseudo-critical band" */
|
||||
|
||||
int maxLM;
|
||||
int nbShortMdcts;
|
||||
int shortMdctSize;
|
||||
|
||||
int nbAllocVectors; /**< Number of lines in the matrix below */
|
||||
const unsigned char *allocVectors; /**< Number of bits in each band for several rates */
|
||||
const opus_int16 *logN;
|
||||
|
||||
const opus_val16 *window;
|
||||
mdct_lookup mdct;
|
||||
PulseCache cache;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,210 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "opus_custom.h"
|
||||
#include "arch.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_PACKET 1275
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
char *inFile, *outFile;
|
||||
FILE *fin, *fout;
|
||||
OpusCustomMode *mode=NULL;
|
||||
OpusCustomEncoder *enc;
|
||||
OpusCustomDecoder *dec;
|
||||
int len;
|
||||
opus_int32 frame_size, channels, rate;
|
||||
int bytes_per_packet;
|
||||
unsigned char data[MAX_PACKET];
|
||||
int complexity;
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
int i;
|
||||
double rmsd = 0;
|
||||
#endif
|
||||
int count = 0;
|
||||
opus_int32 skip;
|
||||
opus_int16 *in, *out;
|
||||
if (argc != 9 && argc != 8 && argc != 7)
|
||||
{
|
||||
fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
|
||||
" <bytes per packet> [<complexity> [packet loss rate]] "
|
||||
"<input> <output>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rate = (opus_int32)atol(argv[1]);
|
||||
channels = atoi(argv[2]);
|
||||
frame_size = atoi(argv[3]);
|
||||
mode = opus_custom_mode_create(rate, frame_size, NULL);
|
||||
if (mode == NULL)
|
||||
{
|
||||
fprintf(stderr, "failed to create a mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes_per_packet = atoi(argv[4]);
|
||||
if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
|
||||
{
|
||||
fprintf (stderr, "bytes per packet must be between 0 and %d\n",
|
||||
MAX_PACKET);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inFile = argv[argc-2];
|
||||
fin = fopen(inFile, "rb");
|
||||
if (!fin)
|
||||
{
|
||||
fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
|
||||
return 1;
|
||||
}
|
||||
outFile = argv[argc-1];
|
||||
fout = fopen(outFile, "wb+");
|
||||
if (!fout)
|
||||
{
|
||||
fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
|
||||
fclose(fin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enc = opus_custom_encoder_create(mode, channels, &err);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
return 1;
|
||||
}
|
||||
dec = opus_custom_decoder_create(mode, channels, &err);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
return 1;
|
||||
}
|
||||
opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
|
||||
|
||||
if (argc>7)
|
||||
{
|
||||
complexity=atoi(argv[5]);
|
||||
opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
|
||||
}
|
||||
|
||||
in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
|
||||
out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
|
||||
|
||||
while (!feof(fin))
|
||||
{
|
||||
int ret;
|
||||
err = fread(in, sizeof(short), frame_size*channels, fin);
|
||||
if (feof(fin))
|
||||
break;
|
||||
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
|
||||
if (len <= 0)
|
||||
fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
|
||||
|
||||
/* This is for simulating bit errors */
|
||||
#if 0
|
||||
int errors = 0;
|
||||
int eid = 0;
|
||||
/* This simulates random bit error */
|
||||
for (i=0;i<len*8;i++)
|
||||
{
|
||||
if (rand()%atoi(argv[8])==0)
|
||||
{
|
||||
if (i<64)
|
||||
{
|
||||
errors++;
|
||||
eid = i;
|
||||
}
|
||||
data[i/8] ^= 1<<(7-(i%8));
|
||||
}
|
||||
}
|
||||
if (errors == 1)
|
||||
data[eid/8] ^= 1<<(7-(eid%8));
|
||||
else if (errors%2 == 1)
|
||||
data[rand()%8] ^= 1<<rand()%8;
|
||||
#endif
|
||||
|
||||
#if 1 /* Set to zero to use the encoder's output instead */
|
||||
/* This is to simulate packet loss */
|
||||
if (argc==9 && rand()%1000<atoi(argv[argc-3]))
|
||||
/*if (errors && (errors%2==0))*/
|
||||
ret = opus_custom_decode(dec, NULL, len, out, frame_size);
|
||||
else
|
||||
ret = opus_custom_decode(dec, data, len, out, frame_size);
|
||||
if (ret < 0)
|
||||
fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
|
||||
#else
|
||||
for (i=0;i<ret*channels;i++)
|
||||
out[i] = in[i];
|
||||
#endif
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
for (i=0;i<ret*channels;i++)
|
||||
{
|
||||
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
|
||||
/*out[i] -= in[i];*/
|
||||
}
|
||||
#endif
|
||||
count++;
|
||||
fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
|
||||
skip = 0;
|
||||
}
|
||||
PRINT_MIPS(stderr);
|
||||
|
||||
opus_custom_encoder_destroy(enc);
|
||||
opus_custom_decoder_destroy(dec);
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
opus_custom_mode_destroy(mode);
|
||||
free(in);
|
||||
free(out);
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
if (rmsd > 0)
|
||||
{
|
||||
rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
|
||||
fprintf (stderr, "Error: encoder doesn't match decoder\n");
|
||||
fprintf (stderr, "RMS mismatch is %f\n", rmsd);
|
||||
return 1;
|
||||
} else {
|
||||
fprintf (stderr, "Encoder matches decoder!!\n");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/* Copyright (C) 2007 Jean-Marc Valin
|
||||
|
||||
File: os_support.h
|
||||
This is the (tiny) OS abstraction layer. Aside from math.h, this is the
|
||||
only place where system headers are allowed.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef OS_SUPPORT_H
|
||||
#define OS_SUPPORT_H
|
||||
|
||||
#ifdef CUSTOM_SUPPORT
|
||||
# include "custom_support.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** Opus wrapper for malloc(). To do your own dynamic allocation, all you need to do is replace this function and opus_free */
|
||||
#ifndef OVERRIDE_OPUS_ALLOC
|
||||
static inline void *opus_alloc (size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */
|
||||
#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH
|
||||
static inline void *opus_alloc_scratch (size_t size)
|
||||
{
|
||||
/* Scratch space doesn't need to be cleared */
|
||||
return opus_alloc(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Opus wrapper for free(). To do your own dynamic allocation, all you need to do is replace this function and opus_alloc */
|
||||
#ifndef OVERRIDE_OPUS_FREE
|
||||
static inline void opus_free (void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */
|
||||
#ifndef OVERRIDE_OPUS_COPY
|
||||
#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
|
||||
#endif
|
||||
|
||||
/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term
|
||||
provides compile-time type checking */
|
||||
#ifndef OVERRIDE_OPUS_MOVE
|
||||
#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
|
||||
#endif
|
||||
|
||||
/** Set n elements of dst to zero, starting at address s */
|
||||
#ifndef OVERRIDE_OPUS_CLEAR
|
||||
#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst))))
|
||||
#endif
|
||||
|
||||
/*#ifdef __GNUC__
|
||||
#pragma GCC poison printf sprintf
|
||||
#pragma GCC poison malloc free realloc calloc
|
||||
#endif*/
|
||||
|
||||
#endif /* OS_SUPPORT_H */
|
||||
|
|
@ -0,0 +1,410 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file pitch.c
|
||||
@brief Pitch analysis
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pitch.h"
|
||||
#include "os_support.h"
|
||||
#include "modes.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
#include "celt_lpc.h"
|
||||
|
||||
static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
|
||||
int max_pitch, int *best_pitch
|
||||
#ifdef FIXED_POINT
|
||||
, int yshift, opus_val32 maxcorr
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
opus_val32 Syy=1;
|
||||
opus_val16 best_num[2];
|
||||
opus_val32 best_den[2];
|
||||
#ifdef FIXED_POINT
|
||||
int xshift;
|
||||
|
||||
xshift = celt_ilog2(maxcorr)-14;
|
||||
#endif
|
||||
|
||||
best_num[0] = -1;
|
||||
best_num[1] = -1;
|
||||
best_den[0] = 0;
|
||||
best_den[1] = 0;
|
||||
best_pitch[0] = 0;
|
||||
best_pitch[1] = 1;
|
||||
for (j=0;j<len;j++)
|
||||
Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
|
||||
for (i=0;i<max_pitch;i++)
|
||||
{
|
||||
if (xcorr[i]>0)
|
||||
{
|
||||
opus_val16 num;
|
||||
opus_val32 xcorr16;
|
||||
xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
|
||||
#ifndef FIXED_POINT
|
||||
/* Considering the range of xcorr16, this should avoid both underflows
|
||||
and overflows (inf) when squaring xcorr16 */
|
||||
xcorr16 *= 1e-12f;
|
||||
#endif
|
||||
num = MULT16_16_Q15(xcorr16,xcorr16);
|
||||
if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
|
||||
{
|
||||
if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
|
||||
{
|
||||
best_num[1] = best_num[0];
|
||||
best_den[1] = best_den[0];
|
||||
best_pitch[1] = best_pitch[0];
|
||||
best_num[0] = num;
|
||||
best_den[0] = Syy;
|
||||
best_pitch[0] = i;
|
||||
} else {
|
||||
best_num[1] = num;
|
||||
best_den[1] = Syy;
|
||||
best_pitch[1] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
|
||||
Syy = MAX32(1, Syy);
|
||||
}
|
||||
}
|
||||
|
||||
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
|
||||
int len, int C)
|
||||
{
|
||||
int i;
|
||||
opus_val32 ac[5];
|
||||
opus_val16 tmp=Q15ONE;
|
||||
opus_val16 lpc[4], mem[4]={0,0,0,0};
|
||||
#ifdef FIXED_POINT
|
||||
int shift;
|
||||
opus_val32 maxabs = celt_maxabs32(x[0], len);
|
||||
if (C==2)
|
||||
{
|
||||
opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
|
||||
maxabs = MAX32(maxabs, maxabs_1);
|
||||
}
|
||||
if (maxabs<1)
|
||||
maxabs=1;
|
||||
shift = celt_ilog2(maxabs)-10;
|
||||
if (shift<0)
|
||||
shift=0;
|
||||
if (C==2)
|
||||
shift++;
|
||||
#endif
|
||||
for (i=1;i<len>>1;i++)
|
||||
x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
|
||||
x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
|
||||
if (C==2)
|
||||
{
|
||||
for (i=1;i<len>>1;i++)
|
||||
x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
|
||||
x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
|
||||
}
|
||||
|
||||
_celt_autocorr(x_lp, ac, NULL, 0,
|
||||
4, len>>1);
|
||||
|
||||
/* Noise floor -40 dB */
|
||||
#ifdef FIXED_POINT
|
||||
ac[0] += SHR32(ac[0],13);
|
||||
#else
|
||||
ac[0] *= 1.0001f;
|
||||
#endif
|
||||
/* Lag windowing */
|
||||
for (i=1;i<=4;i++)
|
||||
{
|
||||
/*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
|
||||
#ifdef FIXED_POINT
|
||||
ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
|
||||
#else
|
||||
ac[i] -= ac[i]*(.008f*i)*(.008f*i);
|
||||
#endif
|
||||
}
|
||||
|
||||
_celt_lpc(lpc, ac, 4);
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
|
||||
lpc[i] = MULT16_16_Q15(lpc[i], tmp);
|
||||
}
|
||||
celt_fir(x_lp, lpc, x_lp, len>>1, 4, mem);
|
||||
|
||||
mem[0]=0;
|
||||
lpc[0]=QCONST16(.8f,12);
|
||||
celt_fir(x_lp, lpc, x_lp, len>>1, 1, mem);
|
||||
|
||||
}
|
||||
|
||||
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
|
||||
int len, int max_pitch, int *pitch)
|
||||
{
|
||||
int i, j;
|
||||
int lag;
|
||||
int best_pitch[2]={0,0};
|
||||
VARDECL(opus_val16, x_lp4);
|
||||
VARDECL(opus_val16, y_lp4);
|
||||
VARDECL(opus_val32, xcorr);
|
||||
#ifdef FIXED_POINT
|
||||
opus_val32 maxcorr=1;
|
||||
opus_val16 xmax, ymax;
|
||||
int shift=0;
|
||||
#endif
|
||||
int offset;
|
||||
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert(len>0);
|
||||
celt_assert(max_pitch>0);
|
||||
lag = len+max_pitch;
|
||||
|
||||
ALLOC(x_lp4, len>>2, opus_val16);
|
||||
ALLOC(y_lp4, lag>>2, opus_val16);
|
||||
ALLOC(xcorr, max_pitch>>1, opus_val32);
|
||||
|
||||
/* Downsample by 2 again */
|
||||
for (j=0;j<len>>2;j++)
|
||||
x_lp4[j] = x_lp[2*j];
|
||||
for (j=0;j<lag>>2;j++)
|
||||
y_lp4[j] = y[2*j];
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
xmax = celt_maxabs16(x_lp4, len>>2);
|
||||
ymax = celt_maxabs16(y_lp4, lag>>2);
|
||||
shift = celt_ilog2(MAX16(1, MAX16(xmax, ymax)))-11;
|
||||
if (shift>0)
|
||||
{
|
||||
for (j=0;j<len>>2;j++)
|
||||
x_lp4[j] = SHR16(x_lp4[j], shift);
|
||||
for (j=0;j<lag>>2;j++)
|
||||
y_lp4[j] = SHR16(y_lp4[j], shift);
|
||||
/* Use double the shift for a MAC */
|
||||
shift *= 2;
|
||||
} else {
|
||||
shift = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Coarse search with 4x decimation */
|
||||
|
||||
for (i=0;i<max_pitch>>2;i++)
|
||||
{
|
||||
opus_val32 sum = 0;
|
||||
for (j=0;j<len>>2;j++)
|
||||
sum = MAC16_16(sum, x_lp4[j],y_lp4[i+j]);
|
||||
xcorr[i] = MAX32(-1, sum);
|
||||
#ifdef FIXED_POINT
|
||||
maxcorr = MAX32(maxcorr, sum);
|
||||
#endif
|
||||
}
|
||||
find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
|
||||
#ifdef FIXED_POINT
|
||||
, 0, maxcorr
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Finer search with 2x decimation */
|
||||
#ifdef FIXED_POINT
|
||||
maxcorr=1;
|
||||
#endif
|
||||
for (i=0;i<max_pitch>>1;i++)
|
||||
{
|
||||
opus_val32 sum=0;
|
||||
xcorr[i] = 0;
|
||||
if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
|
||||
continue;
|
||||
for (j=0;j<len>>1;j++)
|
||||
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
|
||||
xcorr[i] = MAX32(-1, sum);
|
||||
#ifdef FIXED_POINT
|
||||
maxcorr = MAX32(maxcorr, sum);
|
||||
#endif
|
||||
}
|
||||
find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
|
||||
#ifdef FIXED_POINT
|
||||
, shift+1, maxcorr
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Refine by pseudo-interpolation */
|
||||
if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
|
||||
{
|
||||
opus_val32 a, b, c;
|
||||
a = xcorr[best_pitch[0]-1];
|
||||
b = xcorr[best_pitch[0]];
|
||||
c = xcorr[best_pitch[0]+1];
|
||||
if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
|
||||
offset = 1;
|
||||
else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
|
||||
offset = -1;
|
||||
else
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
*pitch = 2*best_pitch[0]-offset;
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
|
||||
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
|
||||
int N, int *T0_, int prev_period, opus_val16 prev_gain)
|
||||
{
|
||||
int k, i, T, T0;
|
||||
opus_val16 g, g0;
|
||||
opus_val16 pg;
|
||||
opus_val32 xy,xx,yy;
|
||||
opus_val32 xcorr[3];
|
||||
opus_val32 best_xy, best_yy;
|
||||
int offset;
|
||||
int minperiod0;
|
||||
|
||||
minperiod0 = minperiod;
|
||||
maxperiod /= 2;
|
||||
minperiod /= 2;
|
||||
*T0_ /= 2;
|
||||
prev_period /= 2;
|
||||
N /= 2;
|
||||
x += maxperiod;
|
||||
if (*T0_>=maxperiod)
|
||||
*T0_=maxperiod-1;
|
||||
|
||||
T = T0 = *T0_;
|
||||
xx=xy=yy=0;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
xy = MAC16_16(xy, x[i], x[i-T0]);
|
||||
xx = MAC16_16(xx, x[i], x[i]);
|
||||
yy = MAC16_16(yy, x[i-T0],x[i-T0]);
|
||||
}
|
||||
best_xy = xy;
|
||||
best_yy = yy;
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
opus_val32 x2y2;
|
||||
int sh, t;
|
||||
x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
|
||||
sh = celt_ilog2(x2y2)>>1;
|
||||
t = VSHR32(x2y2, 2*(sh-7));
|
||||
g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
|
||||
}
|
||||
#else
|
||||
g = g0 = xy/celt_sqrt(1+xx*yy);
|
||||
#endif
|
||||
/* Look for any pitch at T/k */
|
||||
for (k=2;k<=15;k++)
|
||||
{
|
||||
int T1, T1b;
|
||||
opus_val16 g1;
|
||||
opus_val16 cont=0;
|
||||
T1 = (2*T0+k)/(2*k);
|
||||
if (T1 < minperiod)
|
||||
break;
|
||||
/* Look for another strong correlation at T1b */
|
||||
if (k==2)
|
||||
{
|
||||
if (T1+T0>maxperiod)
|
||||
T1b = T0;
|
||||
else
|
||||
T1b = T0+T1;
|
||||
} else
|
||||
{
|
||||
T1b = (2*second_check[k]*T0+k)/(2*k);
|
||||
}
|
||||
xy=yy=0;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
xy = MAC16_16(xy, x[i], x[i-T1]);
|
||||
yy = MAC16_16(yy, x[i-T1], x[i-T1]);
|
||||
|
||||
xy = MAC16_16(xy, x[i], x[i-T1b]);
|
||||
yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
opus_val32 x2y2;
|
||||
int sh, t;
|
||||
x2y2 = 1+MULT32_32_Q31(xx,yy);
|
||||
sh = celt_ilog2(x2y2)>>1;
|
||||
t = VSHR32(x2y2, 2*(sh-7));
|
||||
g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
|
||||
}
|
||||
#else
|
||||
g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
|
||||
#endif
|
||||
if (abs(T1-prev_period)<=1)
|
||||
cont = prev_gain;
|
||||
else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
|
||||
cont = HALF32(prev_gain);
|
||||
else
|
||||
cont = 0;
|
||||
if (g1 > QCONST16(.3f,15) + MULT16_16_Q15(QCONST16(.4f,15),g0)-cont)
|
||||
{
|
||||
best_xy = xy;
|
||||
best_yy = yy;
|
||||
T = T1;
|
||||
g = g1;
|
||||
}
|
||||
}
|
||||
best_xy = MAX32(0, best_xy);
|
||||
if (best_yy <= best_xy)
|
||||
pg = Q15ONE;
|
||||
else
|
||||
pg = SHR32(frac_div32(best_xy,best_yy+1),16);
|
||||
|
||||
for (k=0;k<3;k++)
|
||||
{
|
||||
int T1 = T+k-1;
|
||||
xy = 0;
|
||||
for (i=0;i<N;i++)
|
||||
xy = MAC16_16(xy, x[i], x[i-T1]);
|
||||
xcorr[k] = xy;
|
||||
}
|
||||
if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
|
||||
offset = 1;
|
||||
else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
|
||||
offset = -1;
|
||||
else
|
||||
offset = 0;
|
||||
if (pg > g)
|
||||
pg = g;
|
||||
*T0_ = 2*T+offset;
|
||||
|
||||
if (*T0_<minperiod0)
|
||||
*T0_=minperiod0;
|
||||
return pg;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file pitch.h
|
||||
@brief Pitch analysis
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PITCH_H
|
||||
#define PITCH_H
|
||||
|
||||
#include "modes.h"
|
||||
|
||||
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
|
||||
int len, int C);
|
||||
|
||||
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
|
||||
int len, int max_pitch, int *pitch);
|
||||
|
||||
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
|
||||
int N, int *T0, int prev_period, opus_val16 prev_gain);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,570 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "quant_bands.h"
|
||||
#include "laplace.h"
|
||||
#include <math.h>
|
||||
#include "os_support.h"
|
||||
#include "arch.h"
|
||||
#include "mathops.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "rate.h"
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
/* Mean energy in each band quantized in Q6 */
|
||||
static const signed char eMeans[25] = {
|
||||
103,100, 92, 85, 81,
|
||||
77, 72, 70, 78, 75,
|
||||
73, 71, 78, 74, 69,
|
||||
72, 70, 74, 76, 71,
|
||||
60, 60, 60, 60, 60
|
||||
};
|
||||
#else
|
||||
/* Mean energy in each band quantized in Q6 and converted back to float */
|
||||
static const opus_val16 eMeans[25] = {
|
||||
6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f,
|
||||
4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f,
|
||||
4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f,
|
||||
4.500000f, 4.375000f, 4.625000f, 4.750000f, 4.437500f,
|
||||
3.750000f, 3.750000f, 3.750000f, 3.750000f, 3.750000f
|
||||
};
|
||||
#endif
|
||||
/* prediction coefficients: 0.9, 0.8, 0.65, 0.5 */
|
||||
#ifdef FIXED_POINT
|
||||
static const opus_val16 pred_coef[4] = {29440, 26112, 21248, 16384};
|
||||
static const opus_val16 beta_coef[4] = {30147, 22282, 12124, 6554};
|
||||
static const opus_val16 beta_intra = 4915;
|
||||
#else
|
||||
static const opus_val16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.};
|
||||
static const opus_val16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.};
|
||||
static const opus_val16 beta_intra = 4915/32768.;
|
||||
#endif
|
||||
|
||||
/*Parameters of the Laplace-like probability models used for the coarse energy.
|
||||
There is one pair of parameters for each frame size, prediction type
|
||||
(inter/intra), and band number.
|
||||
The first number of each pair is the probability of 0, and the second is the
|
||||
decay rate, both in Q8 precision.*/
|
||||
static const unsigned char e_prob_model[4][2][42] = {
|
||||
/*120 sample frames.*/
|
||||
{
|
||||
/*Inter*/
|
||||
{
|
||||
72, 127, 65, 129, 66, 128, 65, 128, 64, 128, 62, 128, 64, 128,
|
||||
64, 128, 92, 78, 92, 79, 92, 78, 90, 79, 116, 41, 115, 40,
|
||||
114, 40, 132, 26, 132, 26, 145, 17, 161, 12, 176, 10, 177, 11
|
||||
},
|
||||
/*Intra*/
|
||||
{
|
||||
24, 179, 48, 138, 54, 135, 54, 132, 53, 134, 56, 133, 55, 132,
|
||||
55, 132, 61, 114, 70, 96, 74, 88, 75, 88, 87, 74, 89, 66,
|
||||
91, 67, 100, 59, 108, 50, 120, 40, 122, 37, 97, 43, 78, 50
|
||||
}
|
||||
},
|
||||
/*240 sample frames.*/
|
||||
{
|
||||
/*Inter*/
|
||||
{
|
||||
83, 78, 84, 81, 88, 75, 86, 74, 87, 71, 90, 73, 93, 74,
|
||||
93, 74, 109, 40, 114, 36, 117, 34, 117, 34, 143, 17, 145, 18,
|
||||
146, 19, 162, 12, 165, 10, 178, 7, 189, 6, 190, 8, 177, 9
|
||||
},
|
||||
/*Intra*/
|
||||
{
|
||||
23, 178, 54, 115, 63, 102, 66, 98, 69, 99, 74, 89, 71, 91,
|
||||
73, 91, 78, 89, 86, 80, 92, 66, 93, 64, 102, 59, 103, 60,
|
||||
104, 60, 117, 52, 123, 44, 138, 35, 133, 31, 97, 38, 77, 45
|
||||
}
|
||||
},
|
||||
/*480 sample frames.*/
|
||||
{
|
||||
/*Inter*/
|
||||
{
|
||||
61, 90, 93, 60, 105, 42, 107, 41, 110, 45, 116, 38, 113, 38,
|
||||
112, 38, 124, 26, 132, 27, 136, 19, 140, 20, 155, 14, 159, 16,
|
||||
158, 18, 170, 13, 177, 10, 187, 8, 192, 6, 175, 9, 159, 10
|
||||
},
|
||||
/*Intra*/
|
||||
{
|
||||
21, 178, 59, 110, 71, 86, 75, 85, 84, 83, 91, 66, 88, 73,
|
||||
87, 72, 92, 75, 98, 72, 105, 58, 107, 54, 115, 52, 114, 55,
|
||||
112, 56, 129, 51, 132, 40, 150, 33, 140, 29, 98, 35, 77, 42
|
||||
}
|
||||
},
|
||||
/*960 sample frames.*/
|
||||
{
|
||||
/*Inter*/
|
||||
{
|
||||
42, 121, 96, 66, 108, 43, 111, 40, 117, 44, 123, 32, 120, 36,
|
||||
119, 33, 127, 33, 134, 34, 139, 21, 147, 23, 152, 20, 158, 25,
|
||||
154, 26, 166, 21, 173, 16, 184, 13, 184, 10, 150, 13, 139, 15
|
||||
},
|
||||
/*Intra*/
|
||||
{
|
||||
22, 178, 63, 114, 74, 82, 84, 83, 92, 82, 103, 62, 96, 72,
|
||||
96, 67, 101, 73, 107, 72, 113, 55, 118, 52, 125, 52, 118, 52,
|
||||
117, 55, 135, 49, 137, 39, 157, 32, 145, 29, 97, 33, 77, 40
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char small_energy_icdf[3]={2,1,0};
|
||||
|
||||
static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBands, int start, int end, int len, int C)
|
||||
{
|
||||
int c, i;
|
||||
opus_val32 dist = 0;
|
||||
c=0; do {
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3));
|
||||
dist = MAC16_16(dist, d,d);
|
||||
}
|
||||
} while (++c<C);
|
||||
return MIN32(200,SHR32(dist,2*DB_SHIFT-6));
|
||||
}
|
||||
|
||||
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
|
||||
const opus_val16 *eBands, opus_val16 *oldEBands,
|
||||
opus_int32 budget, opus_int32 tell,
|
||||
const unsigned char *prob_model, opus_val16 *error, ec_enc *enc,
|
||||
int C, int LM, int intra, opus_val16 max_decay)
|
||||
{
|
||||
int i, c;
|
||||
int badness = 0;
|
||||
opus_val32 prev[2] = {0,0};
|
||||
opus_val16 coef;
|
||||
opus_val16 beta;
|
||||
|
||||
if (tell+3 <= budget)
|
||||
ec_enc_bit_logp(enc, intra, 3);
|
||||
if (intra)
|
||||
{
|
||||
coef = 0;
|
||||
beta = beta_intra;
|
||||
} else {
|
||||
beta = beta_coef[LM];
|
||||
coef = pred_coef[LM];
|
||||
}
|
||||
|
||||
/* Encode at a fixed coarse resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
c=0;
|
||||
do {
|
||||
int bits_left;
|
||||
int qi, qi0;
|
||||
opus_val32 q;
|
||||
opus_val16 x;
|
||||
opus_val32 f, tmp;
|
||||
opus_val16 oldE;
|
||||
opus_val16 decay_bound;
|
||||
x = eBands[i+c*m->nbEBands];
|
||||
oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]);
|
||||
#ifdef FIXED_POINT
|
||||
f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c];
|
||||
/* Rounding to nearest integer here is really important! */
|
||||
qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7);
|
||||
decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT),
|
||||
SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay)));
|
||||
#else
|
||||
f = x-coef*oldE-prev[c];
|
||||
/* Rounding to nearest integer here is really important! */
|
||||
qi = (int)floor(.5f+f);
|
||||
decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay;
|
||||
#endif
|
||||
/* Prevent the energy from going down too quickly (e.g. for bands
|
||||
that have just one bin) */
|
||||
if (qi < 0 && x < decay_bound)
|
||||
{
|
||||
qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT);
|
||||
if (qi > 0)
|
||||
qi = 0;
|
||||
}
|
||||
qi0 = qi;
|
||||
/* If we don't have enough bits to encode all the energy, just assume
|
||||
something safe. */
|
||||
tell = ec_tell(enc);
|
||||
bits_left = budget-tell-3*C*(end-i);
|
||||
if (i!=start && bits_left < 30)
|
||||
{
|
||||
if (bits_left < 24)
|
||||
qi = IMIN(1, qi);
|
||||
if (bits_left < 16)
|
||||
qi = IMAX(-1, qi);
|
||||
}
|
||||
if (budget-tell >= 15)
|
||||
{
|
||||
int pi;
|
||||
pi = 2*IMIN(i,20);
|
||||
ec_laplace_encode(enc, &qi,
|
||||
prob_model[pi]<<7, prob_model[pi+1]<<6);
|
||||
}
|
||||
else if(budget-tell >= 2)
|
||||
{
|
||||
qi = IMAX(-1, IMIN(qi, 1));
|
||||
ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2);
|
||||
}
|
||||
else if(budget-tell >= 1)
|
||||
{
|
||||
qi = IMIN(0, qi);
|
||||
ec_enc_bit_logp(enc, -qi, 1);
|
||||
}
|
||||
else
|
||||
qi = -1;
|
||||
error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT);
|
||||
badness += abs(qi0-qi);
|
||||
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
|
||||
|
||||
tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7);
|
||||
#ifdef FIXED_POINT
|
||||
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp);
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7);
|
||||
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
|
||||
} while (++c < C);
|
||||
}
|
||||
return badness;
|
||||
}
|
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
|
||||
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
|
||||
opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
|
||||
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate)
|
||||
{
|
||||
int intra;
|
||||
opus_val16 max_decay;
|
||||
VARDECL(opus_val16, oldEBands_intra);
|
||||
VARDECL(opus_val16, error_intra);
|
||||
ec_enc enc_start_state;
|
||||
opus_uint32 tell;
|
||||
int badness1=0;
|
||||
opus_int32 intra_bias;
|
||||
opus_val32 new_distortion;
|
||||
SAVE_STACK;
|
||||
|
||||
intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
|
||||
intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512));
|
||||
new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C);
|
||||
|
||||
tell = ec_tell(enc);
|
||||
if (tell+3 > budget)
|
||||
two_pass = intra = 0;
|
||||
|
||||
/* Encode the global flags using a simple probability model
|
||||
(first symbols in the stream) */
|
||||
|
||||
max_decay = QCONST16(16.f,DB_SHIFT);
|
||||
if (end-start>10)
|
||||
{
|
||||
#ifdef FIXED_POINT
|
||||
max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3));
|
||||
#else
|
||||
max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
|
||||
#endif
|
||||
}
|
||||
enc_start_state = *enc;
|
||||
|
||||
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16);
|
||||
ALLOC(error_intra, C*m->nbEBands, opus_val16);
|
||||
OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
|
||||
|
||||
if (two_pass || intra)
|
||||
{
|
||||
badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
|
||||
tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay);
|
||||
}
|
||||
|
||||
if (!intra)
|
||||
{
|
||||
unsigned char *intra_buf;
|
||||
ec_enc enc_intra_state;
|
||||
opus_int32 tell_intra;
|
||||
opus_uint32 nstart_bytes;
|
||||
opus_uint32 nintra_bytes;
|
||||
int badness2;
|
||||
VARDECL(unsigned char, intra_bits);
|
||||
|
||||
tell_intra = ec_tell_frac(enc);
|
||||
|
||||
enc_intra_state = *enc;
|
||||
|
||||
nstart_bytes = ec_range_bytes(&enc_start_state);
|
||||
nintra_bytes = ec_range_bytes(&enc_intra_state);
|
||||
intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes;
|
||||
ALLOC(intra_bits, nintra_bytes-nstart_bytes, unsigned char);
|
||||
/* Copy bits from intra bit-stream */
|
||||
OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes);
|
||||
|
||||
*enc = enc_start_state;
|
||||
|
||||
badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
|
||||
tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay);
|
||||
|
||||
if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
|
||||
{
|
||||
*enc = enc_intra_state;
|
||||
/* Copy intra bits to bit-stream */
|
||||
OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes);
|
||||
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
|
||||
OPUS_COPY(error, error_intra, C*m->nbEBands);
|
||||
intra = 1;
|
||||
}
|
||||
} else {
|
||||
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
|
||||
OPUS_COPY(error, error_intra, C*m->nbEBands);
|
||||
}
|
||||
|
||||
if (intra)
|
||||
*delayedIntra = new_distortion;
|
||||
else
|
||||
*delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra),
|
||||
new_distortion);
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
/* Encode finer resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
opus_int16 frac = 1<<fine_quant[i];
|
||||
if (fine_quant[i] <= 0)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
opus_val16 offset;
|
||||
#ifdef FIXED_POINT
|
||||
/* Has to be without rounding */
|
||||
q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]);
|
||||
#else
|
||||
q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac);
|
||||
#endif
|
||||
if (q2 > frac-1)
|
||||
q2 = frac-1;
|
||||
if (q2<0)
|
||||
q2 = 0;
|
||||
ec_enc_bits(enc, q2, fine_quant[i]);
|
||||
#ifdef FIXED_POINT
|
||||
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT));
|
||||
#else
|
||||
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] += offset;
|
||||
error[i+c*m->nbEBands] -= offset;
|
||||
/*printf ("%f ", error[i] - offset);*/
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
|
||||
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
|
||||
{
|
||||
int i, prio, c;
|
||||
|
||||
/* Use up the remaining bits */
|
||||
for (prio=0;prio<2;prio++)
|
||||
{
|
||||
for (i=start;i<end && bits_left>=C ;i++)
|
||||
{
|
||||
if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
opus_val16 offset;
|
||||
q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
|
||||
ec_enc_bits(enc, q2, 1);
|
||||
#ifdef FIXED_POINT
|
||||
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
|
||||
#else
|
||||
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] += offset;
|
||||
bits_left--;
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM)
|
||||
{
|
||||
const unsigned char *prob_model = e_prob_model[LM][intra];
|
||||
int i, c;
|
||||
opus_val32 prev[2] = {0, 0};
|
||||
opus_val16 coef;
|
||||
opus_val16 beta;
|
||||
opus_int32 budget;
|
||||
opus_int32 tell;
|
||||
|
||||
if (intra)
|
||||
{
|
||||
coef = 0;
|
||||
beta = beta_intra;
|
||||
} else {
|
||||
beta = beta_coef[LM];
|
||||
coef = pred_coef[LM];
|
||||
}
|
||||
|
||||
budget = dec->storage*8;
|
||||
|
||||
/* Decode at a fixed coarse resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
c=0;
|
||||
do {
|
||||
int qi;
|
||||
opus_val32 q;
|
||||
opus_val32 tmp;
|
||||
/* It would be better to express this invariant as a
|
||||
test on C at function entry, but that isn't enough
|
||||
to make the static analyzer happy. */
|
||||
celt_assert(c<2);
|
||||
tell = ec_tell(dec);
|
||||
if(budget-tell>=15)
|
||||
{
|
||||
int pi;
|
||||
pi = 2*IMIN(i,20);
|
||||
qi = ec_laplace_decode(dec,
|
||||
prob_model[pi]<<7, prob_model[pi+1]<<6);
|
||||
}
|
||||
else if(budget-tell>=2)
|
||||
{
|
||||
qi = ec_dec_icdf(dec, small_energy_icdf, 2);
|
||||
qi = (qi>>1)^-(qi&1);
|
||||
}
|
||||
else if(budget-tell>=1)
|
||||
{
|
||||
qi = -ec_dec_bit_logp(dec, 1);
|
||||
}
|
||||
else
|
||||
qi = -1;
|
||||
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
|
||||
|
||||
oldEBands[i+c*m->nbEBands] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]);
|
||||
tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7);
|
||||
#ifdef FIXED_POINT
|
||||
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp);
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7);
|
||||
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
|
||||
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C)
|
||||
{
|
||||
int i, c;
|
||||
/* Decode finer resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
if (fine_quant[i] <= 0)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
opus_val16 offset;
|
||||
q2 = ec_dec_bits(dec, fine_quant[i]);
|
||||
#ifdef FIXED_POINT
|
||||
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT));
|
||||
#else
|
||||
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] += offset;
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
|
||||
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C)
|
||||
{
|
||||
int i, prio, c;
|
||||
|
||||
/* Use up the remaining bits */
|
||||
for (prio=0;prio<2;prio++)
|
||||
{
|
||||
for (i=start;i<end && bits_left>=C ;i++)
|
||||
{
|
||||
if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
opus_val16 offset;
|
||||
q2 = ec_dec_bits(dec, 1);
|
||||
#ifdef FIXED_POINT
|
||||
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
|
||||
#else
|
||||
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
|
||||
#endif
|
||||
oldEBands[i+c*m->nbEBands] += offset;
|
||||
bits_left--;
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void log2Amp(const CELTMode *m, int start, int end,
|
||||
celt_ener *eBands, const opus_val16 *oldEBands, int C)
|
||||
{
|
||||
int c, i;
|
||||
c=0;
|
||||
do {
|
||||
for (i=0;i<start;i++)
|
||||
eBands[i+c*m->nbEBands] = 0;
|
||||
for (;i<end;i++)
|
||||
{
|
||||
opus_val16 lg = ADD16(oldEBands[i+c*m->nbEBands],
|
||||
SHL16((opus_val16)eMeans[i],6));
|
||||
eBands[i+c*m->nbEBands] = PSHR32(celt_exp2(lg),4);
|
||||
}
|
||||
for (;i<m->nbEBands;i++)
|
||||
eBands[i+c*m->nbEBands] = 0;
|
||||
} while (++c < C);
|
||||
}
|
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end,
|
||||
celt_ener *bandE, opus_val16 *bandLogE, int C)
|
||||
{
|
||||
int c, i;
|
||||
c=0;
|
||||
do {
|
||||
for (i=0;i<effEnd;i++)
|
||||
bandLogE[i+c*m->nbEBands] =
|
||||
celt_log2(SHL32(bandE[i+c*m->nbEBands],2))
|
||||
- SHL16((opus_val16)eMeans[i],6);
|
||||
for (i=effEnd;i<end;i++)
|
||||
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
|
||||
} while (++c < C);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef QUANT_BANDS
|
||||
#define QUANT_BANDS
|
||||
|
||||
#include "arch.h"
|
||||
#include "modes.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "mathops.h"
|
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end,
|
||||
celt_ener *bandE, opus_val16 *bandLogE, int C);
|
||||
|
||||
void log2Amp(const CELTMode *m, int start, int end,
|
||||
celt_ener *eBands, const opus_val16 *oldEBands, int C);
|
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
|
||||
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
|
||||
opus_val16 *error, ec_enc *enc, int C, int LM,
|
||||
int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
|
||||
int two_pass, int loss_rate);
|
||||
|
||||
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C);
|
||||
|
||||
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C);
|
||||
|
||||
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM);
|
||||
|
||||
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C);
|
||||
|
||||
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C);
|
||||
|
||||
#endif /* QUANT_BANDS */
|
|
@ -0,0 +1,638 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include "modes.h"
|
||||
#include "cwrs.h"
|
||||
#include "arch.h"
|
||||
#include "os_support.h"
|
||||
|
||||
#include "entcode.h"
|
||||
#include "rate.h"
|
||||
|
||||
static const unsigned char LOG2_FRAC_TABLE[24]={
|
||||
0,
|
||||
8,13,
|
||||
16,19,21,23,
|
||||
24,26,27,28,29,30,31,32,
|
||||
32,33,34,34,35,36,36,37,37
|
||||
};
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
/*Determines if V(N,K) fits in a 32-bit unsigned integer.
|
||||
N and K are themselves limited to 15 bits.*/
|
||||
static int fits_in32(int _n, int _k)
|
||||
{
|
||||
static const opus_int16 maxN[15] = {
|
||||
32767, 32767, 32767, 1476, 283, 109, 60, 40,
|
||||
29, 24, 20, 18, 16, 14, 13};
|
||||
static const opus_int16 maxK[15] = {
|
||||
32767, 32767, 32767, 32767, 1172, 238, 95, 53,
|
||||
36, 27, 22, 18, 16, 15, 13};
|
||||
if (_n>=14)
|
||||
{
|
||||
if (_k>=14)
|
||||
return 0;
|
||||
else
|
||||
return _n <= maxN[_k];
|
||||
} else {
|
||||
return _k <= maxK[_n];
|
||||
}
|
||||
}
|
||||
|
||||
void compute_pulse_cache(CELTMode *m, int LM)
|
||||
{
|
||||
int C;
|
||||
int i;
|
||||
int j;
|
||||
int curr=0;
|
||||
int nbEntries=0;
|
||||
int entryN[100], entryK[100], entryI[100];
|
||||
const opus_int16 *eBands = m->eBands;
|
||||
PulseCache *cache = &m->cache;
|
||||
opus_int16 *cindex;
|
||||
unsigned char *bits;
|
||||
unsigned char *cap;
|
||||
|
||||
cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
|
||||
cache->index = cindex;
|
||||
|
||||
/* Scan for all unique band sizes */
|
||||
for (i=0;i<=LM+1;i++)
|
||||
{
|
||||
for (j=0;j<m->nbEBands;j++)
|
||||
{
|
||||
int k;
|
||||
int N = (eBands[j+1]-eBands[j])<<i>>1;
|
||||
cindex[i*m->nbEBands+j] = -1;
|
||||
/* Find other bands that have the same size */
|
||||
for (k=0;k<=i;k++)
|
||||
{
|
||||
int n;
|
||||
for (n=0;n<m->nbEBands && (k!=i || n<j);n++)
|
||||
{
|
||||
if (N == (eBands[n+1]-eBands[n])<<k>>1)
|
||||
{
|
||||
cindex[i*m->nbEBands+j] = cindex[k*m->nbEBands+n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cache->index[i*m->nbEBands+j] == -1 && N!=0)
|
||||
{
|
||||
int K;
|
||||
entryN[nbEntries] = N;
|
||||
K = 0;
|
||||
while (fits_in32(N,get_pulses(K+1)) && K<MAX_PSEUDO)
|
||||
K++;
|
||||
entryK[nbEntries] = K;
|
||||
cindex[i*m->nbEBands+j] = curr;
|
||||
entryI[nbEntries] = curr;
|
||||
|
||||
curr += K+1;
|
||||
nbEntries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr);
|
||||
cache->bits = bits;
|
||||
cache->size = curr;
|
||||
/* Compute the cache for all unique sizes */
|
||||
for (i=0;i<nbEntries;i++)
|
||||
{
|
||||
unsigned char *ptr = bits+entryI[i];
|
||||
opus_int16 tmp[MAX_PULSES+1];
|
||||
get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
|
||||
for (j=1;j<=entryK[i];j++)
|
||||
ptr[j] = tmp[get_pulses(j)]-1;
|
||||
ptr[0] = entryK[i];
|
||||
}
|
||||
|
||||
/* Compute the maximum rate for each band at which we'll reliably use as
|
||||
many bits as we ask for. */
|
||||
cache->caps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
|
||||
for (i=0;i<=LM;i++)
|
||||
{
|
||||
for (C=1;C<=2;C++)
|
||||
{
|
||||
for (j=0;j<m->nbEBands;j++)
|
||||
{
|
||||
int N0;
|
||||
int max_bits;
|
||||
N0 = m->eBands[j+1]-m->eBands[j];
|
||||
/* N=1 bands only have a sign bit and fine bits. */
|
||||
if (N0<<i == 1)
|
||||
max_bits = C*(1+MAX_FINE_BITS)<<BITRES;
|
||||
else
|
||||
{
|
||||
const unsigned char *pcache;
|
||||
opus_int32 num;
|
||||
opus_int32 den;
|
||||
int LM0;
|
||||
int N;
|
||||
int offset;
|
||||
int ndof;
|
||||
int qb;
|
||||
int k;
|
||||
LM0 = 0;
|
||||
/* Even-sized bands bigger than N=2 can be split one more time.
|
||||
As of commit 44203907 all bands >1 are even, including custom modes.*/
|
||||
if (N0 > 2)
|
||||
{
|
||||
N0>>=1;
|
||||
LM0--;
|
||||
}
|
||||
/* N0=1 bands can't be split down to N<2. */
|
||||
else if (N0 <= 1)
|
||||
{
|
||||
LM0=IMIN(i,1);
|
||||
N0<<=LM0;
|
||||
}
|
||||
/* Compute the cost for the lowest-level PVQ of a fully split
|
||||
band. */
|
||||
pcache = bits + cindex[(LM0+1)*m->nbEBands+j];
|
||||
max_bits = pcache[pcache[0]]+1;
|
||||
/* Add in the cost of coding regular splits. */
|
||||
N = N0;
|
||||
for(k=0;k<i-LM0;k++){
|
||||
max_bits <<= 1;
|
||||
/* Offset the number of qtheta bits by log2(N)/2
|
||||
+ QTHETA_OFFSET compared to their "fair share" of
|
||||
total/N */
|
||||
offset = ((m->logN[j]+((LM0+k)<<BITRES))>>1)-QTHETA_OFFSET;
|
||||
/* The number of qtheta bits we'll allocate if the remainder
|
||||
is to be max_bits.
|
||||
The average measured cost for theta is 0.89701 times qb,
|
||||
approximated here as 459/512. */
|
||||
num=459*(opus_int32)((2*N-1)*offset+max_bits);
|
||||
den=((opus_int32)(2*N-1)<<9)-459;
|
||||
qb = IMIN((num+(den>>1))/den, 57);
|
||||
celt_assert(qb >= 0);
|
||||
max_bits += qb;
|
||||
N <<= 1;
|
||||
}
|
||||
/* Add in the cost of a stereo split, if necessary. */
|
||||
if (C==2)
|
||||
{
|
||||
max_bits <<= 1;
|
||||
offset = ((m->logN[j]+(i<<BITRES))>>1)-(N==2?QTHETA_OFFSET_TWOPHASE:QTHETA_OFFSET);
|
||||
ndof = 2*N-1-(N==2);
|
||||
/* The average measured cost for theta with the step PDF is
|
||||
0.95164 times qb, approximated here as 487/512. */
|
||||
num = (N==2?512:487)*(opus_int32)(max_bits+ndof*offset);
|
||||
den = ((opus_int32)ndof<<9)-(N==2?512:487);
|
||||
qb = IMIN((num+(den>>1))/den, (N==2?64:61));
|
||||
celt_assert(qb >= 0);
|
||||
max_bits += qb;
|
||||
}
|
||||
/* Add the fine bits we'll use. */
|
||||
/* Compensate for the extra DoF in stereo */
|
||||
ndof = C*N + ((C==2 && N>2) ? 1 : 0);
|
||||
/* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET
|
||||
compared to their "fair share" of total/N */
|
||||
offset = ((m->logN[j] + (i<<BITRES))>>1)-FINE_OFFSET;
|
||||
/* N=2 is the only point that doesn't match the curve */
|
||||
if (N==2)
|
||||
offset += 1<<BITRES>>2;
|
||||
/* The number of fine bits we'll allocate if the remainder is
|
||||
to be max_bits. */
|
||||
num = max_bits+ndof*offset;
|
||||
den = (ndof-1)<<BITRES;
|
||||
qb = IMIN((num+(den>>1))/den, MAX_FINE_BITS);
|
||||
celt_assert(qb >= 0);
|
||||
max_bits += C*qb<<BITRES;
|
||||
}
|
||||
max_bits = (4*max_bits/(C*((m->eBands[j+1]-m->eBands[j])<<i)))-64;
|
||||
celt_assert(max_bits >= 0);
|
||||
celt_assert(max_bits < 256);
|
||||
*cap++ = (unsigned char)max_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
#define ALLOC_STEPS 6
|
||||
|
||||
static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start,
|
||||
const int *bits1, const int *bits2, const int *thresh, const int *cap, opus_int32 total, opus_int32 *_balance,
|
||||
int skip_rsv, int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits,
|
||||
int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev)
|
||||
{
|
||||
opus_int32 psum;
|
||||
int lo, hi;
|
||||
int i, j;
|
||||
int logM;
|
||||
int stereo;
|
||||
int codedBands=-1;
|
||||
int alloc_floor;
|
||||
opus_int32 left, percoeff;
|
||||
int done;
|
||||
opus_int32 balance;
|
||||
SAVE_STACK;
|
||||
|
||||
alloc_floor = C<<BITRES;
|
||||
stereo = C>1;
|
||||
|
||||
logM = LM<<BITRES;
|
||||
lo = 0;
|
||||
hi = 1<<ALLOC_STEPS;
|
||||
for (i=0;i<ALLOC_STEPS;i++)
|
||||
{
|
||||
int mid = (lo+hi)>>1;
|
||||
psum = 0;
|
||||
done = 0;
|
||||
for (j=end;j-->start;)
|
||||
{
|
||||
int tmp = bits1[j] + (mid*(opus_int32)bits2[j]>>ALLOC_STEPS);
|
||||
if (tmp >= thresh[j] || done)
|
||||
{
|
||||
done = 1;
|
||||
/* Don't allocate more than we can actually use */
|
||||
psum += IMIN(tmp, cap[j]);
|
||||
} else {
|
||||
if (tmp >= alloc_floor)
|
||||
psum += alloc_floor;
|
||||
}
|
||||
}
|
||||
if (psum > total)
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
psum = 0;
|
||||
/*printf ("interp bisection gave %d\n", lo);*/
|
||||
done = 0;
|
||||
for (j=end;j-->start;)
|
||||
{
|
||||
int tmp = bits1[j] + (lo*bits2[j]>>ALLOC_STEPS);
|
||||
if (tmp < thresh[j] && !done)
|
||||
{
|
||||
if (tmp >= alloc_floor)
|
||||
tmp = alloc_floor;
|
||||
else
|
||||
tmp = 0;
|
||||
} else
|
||||
done = 1;
|
||||
/* Don't allocate more than we can actually use */
|
||||
tmp = IMIN(tmp, cap[j]);
|
||||
bits[j] = tmp;
|
||||
psum += tmp;
|
||||
}
|
||||
|
||||
/* Decide which bands to skip, working backwards from the end. */
|
||||
for (codedBands=end;;codedBands--)
|
||||
{
|
||||
int band_width;
|
||||
int band_bits;
|
||||
int rem;
|
||||
j = codedBands-1;
|
||||
/* Never skip the first band, nor a band that has been boosted by
|
||||
dynalloc.
|
||||
In the first case, we'd be coding a bit to signal we're going to waste
|
||||
all the other bits.
|
||||
In the second case, we'd be coding a bit to redistribute all the bits
|
||||
we just signaled should be cocentrated in this band. */
|
||||
if (j<=skip_start)
|
||||
{
|
||||
/* Give the bit we reserved to end skipping back. */
|
||||
total += skip_rsv;
|
||||
break;
|
||||
}
|
||||
/*Figure out how many left-over bits we would be adding to this band.
|
||||
This can include bits we've stolen back from higher, skipped bands.*/
|
||||
left = total-psum;
|
||||
percoeff = left/(m->eBands[codedBands]-m->eBands[start]);
|
||||
left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
|
||||
rem = IMAX(left-(m->eBands[j]-m->eBands[start]),0);
|
||||
band_width = m->eBands[codedBands]-m->eBands[j];
|
||||
band_bits = (int)(bits[j] + percoeff*band_width + rem);
|
||||
/*Only code a skip decision if we're above the threshold for this band.
|
||||
Otherwise it is force-skipped.
|
||||
This ensures that we have enough bits to code the skip flag.*/
|
||||
if (band_bits >= IMAX(thresh[j], alloc_floor+(1<<BITRES)))
|
||||
{
|
||||
if (encode)
|
||||
{
|
||||
/*This if() block is the only part of the allocation function that
|
||||
is not a mandatory part of the bitstream: any bands we choose to
|
||||
skip here must be explicitly signaled.*/
|
||||
/*Choose a threshold with some hysteresis to keep bands from
|
||||
fluctuating in and out.*/
|
||||
#ifdef FUZZING
|
||||
if ((rand()&0x1) == 0)
|
||||
#else
|
||||
if (codedBands<=start+2 || band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4)
|
||||
#endif
|
||||
{
|
||||
ec_enc_bit_logp(ec, 1, 1);
|
||||
break;
|
||||
}
|
||||
ec_enc_bit_logp(ec, 0, 1);
|
||||
} else if (ec_dec_bit_logp(ec, 1)) {
|
||||
break;
|
||||
}
|
||||
/*We used a bit to skip this band.*/
|
||||
psum += 1<<BITRES;
|
||||
band_bits -= 1<<BITRES;
|
||||
}
|
||||
/*Reclaim the bits originally allocated to this band.*/
|
||||
psum -= bits[j]+intensity_rsv;
|
||||
if (intensity_rsv > 0)
|
||||
intensity_rsv = LOG2_FRAC_TABLE[j-start];
|
||||
psum += intensity_rsv;
|
||||
if (band_bits >= alloc_floor)
|
||||
{
|
||||
/*If we have enough for a fine energy bit per channel, use it.*/
|
||||
psum += alloc_floor;
|
||||
bits[j] = alloc_floor;
|
||||
} else {
|
||||
/*Otherwise this band gets nothing at all.*/
|
||||
bits[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
celt_assert(codedBands > start);
|
||||
/* Code the intensity and dual stereo parameters. */
|
||||
if (intensity_rsv > 0)
|
||||
{
|
||||
if (encode)
|
||||
{
|
||||
*intensity = IMIN(*intensity, codedBands);
|
||||
ec_enc_uint(ec, *intensity-start, codedBands+1-start);
|
||||
}
|
||||
else
|
||||
*intensity = start+ec_dec_uint(ec, codedBands+1-start);
|
||||
}
|
||||
else
|
||||
*intensity = 0;
|
||||
if (*intensity <= start)
|
||||
{
|
||||
total += dual_stereo_rsv;
|
||||
dual_stereo_rsv = 0;
|
||||
}
|
||||
if (dual_stereo_rsv > 0)
|
||||
{
|
||||
if (encode)
|
||||
ec_enc_bit_logp(ec, *dual_stereo, 1);
|
||||
else
|
||||
*dual_stereo = ec_dec_bit_logp(ec, 1);
|
||||
}
|
||||
else
|
||||
*dual_stereo = 0;
|
||||
|
||||
/* Allocate the remaining bits */
|
||||
left = total-psum;
|
||||
percoeff = left/(m->eBands[codedBands]-m->eBands[start]);
|
||||
left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
|
||||
for (j=start;j<codedBands;j++)
|
||||
bits[j] += ((int)percoeff*(m->eBands[j+1]-m->eBands[j]));
|
||||
for (j=start;j<codedBands;j++)
|
||||
{
|
||||
int tmp = (int)IMIN(left, m->eBands[j+1]-m->eBands[j]);
|
||||
bits[j] += tmp;
|
||||
left -= tmp;
|
||||
}
|
||||
/*for (j=0;j<end;j++)printf("%d ", bits[j]);printf("\n");*/
|
||||
|
||||
balance = 0;
|
||||
for (j=start;j<codedBands;j++)
|
||||
{
|
||||
int N0, N, den;
|
||||
int offset;
|
||||
int NClogN;
|
||||
opus_int32 excess, bit;
|
||||
|
||||
celt_assert(bits[j] >= 0);
|
||||
N0 = m->eBands[j+1]-m->eBands[j];
|
||||
N=N0<<LM;
|
||||
bit = (opus_int32)bits[j]+balance;
|
||||
|
||||
if (N>1)
|
||||
{
|
||||
excess = MAX32(bit-cap[j],0);
|
||||
bits[j] = bit-excess;
|
||||
|
||||
/* Compensate for the extra DoF in stereo */
|
||||
den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0));
|
||||
|
||||
NClogN = den*(m->logN[j] + logM);
|
||||
|
||||
/* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET
|
||||
compared to their "fair share" of total/N */
|
||||
offset = (NClogN>>1)-den*FINE_OFFSET;
|
||||
|
||||
/* N=2 is the only point that doesn't match the curve */
|
||||
if (N==2)
|
||||
offset += den<<BITRES>>2;
|
||||
|
||||
/* Changing the offset for allocating the second and third
|
||||
fine energy bit */
|
||||
if (bits[j] + offset < den*2<<BITRES)
|
||||
offset += NClogN>>2;
|
||||
else if (bits[j] + offset < den*3<<BITRES)
|
||||
offset += NClogN>>3;
|
||||
|
||||
/* Divide with rounding */
|
||||
ebits[j] = IMAX(0, (bits[j] + offset + (den<<(BITRES-1))) / (den<<BITRES));
|
||||
|
||||
/* Make sure not to bust */
|
||||
if (C*ebits[j] > (bits[j]>>BITRES))
|
||||
ebits[j] = bits[j] >> stereo >> BITRES;
|
||||
|
||||
/* More than that is useless because that's about as far as PVQ can go */
|
||||
ebits[j] = IMIN(ebits[j], MAX_FINE_BITS);
|
||||
|
||||
/* If we rounded down or capped this band, make it a candidate for the
|
||||
final fine energy pass */
|
||||
fine_priority[j] = ebits[j]*(den<<BITRES) >= bits[j]+offset;
|
||||
|
||||
/* Remove the allocated fine bits; the rest are assigned to PVQ */
|
||||
bits[j] -= C*ebits[j]<<BITRES;
|
||||
|
||||
} else {
|
||||
/* For N=1, all bits go to fine energy except for a single sign bit */
|
||||
excess = MAX32(0,bit-(C<<BITRES));
|
||||
bits[j] = bit-excess;
|
||||
ebits[j] = 0;
|
||||
fine_priority[j] = 1;
|
||||
}
|
||||
|
||||
/* Fine energy can't take advantage of the re-balancing in
|
||||
quant_all_bands().
|
||||
Instead, do the re-balancing here.*/
|
||||
if(excess > 0)
|
||||
{
|
||||
int extra_fine;
|
||||
int extra_bits;
|
||||
extra_fine = IMIN(excess>>(stereo+BITRES),MAX_FINE_BITS-ebits[j]);
|
||||
ebits[j] += extra_fine;
|
||||
extra_bits = extra_fine*C<<BITRES;
|
||||
fine_priority[j] = extra_bits >= excess-balance;
|
||||
excess -= extra_bits;
|
||||
}
|
||||
balance = excess;
|
||||
|
||||
celt_assert(bits[j] >= 0);
|
||||
celt_assert(ebits[j] >= 0);
|
||||
}
|
||||
/* Save any remaining bits over the cap for the rebalancing in
|
||||
quant_all_bands(). */
|
||||
*_balance = balance;
|
||||
|
||||
/* The skipped bands use all their bits for fine energy. */
|
||||
for (;j<end;j++)
|
||||
{
|
||||
ebits[j] = bits[j] >> stereo >> BITRES;
|
||||
celt_assert(C*ebits[j]<<BITRES == bits[j]);
|
||||
bits[j] = 0;
|
||||
fine_priority[j] = ebits[j]<1;
|
||||
}
|
||||
RESTORE_STACK;
|
||||
return codedBands;
|
||||
}
|
||||
|
||||
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
|
||||
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev)
|
||||
{
|
||||
int lo, hi, len, j;
|
||||
int codedBands;
|
||||
int skip_start;
|
||||
int skip_rsv;
|
||||
int intensity_rsv;
|
||||
int dual_stereo_rsv;
|
||||
VARDECL(int, bits1);
|
||||
VARDECL(int, bits2);
|
||||
VARDECL(int, thresh);
|
||||
VARDECL(int, trim_offset);
|
||||
SAVE_STACK;
|
||||
|
||||
total = IMAX(total, 0);
|
||||
len = m->nbEBands;
|
||||
skip_start = start;
|
||||
/* Reserve a bit to signal the end of manually skipped bands. */
|
||||
skip_rsv = total >= 1<<BITRES ? 1<<BITRES : 0;
|
||||
total -= skip_rsv;
|
||||
/* Reserve bits for the intensity and dual stereo parameters. */
|
||||
intensity_rsv = dual_stereo_rsv = 0;
|
||||
if (C==2)
|
||||
{
|
||||
intensity_rsv = LOG2_FRAC_TABLE[end-start];
|
||||
if (intensity_rsv>total)
|
||||
intensity_rsv = 0;
|
||||
else
|
||||
{
|
||||
total -= intensity_rsv;
|
||||
dual_stereo_rsv = total>=1<<BITRES ? 1<<BITRES : 0;
|
||||
total -= dual_stereo_rsv;
|
||||
}
|
||||
}
|
||||
ALLOC(bits1, len, int);
|
||||
ALLOC(bits2, len, int);
|
||||
ALLOC(thresh, len, int);
|
||||
ALLOC(trim_offset, len, int);
|
||||
|
||||
for (j=start;j<end;j++)
|
||||
{
|
||||
/* Below this threshold, we're sure not to allocate any PVQ bits */
|
||||
thresh[j] = IMAX((C)<<BITRES, (3*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>4);
|
||||
/* Tilt of the allocation curve */
|
||||
trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(end-j-1)
|
||||
*(1<<(LM+BITRES))>>6;
|
||||
/* Giving less resolution to single-coefficient bands because they get
|
||||
more benefit from having one coarse value per coefficient*/
|
||||
if ((m->eBands[j+1]-m->eBands[j])<<LM==1)
|
||||
trim_offset[j] -= C<<BITRES;
|
||||
}
|
||||
lo = 1;
|
||||
hi = m->nbAllocVectors - 1;
|
||||
do
|
||||
{
|
||||
int done = 0;
|
||||
int psum = 0;
|
||||
int mid = (lo+hi) >> 1;
|
||||
for (j=end;j-->start;)
|
||||
{
|
||||
int bitsj;
|
||||
int N = m->eBands[j+1]-m->eBands[j];
|
||||
bitsj = C*N*m->allocVectors[mid*len+j]<<LM>>2;
|
||||
if (bitsj > 0)
|
||||
bitsj = IMAX(0, bitsj + trim_offset[j]);
|
||||
bitsj += offsets[j];
|
||||
if (bitsj >= thresh[j] || done)
|
||||
{
|
||||
done = 1;
|
||||
/* Don't allocate more than we can actually use */
|
||||
psum += IMIN(bitsj, cap[j]);
|
||||
} else {
|
||||
if (bitsj >= C<<BITRES)
|
||||
psum += C<<BITRES;
|
||||
}
|
||||
}
|
||||
if (psum > total)
|
||||
hi = mid - 1;
|
||||
else
|
||||
lo = mid + 1;
|
||||
/*printf ("lo = %d, hi = %d\n", lo, hi);*/
|
||||
}
|
||||
while (lo <= hi);
|
||||
hi = lo--;
|
||||
/*printf ("interp between %d and %d\n", lo, hi);*/
|
||||
for (j=start;j<end;j++)
|
||||
{
|
||||
int bits1j, bits2j;
|
||||
int N = m->eBands[j+1]-m->eBands[j];
|
||||
bits1j = C*N*m->allocVectors[lo*len+j]<<LM>>2;
|
||||
bits2j = hi>=m->nbAllocVectors ?
|
||||
cap[j] : C*N*m->allocVectors[hi*len+j]<<LM>>2;
|
||||
if (bits1j > 0)
|
||||
bits1j = IMAX(0, bits1j + trim_offset[j]);
|
||||
if (bits2j > 0)
|
||||
bits2j = IMAX(0, bits2j + trim_offset[j]);
|
||||
if (lo > 0)
|
||||
bits1j += offsets[j];
|
||||
bits2j += offsets[j];
|
||||
if (offsets[j]>0)
|
||||
skip_start = j;
|
||||
bits2j = IMAX(0,bits2j-bits1j);
|
||||
bits1[j] = bits1j;
|
||||
bits2[j] = bits2j;
|
||||
}
|
||||
codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
|
||||
total, balance, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv,
|
||||
pulses, ebits, fine_priority, C, LM, ec, encode, prev);
|
||||
RESTORE_STACK;
|
||||
return codedBands;
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RATE_H
|
||||
#define RATE_H
|
||||
|
||||
#define MAX_PSEUDO 40
|
||||
#define LOG_MAX_PSEUDO 6
|
||||
|
||||
#define MAX_PULSES 128
|
||||
|
||||
#define MAX_FINE_BITS 8
|
||||
|
||||
#define FINE_OFFSET 21
|
||||
#define QTHETA_OFFSET 4
|
||||
#define QTHETA_OFFSET_TWOPHASE 16
|
||||
|
||||
#include "cwrs.h"
|
||||
#include "modes.h"
|
||||
|
||||
void compute_pulse_cache(CELTMode *m, int LM);
|
||||
|
||||
static inline int get_pulses(int i)
|
||||
{
|
||||
return i<8 ? i : (8 + (i&7)) << ((i>>3)-1);
|
||||
}
|
||||
|
||||
static inline int bits2pulses(const CELTMode *m, int band, int LM, int bits)
|
||||
{
|
||||
int i;
|
||||
int lo, hi;
|
||||
const unsigned char *cache;
|
||||
|
||||
LM++;
|
||||
cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
|
||||
|
||||
lo = 0;
|
||||
hi = cache[0];
|
||||
bits--;
|
||||
for (i=0;i<LOG_MAX_PSEUDO;i++)
|
||||
{
|
||||
int mid = (lo+hi+1)>>1;
|
||||
/* OPT: Make sure this is implemented with a conditional move */
|
||||
if ((int)cache[mid] >= bits)
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
if (bits- (lo == 0 ? -1 : (int)cache[lo]) <= (int)cache[hi]-bits)
|
||||
return lo;
|
||||
else
|
||||
return hi;
|
||||
}
|
||||
|
||||
static inline int pulses2bits(const CELTMode *m, int band, int LM, int pulses)
|
||||
{
|
||||
const unsigned char *cache;
|
||||
|
||||
LM++;
|
||||
cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
|
||||
return pulses == 0 ? 0 : cache[pulses]+1;
|
||||
}
|
||||
|
||||
/** Compute the pulse allocation, i.e. how many pulses will go in each
|
||||
* band.
|
||||
@param m mode
|
||||
@param offsets Requested increase or decrease in the number of bits for
|
||||
each band
|
||||
@param total Number of bands
|
||||
@param pulses Number of pulses per band (returned)
|
||||
@return Total number of bits allocated
|
||||
*/
|
||||
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
|
||||
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (C) 2002-2003 Jean-Marc Valin
|
||||
Copyright (C) 2007-2009 Xiph.Org Foundation */
|
||||
/**
|
||||
@file stack_alloc.h
|
||||
@brief Temporary memory allocation on stack
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_H
|
||||
#define STACK_ALLOC_H
|
||||
|
||||
#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
|
||||
#error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALLOCA
|
||||
# ifdef WIN32
|
||||
# include <malloc.h>
|
||||
# else
|
||||
# ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def ALIGN(stack, size)
|
||||
*
|
||||
* Aligns the stack to a 'size' boundary
|
||||
*
|
||||
* @param stack Stack
|
||||
* @param size New size boundary
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def PUSH(stack, size, type)
|
||||
*
|
||||
* Allocates 'size' elements of type 'type' on the stack
|
||||
*
|
||||
* @param stack Stack
|
||||
* @param size Number of elements
|
||||
* @param type Type of element
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def VARDECL(var)
|
||||
*
|
||||
* Declare variable on stack
|
||||
*
|
||||
* @param var Variable to declare
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def ALLOC(var, size, type)
|
||||
*
|
||||
* Allocate 'size' elements of 'type' on stack
|
||||
*
|
||||
* @param var Name of variable to allocate
|
||||
* @param size Number of elements
|
||||
* @param type Type of element
|
||||
*/
|
||||
|
||||
#if defined(VAR_ARRAYS)
|
||||
|
||||
#define VARDECL(type, var)
|
||||
#define ALLOC(var, size, type) type var[size]
|
||||
#define SAVE_STACK
|
||||
#define RESTORE_STACK
|
||||
#define ALLOC_STACK
|
||||
|
||||
#elif defined(USE_ALLOCA)
|
||||
|
||||
#define VARDECL(type, var) type *var
|
||||
|
||||
# ifdef WIN32
|
||||
# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
|
||||
# else
|
||||
# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
|
||||
# endif
|
||||
|
||||
#define SAVE_STACK
|
||||
#define RESTORE_STACK
|
||||
#define ALLOC_STACK
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CELT_C
|
||||
char *global_stack=0;
|
||||
#else
|
||||
extern char *global_stack;
|
||||
#endif /* CELT_C */
|
||||
|
||||
#ifdef ENABLE_VALGRIND
|
||||
|
||||
#include <valgrind/memcheck.h>
|
||||
|
||||
#ifdef CELT_C
|
||||
char *global_stack_top=0;
|
||||
#else
|
||||
extern char *global_stack_top;
|
||||
#endif /* CELT_C */
|
||||
|
||||
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
|
||||
#define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),sizeof(type)/sizeof(char)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char))))
|
||||
#define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
|
||||
#define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack;
|
||||
|
||||
#else
|
||||
|
||||
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
|
||||
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char))))
|
||||
#define RESTORE_STACK (global_stack = _saved_stack)
|
||||
#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? opus_alloc_scratch(GLOBAL_STACK_SIZE) : global_stack); _saved_stack = global_stack;
|
||||
|
||||
#endif /* ENABLE_VALGRIND */
|
||||
|
||||
#include "os_support.h"
|
||||
#define VARDECL(type, var) type *var
|
||||
#define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
|
||||
#define SAVE_STACK char *_saved_stack = global_stack;
|
||||
|
||||
#endif /* VAR_ARRAYS */
|
||||
|
||||
#endif /* STACK_ALLOC_H */
|
|
@ -0,0 +1,595 @@
|
|||
/* The contents of this file was automatically generated by dump_modes.c
|
||||
with arguments: 48000 960
|
||||
It contains static definitions for some pre-defined modes. */
|
||||
#include "modes.h"
|
||||
#include "rate.h"
|
||||
|
||||
#ifndef DEF_WINDOW120
|
||||
#define DEF_WINDOW120
|
||||
static const opus_val16 window120[120] = {
|
||||
2, 20, 55, 108, 178,
|
||||
266, 372, 494, 635, 792,
|
||||
966, 1157, 1365, 1590, 1831,
|
||||
2089, 2362, 2651, 2956, 3276,
|
||||
3611, 3961, 4325, 4703, 5094,
|
||||
5499, 5916, 6346, 6788, 7241,
|
||||
7705, 8179, 8663, 9156, 9657,
|
||||
10167, 10684, 11207, 11736, 12271,
|
||||
12810, 13353, 13899, 14447, 14997,
|
||||
15547, 16098, 16648, 17197, 17744,
|
||||
18287, 18827, 19363, 19893, 20418,
|
||||
20936, 21447, 21950, 22445, 22931,
|
||||
23407, 23874, 24330, 24774, 25208,
|
||||
25629, 26039, 26435, 26819, 27190,
|
||||
27548, 27893, 28224, 28541, 28845,
|
||||
29135, 29411, 29674, 29924, 30160,
|
||||
30384, 30594, 30792, 30977, 31151,
|
||||
31313, 31463, 31602, 31731, 31849,
|
||||
31958, 32057, 32148, 32229, 32303,
|
||||
32370, 32429, 32481, 32528, 32568,
|
||||
32604, 32634, 32661, 32683, 32701,
|
||||
32717, 32729, 32740, 32748, 32754,
|
||||
32758, 32762, 32764, 32766, 32767,
|
||||
32767, 32767, 32767, 32767, 32767,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DEF_LOGN400
|
||||
#define DEF_LOGN400
|
||||
static const opus_int16 logN400[21] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
|
||||
#endif
|
||||
|
||||
#ifndef DEF_PULSE_CACHE50
|
||||
#define DEF_PULSE_CACHE50
|
||||
static const opus_int16 cache_index50[105] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
|
||||
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
|
||||
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
|
||||
41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
|
||||
318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
|
||||
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
|
||||
};
|
||||
static const unsigned char cache_bits50[392] = {
|
||||
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
|
||||
31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
|
||||
51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
|
||||
66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
|
||||
64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
|
||||
94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
|
||||
124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
|
||||
97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
|
||||
142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
|
||||
28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
|
||||
153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
|
||||
229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
|
||||
166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
|
||||
86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
|
||||
25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
|
||||
185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
|
||||
110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
|
||||
74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
|
||||
163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
|
||||
228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
|
||||
90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
|
||||
87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
|
||||
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
|
||||
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
|
||||
182, 234, };
|
||||
static const unsigned char cache_caps50[168] = {
|
||||
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
|
||||
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
|
||||
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
|
||||
160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
|
||||
138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
|
||||
204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
|
||||
185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
|
||||
207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
|
||||
188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
|
||||
193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
|
||||
204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
|
||||
140, 66, 40, };
|
||||
#endif
|
||||
|
||||
#ifndef FFT_TWIDDLES48000_960
|
||||
#define FFT_TWIDDLES48000_960
|
||||
static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
|
||||
{32767, 0}, {32766, -429},
|
||||
{32757, -858}, {32743, -1287},
|
||||
{32724, -1715}, {32698, -2143},
|
||||
{32667, -2570}, {32631, -2998},
|
||||
{32588, -3425}, {32541, -3851},
|
||||
{32488, -4277}, {32429, -4701},
|
||||
{32364, -5125}, {32295, -5548},
|
||||
{32219, -5971}, {32138, -6393},
|
||||
{32051, -6813}, {31960, -7231},
|
||||
{31863, -7650}, {31760, -8067},
|
||||
{31652, -8481}, {31539, -8895},
|
||||
{31419, -9306}, {31294, -9716},
|
||||
{31165, -10126}, {31030, -10532},
|
||||
{30889, -10937}, {30743, -11340},
|
||||
{30592, -11741}, {30436, -12141},
|
||||
{30274, -12540}, {30107, -12935},
|
||||
{29936, -13328}, {29758, -13718},
|
||||
{29577, -14107}, {29390, -14493},
|
||||
{29197, -14875}, {29000, -15257},
|
||||
{28797, -15635}, {28590, -16010},
|
||||
{28379, -16384}, {28162, -16753},
|
||||
{27940, -17119}, {27714, -17484},
|
||||
{27482, -17845}, {27246, -18205},
|
||||
{27006, -18560}, {26760, -18911},
|
||||
{26510, -19260}, {26257, -19606},
|
||||
{25997, -19947}, {25734, -20286},
|
||||
{25466, -20621}, {25194, -20952},
|
||||
{24918, -21281}, {24637, -21605},
|
||||
{24353, -21926}, {24063, -22242},
|
||||
{23770, -22555}, {23473, -22865},
|
||||
{23171, -23171}, {22866, -23472},
|
||||
{22557, -23769}, {22244, -24063},
|
||||
{21927, -24352}, {21606, -24636},
|
||||
{21282, -24917}, {20954, -25194},
|
||||
{20622, -25465}, {20288, -25733},
|
||||
{19949, -25997}, {19607, -26255},
|
||||
{19261, -26509}, {18914, -26760},
|
||||
{18561, -27004}, {18205, -27246},
|
||||
{17846, -27481}, {17485, -27713},
|
||||
{17122, -27940}, {16755, -28162},
|
||||
{16385, -28378}, {16012, -28590},
|
||||
{15636, -28797}, {15258, -28999},
|
||||
{14878, -29197}, {14494, -29389},
|
||||
{14108, -29576}, {13720, -29757},
|
||||
{13329, -29934}, {12937, -30107},
|
||||
{12540, -30274}, {12142, -30435},
|
||||
{11744, -30592}, {11342, -30743},
|
||||
{10939, -30889}, {10534, -31030},
|
||||
{10127, -31164}, {9718, -31294},
|
||||
{9307, -31418}, {8895, -31537},
|
||||
{8482, -31652}, {8067, -31759},
|
||||
{7650, -31862}, {7233, -31960},
|
||||
{6815, -32051}, {6393, -32138},
|
||||
{5973, -32219}, {5549, -32294},
|
||||
{5127, -32364}, {4703, -32429},
|
||||
{4278, -32487}, {3852, -32541},
|
||||
{3426, -32588}, {2999, -32630},
|
||||
{2572, -32667}, {2144, -32698},
|
||||
{1716, -32724}, {1287, -32742},
|
||||
{860, -32757}, {430, -32766},
|
||||
{0, -32767}, {-429, -32766},
|
||||
{-858, -32757}, {-1287, -32743},
|
||||
{-1715, -32724}, {-2143, -32698},
|
||||
{-2570, -32667}, {-2998, -32631},
|
||||
{-3425, -32588}, {-3851, -32541},
|
||||
{-4277, -32488}, {-4701, -32429},
|
||||
{-5125, -32364}, {-5548, -32295},
|
||||
{-5971, -32219}, {-6393, -32138},
|
||||
{-6813, -32051}, {-7231, -31960},
|
||||
{-7650, -31863}, {-8067, -31760},
|
||||
{-8481, -31652}, {-8895, -31539},
|
||||
{-9306, -31419}, {-9716, -31294},
|
||||
{-10126, -31165}, {-10532, -31030},
|
||||
{-10937, -30889}, {-11340, -30743},
|
||||
{-11741, -30592}, {-12141, -30436},
|
||||
{-12540, -30274}, {-12935, -30107},
|
||||
{-13328, -29936}, {-13718, -29758},
|
||||
{-14107, -29577}, {-14493, -29390},
|
||||
{-14875, -29197}, {-15257, -29000},
|
||||
{-15635, -28797}, {-16010, -28590},
|
||||
{-16384, -28379}, {-16753, -28162},
|
||||
{-17119, -27940}, {-17484, -27714},
|
||||
{-17845, -27482}, {-18205, -27246},
|
||||
{-18560, -27006}, {-18911, -26760},
|
||||
{-19260, -26510}, {-19606, -26257},
|
||||
{-19947, -25997}, {-20286, -25734},
|
||||
{-20621, -25466}, {-20952, -25194},
|
||||
{-21281, -24918}, {-21605, -24637},
|
||||
{-21926, -24353}, {-22242, -24063},
|
||||
{-22555, -23770}, {-22865, -23473},
|
||||
{-23171, -23171}, {-23472, -22866},
|
||||
{-23769, -22557}, {-24063, -22244},
|
||||
{-24352, -21927}, {-24636, -21606},
|
||||
{-24917, -21282}, {-25194, -20954},
|
||||
{-25465, -20622}, {-25733, -20288},
|
||||
{-25997, -19949}, {-26255, -19607},
|
||||
{-26509, -19261}, {-26760, -18914},
|
||||
{-27004, -18561}, {-27246, -18205},
|
||||
{-27481, -17846}, {-27713, -17485},
|
||||
{-27940, -17122}, {-28162, -16755},
|
||||
{-28378, -16385}, {-28590, -16012},
|
||||
{-28797, -15636}, {-28999, -15258},
|
||||
{-29197, -14878}, {-29389, -14494},
|
||||
{-29576, -14108}, {-29757, -13720},
|
||||
{-29934, -13329}, {-30107, -12937},
|
||||
{-30274, -12540}, {-30435, -12142},
|
||||
{-30592, -11744}, {-30743, -11342},
|
||||
{-30889, -10939}, {-31030, -10534},
|
||||
{-31164, -10127}, {-31294, -9718},
|
||||
{-31418, -9307}, {-31537, -8895},
|
||||
{-31652, -8482}, {-31759, -8067},
|
||||
{-31862, -7650}, {-31960, -7233},
|
||||
{-32051, -6815}, {-32138, -6393},
|
||||
{-32219, -5973}, {-32294, -5549},
|
||||
{-32364, -5127}, {-32429, -4703},
|
||||
{-32487, -4278}, {-32541, -3852},
|
||||
{-32588, -3426}, {-32630, -2999},
|
||||
{-32667, -2572}, {-32698, -2144},
|
||||
{-32724, -1716}, {-32742, -1287},
|
||||
{-32757, -860}, {-32766, -430},
|
||||
{-32767, 0}, {-32766, 429},
|
||||
{-32757, 858}, {-32743, 1287},
|
||||
{-32724, 1715}, {-32698, 2143},
|
||||
{-32667, 2570}, {-32631, 2998},
|
||||
{-32588, 3425}, {-32541, 3851},
|
||||
{-32488, 4277}, {-32429, 4701},
|
||||
{-32364, 5125}, {-32295, 5548},
|
||||
{-32219, 5971}, {-32138, 6393},
|
||||
{-32051, 6813}, {-31960, 7231},
|
||||
{-31863, 7650}, {-31760, 8067},
|
||||
{-31652, 8481}, {-31539, 8895},
|
||||
{-31419, 9306}, {-31294, 9716},
|
||||
{-31165, 10126}, {-31030, 10532},
|
||||
{-30889, 10937}, {-30743, 11340},
|
||||
{-30592, 11741}, {-30436, 12141},
|
||||
{-30274, 12540}, {-30107, 12935},
|
||||
{-29936, 13328}, {-29758, 13718},
|
||||
{-29577, 14107}, {-29390, 14493},
|
||||
{-29197, 14875}, {-29000, 15257},
|
||||
{-28797, 15635}, {-28590, 16010},
|
||||
{-28379, 16384}, {-28162, 16753},
|
||||
{-27940, 17119}, {-27714, 17484},
|
||||
{-27482, 17845}, {-27246, 18205},
|
||||
{-27006, 18560}, {-26760, 18911},
|
||||
{-26510, 19260}, {-26257, 19606},
|
||||
{-25997, 19947}, {-25734, 20286},
|
||||
{-25466, 20621}, {-25194, 20952},
|
||||
{-24918, 21281}, {-24637, 21605},
|
||||
{-24353, 21926}, {-24063, 22242},
|
||||
{-23770, 22555}, {-23473, 22865},
|
||||
{-23171, 23171}, {-22866, 23472},
|
||||
{-22557, 23769}, {-22244, 24063},
|
||||
{-21927, 24352}, {-21606, 24636},
|
||||
{-21282, 24917}, {-20954, 25194},
|
||||
{-20622, 25465}, {-20288, 25733},
|
||||
{-19949, 25997}, {-19607, 26255},
|
||||
{-19261, 26509}, {-18914, 26760},
|
||||
{-18561, 27004}, {-18205, 27246},
|
||||
{-17846, 27481}, {-17485, 27713},
|
||||
{-17122, 27940}, {-16755, 28162},
|
||||
{-16385, 28378}, {-16012, 28590},
|
||||
{-15636, 28797}, {-15258, 28999},
|
||||
{-14878, 29197}, {-14494, 29389},
|
||||
{-14108, 29576}, {-13720, 29757},
|
||||
{-13329, 29934}, {-12937, 30107},
|
||||
{-12540, 30274}, {-12142, 30435},
|
||||
{-11744, 30592}, {-11342, 30743},
|
||||
{-10939, 30889}, {-10534, 31030},
|
||||
{-10127, 31164}, {-9718, 31294},
|
||||
{-9307, 31418}, {-8895, 31537},
|
||||
{-8482, 31652}, {-8067, 31759},
|
||||
{-7650, 31862}, {-7233, 31960},
|
||||
{-6815, 32051}, {-6393, 32138},
|
||||
{-5973, 32219}, {-5549, 32294},
|
||||
{-5127, 32364}, {-4703, 32429},
|
||||
{-4278, 32487}, {-3852, 32541},
|
||||
{-3426, 32588}, {-2999, 32630},
|
||||
{-2572, 32667}, {-2144, 32698},
|
||||
{-1716, 32724}, {-1287, 32742},
|
||||
{-860, 32757}, {-430, 32766},
|
||||
{0, 32767}, {429, 32766},
|
||||
{858, 32757}, {1287, 32743},
|
||||
{1715, 32724}, {2143, 32698},
|
||||
{2570, 32667}, {2998, 32631},
|
||||
{3425, 32588}, {3851, 32541},
|
||||
{4277, 32488}, {4701, 32429},
|
||||
{5125, 32364}, {5548, 32295},
|
||||
{5971, 32219}, {6393, 32138},
|
||||
{6813, 32051}, {7231, 31960},
|
||||
{7650, 31863}, {8067, 31760},
|
||||
{8481, 31652}, {8895, 31539},
|
||||
{9306, 31419}, {9716, 31294},
|
||||
{10126, 31165}, {10532, 31030},
|
||||
{10937, 30889}, {11340, 30743},
|
||||
{11741, 30592}, {12141, 30436},
|
||||
{12540, 30274}, {12935, 30107},
|
||||
{13328, 29936}, {13718, 29758},
|
||||
{14107, 29577}, {14493, 29390},
|
||||
{14875, 29197}, {15257, 29000},
|
||||
{15635, 28797}, {16010, 28590},
|
||||
{16384, 28379}, {16753, 28162},
|
||||
{17119, 27940}, {17484, 27714},
|
||||
{17845, 27482}, {18205, 27246},
|
||||
{18560, 27006}, {18911, 26760},
|
||||
{19260, 26510}, {19606, 26257},
|
||||
{19947, 25997}, {20286, 25734},
|
||||
{20621, 25466}, {20952, 25194},
|
||||
{21281, 24918}, {21605, 24637},
|
||||
{21926, 24353}, {22242, 24063},
|
||||
{22555, 23770}, {22865, 23473},
|
||||
{23171, 23171}, {23472, 22866},
|
||||
{23769, 22557}, {24063, 22244},
|
||||
{24352, 21927}, {24636, 21606},
|
||||
{24917, 21282}, {25194, 20954},
|
||||
{25465, 20622}, {25733, 20288},
|
||||
{25997, 19949}, {26255, 19607},
|
||||
{26509, 19261}, {26760, 18914},
|
||||
{27004, 18561}, {27246, 18205},
|
||||
{27481, 17846}, {27713, 17485},
|
||||
{27940, 17122}, {28162, 16755},
|
||||
{28378, 16385}, {28590, 16012},
|
||||
{28797, 15636}, {28999, 15258},
|
||||
{29197, 14878}, {29389, 14494},
|
||||
{29576, 14108}, {29757, 13720},
|
||||
{29934, 13329}, {30107, 12937},
|
||||
{30274, 12540}, {30435, 12142},
|
||||
{30592, 11744}, {30743, 11342},
|
||||
{30889, 10939}, {31030, 10534},
|
||||
{31164, 10127}, {31294, 9718},
|
||||
{31418, 9307}, {31537, 8895},
|
||||
{31652, 8482}, {31759, 8067},
|
||||
{31862, 7650}, {31960, 7233},
|
||||
{32051, 6815}, {32138, 6393},
|
||||
{32219, 5973}, {32294, 5549},
|
||||
{32364, 5127}, {32429, 4703},
|
||||
{32487, 4278}, {32541, 3852},
|
||||
{32588, 3426}, {32630, 2999},
|
||||
{32667, 2572}, {32698, 2144},
|
||||
{32724, 1716}, {32742, 1287},
|
||||
{32757, 860}, {32766, 430},
|
||||
};
|
||||
#ifndef FFT_BITREV480
|
||||
#define FFT_BITREV480
|
||||
static const opus_int16 fft_bitrev480[480] = {
|
||||
0, 120, 240, 360, 30, 150, 270, 390, 60, 180, 300, 420, 90, 210, 330,
|
||||
450, 15, 135, 255, 375, 45, 165, 285, 405, 75, 195, 315, 435, 105, 225,
|
||||
345, 465, 5, 125, 245, 365, 35, 155, 275, 395, 65, 185, 305, 425, 95,
|
||||
215, 335, 455, 20, 140, 260, 380, 50, 170, 290, 410, 80, 200, 320, 440,
|
||||
110, 230, 350, 470, 10, 130, 250, 370, 40, 160, 280, 400, 70, 190, 310,
|
||||
430, 100, 220, 340, 460, 25, 145, 265, 385, 55, 175, 295, 415, 85, 205,
|
||||
325, 445, 115, 235, 355, 475, 1, 121, 241, 361, 31, 151, 271, 391, 61,
|
||||
181, 301, 421, 91, 211, 331, 451, 16, 136, 256, 376, 46, 166, 286, 406,
|
||||
76, 196, 316, 436, 106, 226, 346, 466, 6, 126, 246, 366, 36, 156, 276,
|
||||
396, 66, 186, 306, 426, 96, 216, 336, 456, 21, 141, 261, 381, 51, 171,
|
||||
291, 411, 81, 201, 321, 441, 111, 231, 351, 471, 11, 131, 251, 371, 41,
|
||||
161, 281, 401, 71, 191, 311, 431, 101, 221, 341, 461, 26, 146, 266, 386,
|
||||
56, 176, 296, 416, 86, 206, 326, 446, 116, 236, 356, 476, 2, 122, 242,
|
||||
362, 32, 152, 272, 392, 62, 182, 302, 422, 92, 212, 332, 452, 17, 137,
|
||||
257, 377, 47, 167, 287, 407, 77, 197, 317, 437, 107, 227, 347, 467, 7,
|
||||
127, 247, 367, 37, 157, 277, 397, 67, 187, 307, 427, 97, 217, 337, 457,
|
||||
22, 142, 262, 382, 52, 172, 292, 412, 82, 202, 322, 442, 112, 232, 352,
|
||||
472, 12, 132, 252, 372, 42, 162, 282, 402, 72, 192, 312, 432, 102, 222,
|
||||
342, 462, 27, 147, 267, 387, 57, 177, 297, 417, 87, 207, 327, 447, 117,
|
||||
237, 357, 477, 3, 123, 243, 363, 33, 153, 273, 393, 63, 183, 303, 423,
|
||||
93, 213, 333, 453, 18, 138, 258, 378, 48, 168, 288, 408, 78, 198, 318,
|
||||
438, 108, 228, 348, 468, 8, 128, 248, 368, 38, 158, 278, 398, 68, 188,
|
||||
308, 428, 98, 218, 338, 458, 23, 143, 263, 383, 53, 173, 293, 413, 83,
|
||||
203, 323, 443, 113, 233, 353, 473, 13, 133, 253, 373, 43, 163, 283, 403,
|
||||
73, 193, 313, 433, 103, 223, 343, 463, 28, 148, 268, 388, 58, 178, 298,
|
||||
418, 88, 208, 328, 448, 118, 238, 358, 478, 4, 124, 244, 364, 34, 154,
|
||||
274, 394, 64, 184, 304, 424, 94, 214, 334, 454, 19, 139, 259, 379, 49,
|
||||
169, 289, 409, 79, 199, 319, 439, 109, 229, 349, 469, 9, 129, 249, 369,
|
||||
39, 159, 279, 399, 69, 189, 309, 429, 99, 219, 339, 459, 24, 144, 264,
|
||||
384, 54, 174, 294, 414, 84, 204, 324, 444, 114, 234, 354, 474, 14, 134,
|
||||
254, 374, 44, 164, 284, 404, 74, 194, 314, 434, 104, 224, 344, 464, 29,
|
||||
149, 269, 389, 59, 179, 299, 419, 89, 209, 329, 449, 119, 239, 359, 479,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV240
|
||||
#define FFT_BITREV240
|
||||
static const opus_int16 fft_bitrev240[240] = {
|
||||
0, 60, 120, 180, 15, 75, 135, 195, 30, 90, 150, 210, 45, 105, 165,
|
||||
225, 5, 65, 125, 185, 20, 80, 140, 200, 35, 95, 155, 215, 50, 110,
|
||||
170, 230, 10, 70, 130, 190, 25, 85, 145, 205, 40, 100, 160, 220, 55,
|
||||
115, 175, 235, 1, 61, 121, 181, 16, 76, 136, 196, 31, 91, 151, 211,
|
||||
46, 106, 166, 226, 6, 66, 126, 186, 21, 81, 141, 201, 36, 96, 156,
|
||||
216, 51, 111, 171, 231, 11, 71, 131, 191, 26, 86, 146, 206, 41, 101,
|
||||
161, 221, 56, 116, 176, 236, 2, 62, 122, 182, 17, 77, 137, 197, 32,
|
||||
92, 152, 212, 47, 107, 167, 227, 7, 67, 127, 187, 22, 82, 142, 202,
|
||||
37, 97, 157, 217, 52, 112, 172, 232, 12, 72, 132, 192, 27, 87, 147,
|
||||
207, 42, 102, 162, 222, 57, 117, 177, 237, 3, 63, 123, 183, 18, 78,
|
||||
138, 198, 33, 93, 153, 213, 48, 108, 168, 228, 8, 68, 128, 188, 23,
|
||||
83, 143, 203, 38, 98, 158, 218, 53, 113, 173, 233, 13, 73, 133, 193,
|
||||
28, 88, 148, 208, 43, 103, 163, 223, 58, 118, 178, 238, 4, 64, 124,
|
||||
184, 19, 79, 139, 199, 34, 94, 154, 214, 49, 109, 169, 229, 9, 69,
|
||||
129, 189, 24, 84, 144, 204, 39, 99, 159, 219, 54, 114, 174, 234, 14,
|
||||
74, 134, 194, 29, 89, 149, 209, 44, 104, 164, 224, 59, 119, 179, 239,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV120
|
||||
#define FFT_BITREV120
|
||||
static const opus_int16 fft_bitrev120[120] = {
|
||||
0, 30, 60, 90, 15, 45, 75, 105, 5, 35, 65, 95, 20, 50, 80,
|
||||
110, 10, 40, 70, 100, 25, 55, 85, 115, 1, 31, 61, 91, 16, 46,
|
||||
76, 106, 6, 36, 66, 96, 21, 51, 81, 111, 11, 41, 71, 101, 26,
|
||||
56, 86, 116, 2, 32, 62, 92, 17, 47, 77, 107, 7, 37, 67, 97,
|
||||
22, 52, 82, 112, 12, 42, 72, 102, 27, 57, 87, 117, 3, 33, 63,
|
||||
93, 18, 48, 78, 108, 8, 38, 68, 98, 23, 53, 83, 113, 13, 43,
|
||||
73, 103, 28, 58, 88, 118, 4, 34, 64, 94, 19, 49, 79, 109, 9,
|
||||
39, 69, 99, 24, 54, 84, 114, 14, 44, 74, 104, 29, 59, 89, 119,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV60
|
||||
#define FFT_BITREV60
|
||||
static const opus_int16 fft_bitrev60[60] = {
|
||||
0, 15, 30, 45, 5, 20, 35, 50, 10, 25, 40, 55, 1, 16, 31,
|
||||
46, 6, 21, 36, 51, 11, 26, 41, 56, 2, 17, 32, 47, 7, 22,
|
||||
37, 52, 12, 27, 42, 57, 3, 18, 33, 48, 8, 23, 38, 53, 13,
|
||||
28, 43, 58, 4, 19, 34, 49, 9, 24, 39, 54, 14, 29, 44, 59,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_0
|
||||
#define FFT_STATE48000_960_0
|
||||
static const kiss_fft_state fft_state48000_960_0 = {
|
||||
480, /* nfft */
|
||||
-1, /* shift */
|
||||
{4, 120, 4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev480, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_1
|
||||
#define FFT_STATE48000_960_1
|
||||
static const kiss_fft_state fft_state48000_960_1 = {
|
||||
240, /* nfft */
|
||||
1, /* shift */
|
||||
{4, 60, 4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev240, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_2
|
||||
#define FFT_STATE48000_960_2
|
||||
static const kiss_fft_state fft_state48000_960_2 = {
|
||||
120, /* nfft */
|
||||
2, /* shift */
|
||||
{4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev120, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_3
|
||||
#define FFT_STATE48000_960_3
|
||||
static const kiss_fft_state fft_state48000_960_3 = {
|
||||
60, /* nfft */
|
||||
3, /* shift */
|
||||
{4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev60, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MDCT_TWIDDLES960
|
||||
#define MDCT_TWIDDLES960
|
||||
static const opus_val16 mdct_twiddles960[481] = {
|
||||
32767, 32767, 32767, 32767, 32766,
|
||||
32763, 32762, 32759, 32757, 32753,
|
||||
32751, 32747, 32743, 32738, 32733,
|
||||
32729, 32724, 32717, 32711, 32705,
|
||||
32698, 32690, 32683, 32676, 32667,
|
||||
32658, 32650, 32640, 32631, 32620,
|
||||
32610, 32599, 32588, 32577, 32566,
|
||||
32554, 32541, 32528, 32515, 32502,
|
||||
32487, 32474, 32459, 32444, 32429,
|
||||
32413, 32397, 32381, 32364, 32348,
|
||||
32331, 32313, 32294, 32277, 32257,
|
||||
32239, 32219, 32200, 32180, 32159,
|
||||
32138, 32118, 32096, 32074, 32051,
|
||||
32029, 32006, 31984, 31960, 31936,
|
||||
31912, 31888, 31863, 31837, 31812,
|
||||
31786, 31760, 31734, 31707, 31679,
|
||||
31652, 31624, 31596, 31567, 31539,
|
||||
31508, 31479, 31450, 31419, 31388,
|
||||
31357, 31326, 31294, 31262, 31230,
|
||||
31198, 31164, 31131, 31097, 31063,
|
||||
31030, 30994, 30959, 30924, 30889,
|
||||
30853, 30816, 30779, 30743, 30705,
|
||||
30668, 30629, 30592, 30553, 30515,
|
||||
30475, 30435, 30396, 30356, 30315,
|
||||
30274, 30233, 30191, 30149, 30107,
|
||||
30065, 30022, 29979, 29936, 29891,
|
||||
29847, 29803, 29758, 29713, 29668,
|
||||
29622, 29577, 29529, 29483, 29436,
|
||||
29390, 29341, 29293, 29246, 29197,
|
||||
29148, 29098, 29050, 29000, 28949,
|
||||
28899, 28848, 28797, 28746, 28694,
|
||||
28642, 28590, 28537, 28485, 28432,
|
||||
28378, 28324, 28271, 28217, 28162,
|
||||
28106, 28051, 27995, 27940, 27884,
|
||||
27827, 27770, 27713, 27657, 27598,
|
||||
27540, 27481, 27423, 27365, 27305,
|
||||
27246, 27187, 27126, 27066, 27006,
|
||||
26945, 26883, 26822, 26760, 26698,
|
||||
26636, 26574, 26510, 26448, 26383,
|
||||
26320, 26257, 26191, 26127, 26062,
|
||||
25997, 25931, 25866, 25800, 25734,
|
||||
25667, 25601, 25533, 25466, 25398,
|
||||
25330, 25262, 25194, 25125, 25056,
|
||||
24987, 24917, 24848, 24778, 24707,
|
||||
24636, 24566, 24495, 24424, 24352,
|
||||
24280, 24208, 24135, 24063, 23990,
|
||||
23917, 23842, 23769, 23695, 23622,
|
||||
23546, 23472, 23398, 23322, 23246,
|
||||
23171, 23095, 23018, 22942, 22866,
|
||||
22788, 22711, 22634, 22557, 22478,
|
||||
22400, 22322, 22244, 22165, 22085,
|
||||
22006, 21927, 21846, 21766, 21687,
|
||||
21606, 21524, 21443, 21363, 21282,
|
||||
21199, 21118, 21035, 20954, 20870,
|
||||
20788, 20705, 20621, 20538, 20455,
|
||||
20371, 20286, 20202, 20118, 20034,
|
||||
19947, 19863, 19777, 19692, 19606,
|
||||
19520, 19434, 19347, 19260, 19174,
|
||||
19088, 18999, 18911, 18825, 18737,
|
||||
18648, 18560, 18472, 18384, 18294,
|
||||
18205, 18116, 18025, 17936, 17846,
|
||||
17757, 17666, 17576, 17485, 17395,
|
||||
17303, 17212, 17122, 17030, 16937,
|
||||
16846, 16755, 16662, 16569, 16477,
|
||||
16385, 16291, 16198, 16105, 16012,
|
||||
15917, 15824, 15730, 15636, 15541,
|
||||
15447, 15352, 15257, 15162, 15067,
|
||||
14973, 14875, 14781, 14685, 14589,
|
||||
14493, 14396, 14300, 14204, 14107,
|
||||
14010, 13914, 13815, 13718, 13621,
|
||||
13524, 13425, 13328, 13230, 13133,
|
||||
13033, 12935, 12836, 12738, 12638,
|
||||
12540, 12441, 12341, 12241, 12142,
|
||||
12044, 11943, 11843, 11744, 11643,
|
||||
11542, 11442, 11342, 11241, 11139,
|
||||
11039, 10939, 10836, 10736, 10635,
|
||||
10534, 10431, 10330, 10228, 10127,
|
||||
10024, 9921, 9820, 9718, 9614,
|
||||
9512, 9410, 9306, 9204, 9101,
|
||||
8998, 8895, 8791, 8689, 8585,
|
||||
8481, 8377, 8274, 8171, 8067,
|
||||
7962, 7858, 7753, 7650, 7545,
|
||||
7441, 7336, 7231, 7129, 7023,
|
||||
6917, 6813, 6709, 6604, 6498,
|
||||
6393, 6288, 6182, 6077, 5973,
|
||||
5867, 5760, 5656, 5549, 5445,
|
||||
5339, 5232, 5127, 5022, 4914,
|
||||
4809, 4703, 4596, 4490, 4384,
|
||||
4278, 4171, 4065, 3958, 3852,
|
||||
3745, 3640, 3532, 3426, 3318,
|
||||
3212, 3106, 2998, 2891, 2786,
|
||||
2679, 2570, 2465, 2358, 2251,
|
||||
2143, 2037, 1929, 1823, 1715,
|
||||
1609, 1501, 1393, 1287, 1180,
|
||||
1073, 964, 858, 751, 644,
|
||||
535, 429, 322, 214, 107,
|
||||
0, };
|
||||
#endif
|
||||
|
||||
static const CELTMode mode48000_960_120 = {
|
||||
48000, /* Fs */
|
||||
120, /* overlap */
|
||||
21, /* nbEBands */
|
||||
21, /* effEBands */
|
||||
{27853, 0, 4096, 8192, }, /* preemph */
|
||||
eband5ms, /* eBands */
|
||||
3, /* maxLM */
|
||||
8, /* nbShortMdcts */
|
||||
120, /* shortMdctSize */
|
||||
11, /* nbAllocVectors */
|
||||
band_allocation, /* allocVectors */
|
||||
logN400, /* logN */
|
||||
window120, /* window */
|
||||
{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
|
||||
{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
|
||||
};
|
||||
|
||||
/* List of all the available modes */
|
||||
#define TOTAL_MODES 1
|
||||
static const CELTMode * const static_mode_list[TOTAL_MODES] = {
|
||||
&mode48000_960_120,
|
||||
};
|
|
@ -0,0 +1,599 @@
|
|||
/* The contents of this file was automatically generated by dump_modes.c
|
||||
with arguments: 48000 960
|
||||
It contains static definitions for some pre-defined modes. */
|
||||
#include "modes.h"
|
||||
#include "rate.h"
|
||||
|
||||
#ifndef DEF_WINDOW120
|
||||
#define DEF_WINDOW120
|
||||
static const opus_val16 window120[120] = {
|
||||
6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f,
|
||||
0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f,
|
||||
0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f,
|
||||
0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f,
|
||||
0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f,
|
||||
0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f,
|
||||
0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f,
|
||||
0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f,
|
||||
0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f,
|
||||
0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f,
|
||||
0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f,
|
||||
0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f,
|
||||
0.71433873f, 0.72857055f, 0.74248043f, 0.75605424f, 0.76927895f,
|
||||
0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f,
|
||||
0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f,
|
||||
0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f,
|
||||
0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f,
|
||||
0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f,
|
||||
0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f,
|
||||
0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f,
|
||||
0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f,
|
||||
0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f,
|
||||
0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f,
|
||||
0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DEF_LOGN400
|
||||
#define DEF_LOGN400
|
||||
static const opus_int16 logN400[21] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
|
||||
#endif
|
||||
|
||||
#ifndef DEF_PULSE_CACHE50
|
||||
#define DEF_PULSE_CACHE50
|
||||
static const opus_int16 cache_index50[105] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
|
||||
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
|
||||
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
|
||||
41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
|
||||
318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
|
||||
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
|
||||
};
|
||||
static const unsigned char cache_bits50[392] = {
|
||||
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
|
||||
31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
|
||||
51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
|
||||
66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
|
||||
64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
|
||||
94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
|
||||
124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
|
||||
97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
|
||||
142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
|
||||
28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
|
||||
153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
|
||||
229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
|
||||
166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
|
||||
86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
|
||||
25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
|
||||
185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
|
||||
110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
|
||||
74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
|
||||
163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
|
||||
228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
|
||||
90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
|
||||
87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
|
||||
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
|
||||
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
|
||||
182, 234, };
|
||||
static const unsigned char cache_caps50[168] = {
|
||||
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
|
||||
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
|
||||
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
|
||||
160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
|
||||
138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
|
||||
204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
|
||||
185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
|
||||
207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
|
||||
188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
|
||||
193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
|
||||
204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
|
||||
140, 66, 40, };
|
||||
#endif
|
||||
|
||||
#ifndef FFT_TWIDDLES48000_960
|
||||
#define FFT_TWIDDLES48000_960
|
||||
static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
|
||||
{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f},
|
||||
{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f},
|
||||
{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f},
|
||||
{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f},
|
||||
{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f},
|
||||
{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f},
|
||||
{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f},
|
||||
{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f},
|
||||
{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f},
|
||||
{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f},
|
||||
{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f},
|
||||
{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f},
|
||||
{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f},
|
||||
{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f},
|
||||
{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f},
|
||||
{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f},
|
||||
{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f},
|
||||
{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f},
|
||||
{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f},
|
||||
{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f},
|
||||
{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f},
|
||||
{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f},
|
||||
{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f},
|
||||
{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f},
|
||||
{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f},
|
||||
{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f},
|
||||
{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f},
|
||||
{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f},
|
||||
{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f},
|
||||
{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f},
|
||||
{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f},
|
||||
{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f},
|
||||
{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f},
|
||||
{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f},
|
||||
{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f},
|
||||
{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f},
|
||||
{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f},
|
||||
{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f},
|
||||
{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f},
|
||||
{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f},
|
||||
{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f},
|
||||
{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f},
|
||||
{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f},
|
||||
{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f},
|
||||
{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f},
|
||||
{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f},
|
||||
{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f},
|
||||
{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f},
|
||||
{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f},
|
||||
{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f},
|
||||
{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f},
|
||||
{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f},
|
||||
{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f},
|
||||
{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f},
|
||||
{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f},
|
||||
{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f},
|
||||
{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f},
|
||||
{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f},
|
||||
{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f},
|
||||
{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f},
|
||||
{6.1230318e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f},
|
||||
{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f},
|
||||
{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f},
|
||||
{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f},
|
||||
{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f},
|
||||
{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f},
|
||||
{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f},
|
||||
{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f},
|
||||
{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f},
|
||||
{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f},
|
||||
{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f},
|
||||
{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f},
|
||||
{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f},
|
||||
{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f},
|
||||
{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f},
|
||||
{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f},
|
||||
{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f},
|
||||
{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f},
|
||||
{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f},
|
||||
{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f},
|
||||
{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f},
|
||||
{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f},
|
||||
{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f},
|
||||
{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f},
|
||||
{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f},
|
||||
{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f},
|
||||
{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f},
|
||||
{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f},
|
||||
{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f},
|
||||
{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f},
|
||||
{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f},
|
||||
{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f},
|
||||
{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f},
|
||||
{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f},
|
||||
{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f},
|
||||
{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f},
|
||||
{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f},
|
||||
{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f},
|
||||
{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f},
|
||||
{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f},
|
||||
{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f},
|
||||
{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f},
|
||||
{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f},
|
||||
{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f},
|
||||
{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f},
|
||||
{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f},
|
||||
{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f},
|
||||
{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f},
|
||||
{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f},
|
||||
{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f},
|
||||
{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f},
|
||||
{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f},
|
||||
{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f},
|
||||
{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f},
|
||||
{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f},
|
||||
{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f},
|
||||
{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f},
|
||||
{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f},
|
||||
{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f},
|
||||
{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f},
|
||||
{-1.0000000f, -1.2246064e-16f}, {-0.99991433f, 0.013089596f},
|
||||
{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f},
|
||||
{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f},
|
||||
{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f},
|
||||
{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f},
|
||||
{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f},
|
||||
{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f},
|
||||
{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f},
|
||||
{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f},
|
||||
{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f},
|
||||
{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f},
|
||||
{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f},
|
||||
{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f},
|
||||
{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f},
|
||||
{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f},
|
||||
{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f},
|
||||
{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f},
|
||||
{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f},
|
||||
{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f},
|
||||
{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f},
|
||||
{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f},
|
||||
{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f},
|
||||
{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f},
|
||||
{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f},
|
||||
{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f},
|
||||
{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f},
|
||||
{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f},
|
||||
{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f},
|
||||
{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f},
|
||||
{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f},
|
||||
{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f},
|
||||
{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f},
|
||||
{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f},
|
||||
{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f},
|
||||
{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f},
|
||||
{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f},
|
||||
{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f},
|
||||
{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f},
|
||||
{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f},
|
||||
{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f},
|
||||
{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f},
|
||||
{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f},
|
||||
{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f},
|
||||
{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f},
|
||||
{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f},
|
||||
{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f},
|
||||
{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f},
|
||||
{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f},
|
||||
{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f},
|
||||
{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f},
|
||||
{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f},
|
||||
{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f},
|
||||
{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f},
|
||||
{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f},
|
||||
{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f},
|
||||
{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f},
|
||||
{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f},
|
||||
{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f},
|
||||
{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f},
|
||||
{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f},
|
||||
{-1.8369095e-16f, 1.0000000f}, {0.013089596f, 0.99991433f},
|
||||
{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f},
|
||||
{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f},
|
||||
{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f},
|
||||
{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f},
|
||||
{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f},
|
||||
{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f},
|
||||
{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f},
|
||||
{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f},
|
||||
{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f},
|
||||
{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f},
|
||||
{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f},
|
||||
{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f},
|
||||
{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f},
|
||||
{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f},
|
||||
{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f},
|
||||
{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f},
|
||||
{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f},
|
||||
{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f},
|
||||
{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f},
|
||||
{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f},
|
||||
{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f},
|
||||
{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f},
|
||||
{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f},
|
||||
{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f},
|
||||
{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f},
|
||||
{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f},
|
||||
{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f},
|
||||
{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f},
|
||||
{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f},
|
||||
{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f},
|
||||
{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f},
|
||||
{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f},
|
||||
{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f},
|
||||
{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f},
|
||||
{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f},
|
||||
{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f},
|
||||
{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f},
|
||||
{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f},
|
||||
{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f},
|
||||
{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f},
|
||||
{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f},
|
||||
{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f},
|
||||
{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f},
|
||||
{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f},
|
||||
{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f},
|
||||
{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f},
|
||||
{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f},
|
||||
{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f},
|
||||
{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f},
|
||||
{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f},
|
||||
{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f},
|
||||
{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f},
|
||||
{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f},
|
||||
{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f},
|
||||
{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f},
|
||||
{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f},
|
||||
{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f},
|
||||
{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f},
|
||||
{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f},
|
||||
};
|
||||
#ifndef FFT_BITREV480
|
||||
#define FFT_BITREV480
|
||||
static const opus_int16 fft_bitrev480[480] = {
|
||||
0, 120, 240, 360, 30, 150, 270, 390, 60, 180, 300, 420, 90, 210, 330,
|
||||
450, 15, 135, 255, 375, 45, 165, 285, 405, 75, 195, 315, 435, 105, 225,
|
||||
345, 465, 5, 125, 245, 365, 35, 155, 275, 395, 65, 185, 305, 425, 95,
|
||||
215, 335, 455, 20, 140, 260, 380, 50, 170, 290, 410, 80, 200, 320, 440,
|
||||
110, 230, 350, 470, 10, 130, 250, 370, 40, 160, 280, 400, 70, 190, 310,
|
||||
430, 100, 220, 340, 460, 25, 145, 265, 385, 55, 175, 295, 415, 85, 205,
|
||||
325, 445, 115, 235, 355, 475, 1, 121, 241, 361, 31, 151, 271, 391, 61,
|
||||
181, 301, 421, 91, 211, 331, 451, 16, 136, 256, 376, 46, 166, 286, 406,
|
||||
76, 196, 316, 436, 106, 226, 346, 466, 6, 126, 246, 366, 36, 156, 276,
|
||||
396, 66, 186, 306, 426, 96, 216, 336, 456, 21, 141, 261, 381, 51, 171,
|
||||
291, 411, 81, 201, 321, 441, 111, 231, 351, 471, 11, 131, 251, 371, 41,
|
||||
161, 281, 401, 71, 191, 311, 431, 101, 221, 341, 461, 26, 146, 266, 386,
|
||||
56, 176, 296, 416, 86, 206, 326, 446, 116, 236, 356, 476, 2, 122, 242,
|
||||
362, 32, 152, 272, 392, 62, 182, 302, 422, 92, 212, 332, 452, 17, 137,
|
||||
257, 377, 47, 167, 287, 407, 77, 197, 317, 437, 107, 227, 347, 467, 7,
|
||||
127, 247, 367, 37, 157, 277, 397, 67, 187, 307, 427, 97, 217, 337, 457,
|
||||
22, 142, 262, 382, 52, 172, 292, 412, 82, 202, 322, 442, 112, 232, 352,
|
||||
472, 12, 132, 252, 372, 42, 162, 282, 402, 72, 192, 312, 432, 102, 222,
|
||||
342, 462, 27, 147, 267, 387, 57, 177, 297, 417, 87, 207, 327, 447, 117,
|
||||
237, 357, 477, 3, 123, 243, 363, 33, 153, 273, 393, 63, 183, 303, 423,
|
||||
93, 213, 333, 453, 18, 138, 258, 378, 48, 168, 288, 408, 78, 198, 318,
|
||||
438, 108, 228, 348, 468, 8, 128, 248, 368, 38, 158, 278, 398, 68, 188,
|
||||
308, 428, 98, 218, 338, 458, 23, 143, 263, 383, 53, 173, 293, 413, 83,
|
||||
203, 323, 443, 113, 233, 353, 473, 13, 133, 253, 373, 43, 163, 283, 403,
|
||||
73, 193, 313, 433, 103, 223, 343, 463, 28, 148, 268, 388, 58, 178, 298,
|
||||
418, 88, 208, 328, 448, 118, 238, 358, 478, 4, 124, 244, 364, 34, 154,
|
||||
274, 394, 64, 184, 304, 424, 94, 214, 334, 454, 19, 139, 259, 379, 49,
|
||||
169, 289, 409, 79, 199, 319, 439, 109, 229, 349, 469, 9, 129, 249, 369,
|
||||
39, 159, 279, 399, 69, 189, 309, 429, 99, 219, 339, 459, 24, 144, 264,
|
||||
384, 54, 174, 294, 414, 84, 204, 324, 444, 114, 234, 354, 474, 14, 134,
|
||||
254, 374, 44, 164, 284, 404, 74, 194, 314, 434, 104, 224, 344, 464, 29,
|
||||
149, 269, 389, 59, 179, 299, 419, 89, 209, 329, 449, 119, 239, 359, 479,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV240
|
||||
#define FFT_BITREV240
|
||||
static const opus_int16 fft_bitrev240[240] = {
|
||||
0, 60, 120, 180, 15, 75, 135, 195, 30, 90, 150, 210, 45, 105, 165,
|
||||
225, 5, 65, 125, 185, 20, 80, 140, 200, 35, 95, 155, 215, 50, 110,
|
||||
170, 230, 10, 70, 130, 190, 25, 85, 145, 205, 40, 100, 160, 220, 55,
|
||||
115, 175, 235, 1, 61, 121, 181, 16, 76, 136, 196, 31, 91, 151, 211,
|
||||
46, 106, 166, 226, 6, 66, 126, 186, 21, 81, 141, 201, 36, 96, 156,
|
||||
216, 51, 111, 171, 231, 11, 71, 131, 191, 26, 86, 146, 206, 41, 101,
|
||||
161, 221, 56, 116, 176, 236, 2, 62, 122, 182, 17, 77, 137, 197, 32,
|
||||
92, 152, 212, 47, 107, 167, 227, 7, 67, 127, 187, 22, 82, 142, 202,
|
||||
37, 97, 157, 217, 52, 112, 172, 232, 12, 72, 132, 192, 27, 87, 147,
|
||||
207, 42, 102, 162, 222, 57, 117, 177, 237, 3, 63, 123, 183, 18, 78,
|
||||
138, 198, 33, 93, 153, 213, 48, 108, 168, 228, 8, 68, 128, 188, 23,
|
||||
83, 143, 203, 38, 98, 158, 218, 53, 113, 173, 233, 13, 73, 133, 193,
|
||||
28, 88, 148, 208, 43, 103, 163, 223, 58, 118, 178, 238, 4, 64, 124,
|
||||
184, 19, 79, 139, 199, 34, 94, 154, 214, 49, 109, 169, 229, 9, 69,
|
||||
129, 189, 24, 84, 144, 204, 39, 99, 159, 219, 54, 114, 174, 234, 14,
|
||||
74, 134, 194, 29, 89, 149, 209, 44, 104, 164, 224, 59, 119, 179, 239,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV120
|
||||
#define FFT_BITREV120
|
||||
static const opus_int16 fft_bitrev120[120] = {
|
||||
0, 30, 60, 90, 15, 45, 75, 105, 5, 35, 65, 95, 20, 50, 80,
|
||||
110, 10, 40, 70, 100, 25, 55, 85, 115, 1, 31, 61, 91, 16, 46,
|
||||
76, 106, 6, 36, 66, 96, 21, 51, 81, 111, 11, 41, 71, 101, 26,
|
||||
56, 86, 116, 2, 32, 62, 92, 17, 47, 77, 107, 7, 37, 67, 97,
|
||||
22, 52, 82, 112, 12, 42, 72, 102, 27, 57, 87, 117, 3, 33, 63,
|
||||
93, 18, 48, 78, 108, 8, 38, 68, 98, 23, 53, 83, 113, 13, 43,
|
||||
73, 103, 28, 58, 88, 118, 4, 34, 64, 94, 19, 49, 79, 109, 9,
|
||||
39, 69, 99, 24, 54, 84, 114, 14, 44, 74, 104, 29, 59, 89, 119,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_BITREV60
|
||||
#define FFT_BITREV60
|
||||
static const opus_int16 fft_bitrev60[60] = {
|
||||
0, 15, 30, 45, 5, 20, 35, 50, 10, 25, 40, 55, 1, 16, 31,
|
||||
46, 6, 21, 36, 51, 11, 26, 41, 56, 2, 17, 32, 47, 7, 22,
|
||||
37, 52, 12, 27, 42, 57, 3, 18, 33, 48, 8, 23, 38, 53, 13,
|
||||
28, 43, 58, 4, 19, 34, 49, 9, 24, 39, 54, 14, 29, 44, 59,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_0
|
||||
#define FFT_STATE48000_960_0
|
||||
static const kiss_fft_state fft_state48000_960_0 = {
|
||||
480, /* nfft */
|
||||
0.002083333f, /* scale */
|
||||
-1, /* shift */
|
||||
{4, 120, 4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev480, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_1
|
||||
#define FFT_STATE48000_960_1
|
||||
static const kiss_fft_state fft_state48000_960_1 = {
|
||||
240, /* nfft */
|
||||
0.004166667f, /* scale */
|
||||
1, /* shift */
|
||||
{4, 60, 4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev240, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_2
|
||||
#define FFT_STATE48000_960_2
|
||||
static const kiss_fft_state fft_state48000_960_2 = {
|
||||
120, /* nfft */
|
||||
0.008333333f, /* scale */
|
||||
2, /* shift */
|
||||
{4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev120, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FFT_STATE48000_960_3
|
||||
#define FFT_STATE48000_960_3
|
||||
static const kiss_fft_state fft_state48000_960_3 = {
|
||||
60, /* nfft */
|
||||
0.016666667f, /* scale */
|
||||
3, /* shift */
|
||||
{4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
|
||||
fft_bitrev60, /* bitrev */
|
||||
fft_twiddles48000_960, /* bitrev */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MDCT_TWIDDLES960
|
||||
#define MDCT_TWIDDLES960
|
||||
static const opus_val16 mdct_twiddles960[481] = {
|
||||
1.0000000f, 0.99999465f, 0.99997858f, 0.99995181f, 0.99991433f,
|
||||
0.99986614f, 0.99980724f, 0.99973764f, 0.99965732f, 0.99956631f,
|
||||
0.99946459f, 0.99935216f, 0.99922904f, 0.99909521f, 0.99895068f,
|
||||
0.99879546f, 0.99862953f, 0.99845292f, 0.99826561f, 0.99806761f,
|
||||
0.99785892f, 0.99763955f, 0.99740949f, 0.99716875f, 0.99691733f,
|
||||
0.99665524f, 0.99638247f, 0.99609903f, 0.99580493f, 0.99550016f,
|
||||
0.99518473f, 0.99485864f, 0.99452190f, 0.99417450f, 0.99381646f,
|
||||
0.99344778f, 0.99306846f, 0.99267850f, 0.99227791f, 0.99186670f,
|
||||
0.99144486f, 0.99101241f, 0.99056934f, 0.99011566f, 0.98965139f,
|
||||
0.98917651f, 0.98869104f, 0.98819498f, 0.98768834f, 0.98717112f,
|
||||
0.98664333f, 0.98610497f, 0.98555606f, 0.98499659f, 0.98442657f,
|
||||
0.98384600f, 0.98325491f, 0.98265328f, 0.98204113f, 0.98141846f,
|
||||
0.98078528f, 0.98014159f, 0.97948742f, 0.97882275f, 0.97814760f,
|
||||
0.97746197f, 0.97676588f, 0.97605933f, 0.97534232f, 0.97461487f,
|
||||
0.97387698f, 0.97312866f, 0.97236992f, 0.97160077f, 0.97082121f,
|
||||
0.97003125f, 0.96923091f, 0.96842019f, 0.96759909f, 0.96676764f,
|
||||
0.96592582f, 0.96507367f, 0.96421118f, 0.96333837f, 0.96245523f,
|
||||
0.96156180f, 0.96065806f, 0.95974403f, 0.95881973f, 0.95788517f,
|
||||
0.95694034f, 0.95598526f, 0.95501995f, 0.95404440f, 0.95305864f,
|
||||
0.95206267f, 0.95105651f, 0.95004016f, 0.94901364f, 0.94797697f,
|
||||
0.94693013f, 0.94587315f, 0.94480604f, 0.94372882f, 0.94264149f,
|
||||
0.94154406f, 0.94043656f, 0.93931897f, 0.93819133f, 0.93705365f,
|
||||
0.93590592f, 0.93474818f, 0.93358042f, 0.93240268f, 0.93121493f,
|
||||
0.93001722f, 0.92880955f, 0.92759193f, 0.92636438f, 0.92512690f,
|
||||
0.92387953f, 0.92262225f, 0.92135509f, 0.92007809f, 0.91879121f,
|
||||
0.91749449f, 0.91618795f, 0.91487161f, 0.91354545f, 0.91220952f,
|
||||
0.91086382f, 0.90950836f, 0.90814316f, 0.90676824f, 0.90538363f,
|
||||
0.90398929f, 0.90258528f, 0.90117161f, 0.89974828f, 0.89831532f,
|
||||
0.89687273f, 0.89542055f, 0.89395877f, 0.89248742f, 0.89100652f,
|
||||
0.88951606f, 0.88801610f, 0.88650661f, 0.88498764f, 0.88345918f,
|
||||
0.88192125f, 0.88037390f, 0.87881711f, 0.87725090f, 0.87567531f,
|
||||
0.87409035f, 0.87249599f, 0.87089232f, 0.86927933f, 0.86765699f,
|
||||
0.86602540f, 0.86438453f, 0.86273437f, 0.86107503f, 0.85940641f,
|
||||
0.85772862f, 0.85604161f, 0.85434547f, 0.85264014f, 0.85092572f,
|
||||
0.84920218f, 0.84746955f, 0.84572781f, 0.84397704f, 0.84221721f,
|
||||
0.84044838f, 0.83867056f, 0.83688375f, 0.83508799f, 0.83328325f,
|
||||
0.83146961f, 0.82964704f, 0.82781562f, 0.82597530f, 0.82412620f,
|
||||
0.82226820f, 0.82040144f, 0.81852589f, 0.81664154f, 0.81474847f,
|
||||
0.81284665f, 0.81093620f, 0.80901698f, 0.80708914f, 0.80515262f,
|
||||
0.80320752f, 0.80125378f, 0.79929149f, 0.79732067f, 0.79534125f,
|
||||
0.79335335f, 0.79135691f, 0.78935204f, 0.78733867f, 0.78531691f,
|
||||
0.78328674f, 0.78124818f, 0.77920122f, 0.77714595f, 0.77508232f,
|
||||
0.77301043f, 0.77093026f, 0.76884183f, 0.76674517f, 0.76464026f,
|
||||
0.76252720f, 0.76040593f, 0.75827656f, 0.75613907f, 0.75399349f,
|
||||
0.75183978f, 0.74967807f, 0.74750833f, 0.74533054f, 0.74314481f,
|
||||
0.74095112f, 0.73874950f, 0.73653993f, 0.73432251f, 0.73209718f,
|
||||
0.72986405f, 0.72762307f, 0.72537438f, 0.72311787f, 0.72085359f,
|
||||
0.71858162f, 0.71630192f, 0.71401459f, 0.71171956f, 0.70941701f,
|
||||
0.70710677f, 0.70478900f, 0.70246363f, 0.70013079f, 0.69779041f,
|
||||
0.69544260f, 0.69308738f, 0.69072466f, 0.68835458f, 0.68597709f,
|
||||
0.68359229f, 0.68120013f, 0.67880072f, 0.67639404f, 0.67398011f,
|
||||
0.67155892f, 0.66913059f, 0.66669509f, 0.66425240f, 0.66180265f,
|
||||
0.65934581f, 0.65688191f, 0.65441092f, 0.65193298f, 0.64944801f,
|
||||
0.64695613f, 0.64445727f, 0.64195160f, 0.63943902f, 0.63691954f,
|
||||
0.63439328f, 0.63186019f, 0.62932037f, 0.62677377f, 0.62422055f,
|
||||
0.62166055f, 0.61909394f, 0.61652065f, 0.61394081f, 0.61135435f,
|
||||
0.60876139f, 0.60616195f, 0.60355593f, 0.60094349f, 0.59832457f,
|
||||
0.59569929f, 0.59306758f, 0.59042957f, 0.58778523f, 0.58513460f,
|
||||
0.58247766f, 0.57981452f, 0.57714518f, 0.57446961f, 0.57178793f,
|
||||
0.56910013f, 0.56640624f, 0.56370623f, 0.56100023f, 0.55828818f,
|
||||
0.55557020f, 0.55284627f, 0.55011641f, 0.54738067f, 0.54463901f,
|
||||
0.54189157f, 0.53913828f, 0.53637921f, 0.53361450f, 0.53084398f,
|
||||
0.52806787f, 0.52528601f, 0.52249852f, 0.51970543f, 0.51690688f,
|
||||
0.51410279f, 0.51129310f, 0.50847793f, 0.50565732f, 0.50283139f,
|
||||
0.49999997f, 0.49716321f, 0.49432122f, 0.49147383f, 0.48862118f,
|
||||
0.48576340f, 0.48290042f, 0.48003216f, 0.47715876f, 0.47428025f,
|
||||
0.47139677f, 0.46850813f, 0.46561448f, 0.46271584f, 0.45981235f,
|
||||
0.45690383f, 0.45399042f, 0.45107214f, 0.44814915f, 0.44522124f,
|
||||
0.44228868f, 0.43935137f, 0.43640926f, 0.43346247f, 0.43051104f,
|
||||
0.42755511f, 0.42459449f, 0.42162932f, 0.41865964f, 0.41568558f,
|
||||
0.41270697f, 0.40972393f, 0.40673661f, 0.40374494f, 0.40074884f,
|
||||
0.39774844f, 0.39474390f, 0.39173501f, 0.38872193f, 0.38570469f,
|
||||
0.38268343f, 0.37965796f, 0.37662842f, 0.37359496f, 0.37055739f,
|
||||
0.36751585f, 0.36447038f, 0.36142122f, 0.35836797f, 0.35531089f,
|
||||
0.35225000f, 0.34918544f, 0.34611704f, 0.34304493f, 0.33996926f,
|
||||
0.33688983f, 0.33380680f, 0.33072019f, 0.32763015f, 0.32453650f,
|
||||
0.32143936f, 0.31833890f, 0.31523503f, 0.31212767f, 0.30901696f,
|
||||
0.30590306f, 0.30278577f, 0.29966524f, 0.29654150f, 0.29341470f,
|
||||
0.29028464f, 0.28715147f, 0.28401522f, 0.28087605f, 0.27773376f,
|
||||
0.27458861f, 0.27144052f, 0.26828940f, 0.26513541f, 0.26197859f,
|
||||
0.25881907f, 0.25565666f, 0.25249152f, 0.24932367f, 0.24615327f,
|
||||
0.24298012f, 0.23980436f, 0.23662604f, 0.23344530f, 0.23026206f,
|
||||
0.22707623f, 0.22388809f, 0.22069744f, 0.21750443f, 0.21430908f,
|
||||
0.21111156f, 0.20791165f, 0.20470953f, 0.20150520f, 0.19829884f,
|
||||
0.19509024f, 0.19187955f, 0.18866692f, 0.18545227f, 0.18223552f,
|
||||
0.17901681f, 0.17579631f, 0.17257380f, 0.16934945f, 0.16612328f,
|
||||
0.16289546f, 0.15966577f, 0.15643437f, 0.15320141f, 0.14996669f,
|
||||
0.14673037f, 0.14349260f, 0.14025329f, 0.13701235f, 0.13376995f,
|
||||
0.13052612f, 0.12728101f, 0.12403442f, 0.12078650f, 0.11753740f,
|
||||
0.11428693f, 0.11103523f, 0.10778234f, 0.10452842f, 0.10127326f,
|
||||
0.098017137f, 0.094759842f, 0.091501652f, 0.088242363f, 0.084982129f,
|
||||
0.081721103f, 0.078459084f, 0.075196224f, 0.071932560f, 0.068668243f,
|
||||
0.065403073f, 0.062137201f, 0.058870665f, 0.055603617f, 0.052335974f,
|
||||
0.049067651f, 0.045798921f, 0.042529582f, 0.039259788f, 0.035989573f,
|
||||
0.032719092f, 0.029448142f, 0.026176876f, 0.022905329f, 0.019633657f,
|
||||
0.016361655f, 0.013089478f, 0.0098171604f, 0.0065449764f, 0.0032724839f,
|
||||
-4.3711390e-08f, };
|
||||
#endif
|
||||
|
||||
static const CELTMode mode48000_960_120 = {
|
||||
48000, /* Fs */
|
||||
120, /* overlap */
|
||||
21, /* nbEBands */
|
||||
21, /* effEBands */
|
||||
{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, }, /* preemph */
|
||||
eband5ms, /* eBands */
|
||||
3, /* maxLM */
|
||||
8, /* nbShortMdcts */
|
||||
120, /* shortMdctSize */
|
||||
11, /* nbAllocVectors */
|
||||
band_allocation, /* allocVectors */
|
||||
logN400, /* logN */
|
||||
window120, /* window */
|
||||
{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
|
||||
{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
|
||||
};
|
||||
|
||||
/* List of all the available modes */
|
||||
#define TOTAL_MODES 1
|
||||
static const CELTMode * const static_mode_list[TOTAL_MODES] = {
|
||||
&mode48000_960_120,
|
||||
};
|
|
@ -0,0 +1,415 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mathops.h"
|
||||
#include "cwrs.h"
|
||||
#include "vq.h"
|
||||
#include "arch.h"
|
||||
#include "os_support.h"
|
||||
#include "bands.h"
|
||||
#include "rate.h"
|
||||
|
||||
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
|
||||
{
|
||||
int i;
|
||||
celt_norm *Xptr;
|
||||
Xptr = X;
|
||||
for (i=0;i<len-stride;i++)
|
||||
{
|
||||
celt_norm x1, x2;
|
||||
x1 = Xptr[0];
|
||||
x2 = Xptr[stride];
|
||||
Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
|
||||
*Xptr++ = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15));
|
||||
}
|
||||
Xptr = &X[len-2*stride-1];
|
||||
for (i=len-2*stride-1;i>=0;i--)
|
||||
{
|
||||
celt_norm x1, x2;
|
||||
x1 = Xptr[0];
|
||||
x2 = Xptr[stride];
|
||||
Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
|
||||
*Xptr-- = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15));
|
||||
}
|
||||
}
|
||||
|
||||
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
|
||||
{
|
||||
static const int SPREAD_FACTOR[3]={15,10,5};
|
||||
int i;
|
||||
opus_val16 c, s;
|
||||
opus_val16 gain, theta;
|
||||
int stride2=0;
|
||||
int factor;
|
||||
|
||||
if (2*K>=len || spread==SPREAD_NONE)
|
||||
return;
|
||||
factor = SPREAD_FACTOR[spread-1];
|
||||
|
||||
gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
|
||||
theta = HALF16(MULT16_16_Q15(gain,gain));
|
||||
|
||||
c = celt_cos_norm(EXTEND32(theta));
|
||||
s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
|
||||
|
||||
if (len>=8*stride)
|
||||
{
|
||||
stride2 = 1;
|
||||
/* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
|
||||
It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
|
||||
while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
|
||||
stride2++;
|
||||
}
|
||||
/*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
|
||||
extract_collapse_mask().*/
|
||||
len /= stride;
|
||||
for (i=0;i<stride;i++)
|
||||
{
|
||||
if (dir < 0)
|
||||
{
|
||||
if (stride2)
|
||||
exp_rotation1(X+i*len, len, stride2, s, c);
|
||||
exp_rotation1(X+i*len, len, 1, c, s);
|
||||
} else {
|
||||
exp_rotation1(X+i*len, len, 1, c, -s);
|
||||
if (stride2)
|
||||
exp_rotation1(X+i*len, len, stride2, s, -c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Takes the pitch vector and the decoded residual vector, computes the gain
|
||||
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
|
||||
static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
|
||||
int N, opus_val32 Ryy, opus_val16 gain)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
int k;
|
||||
#endif
|
||||
opus_val32 t;
|
||||
opus_val16 g;
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
k = celt_ilog2(Ryy)>>1;
|
||||
#endif
|
||||
t = VSHR32(Ryy, 2*(k-7));
|
||||
g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
|
||||
|
||||
i=0;
|
||||
do
|
||||
X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1));
|
||||
while (++i < N);
|
||||
}
|
||||
|
||||
static unsigned extract_collapse_mask(int *iy, int N, int B)
|
||||
{
|
||||
unsigned collapse_mask;
|
||||
int N0;
|
||||
int i;
|
||||
if (B<=1)
|
||||
return 1;
|
||||
/*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
|
||||
exp_rotation().*/
|
||||
N0 = N/B;
|
||||
collapse_mask = 0;
|
||||
i=0; do {
|
||||
int j;
|
||||
j=0; do {
|
||||
collapse_mask |= (iy[i*N0+j]!=0)<<i;
|
||||
} while (++j<N0);
|
||||
} while (++i<B);
|
||||
return collapse_mask;
|
||||
}
|
||||
|
||||
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
|
||||
#ifdef RESYNTH
|
||||
, opus_val16 gain
|
||||
#endif
|
||||
)
|
||||
{
|
||||
VARDECL(celt_norm, y);
|
||||
VARDECL(int, iy);
|
||||
VARDECL(opus_val16, signx);
|
||||
int i, j;
|
||||
opus_val16 s;
|
||||
int pulsesLeft;
|
||||
opus_val32 sum;
|
||||
opus_val32 xy;
|
||||
opus_val16 yy;
|
||||
unsigned collapse_mask;
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert2(K>0, "alg_quant() needs at least one pulse");
|
||||
celt_assert2(N>1, "alg_quant() needs at least two dimensions");
|
||||
|
||||
ALLOC(y, N, celt_norm);
|
||||
ALLOC(iy, N, int);
|
||||
ALLOC(signx, N, opus_val16);
|
||||
|
||||
exp_rotation(X, N, 1, B, K, spread);
|
||||
|
||||
/* Get rid of the sign */
|
||||
sum = 0;
|
||||
j=0; do {
|
||||
if (X[j]>0)
|
||||
signx[j]=1;
|
||||
else {
|
||||
signx[j]=-1;
|
||||
X[j]=-X[j];
|
||||
}
|
||||
iy[j] = 0;
|
||||
y[j] = 0;
|
||||
} while (++j<N);
|
||||
|
||||
xy = yy = 0;
|
||||
|
||||
pulsesLeft = K;
|
||||
|
||||
/* Do a pre-search by projecting on the pyramid */
|
||||
if (K > (N>>1))
|
||||
{
|
||||
opus_val16 rcp;
|
||||
j=0; do {
|
||||
sum += X[j];
|
||||
} while (++j<N);
|
||||
|
||||
/* If X is too small, just replace it with a pulse at 0 */
|
||||
#ifdef FIXED_POINT
|
||||
if (sum <= K)
|
||||
#else
|
||||
/* Prevents infinities and NaNs from causing too many pulses
|
||||
to be allocated. 64 is an approximation of infinity here. */
|
||||
if (!(sum > EPSILON && sum < 64))
|
||||
#endif
|
||||
{
|
||||
X[0] = QCONST16(1.f,14);
|
||||
j=1; do
|
||||
X[j]=0;
|
||||
while (++j<N);
|
||||
sum = QCONST16(1.f,14);
|
||||
}
|
||||
rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
|
||||
j=0; do {
|
||||
#ifdef FIXED_POINT
|
||||
/* It's really important to round *towards zero* here */
|
||||
iy[j] = MULT16_16_Q15(X[j],rcp);
|
||||
#else
|
||||
iy[j] = (int)floor(rcp*X[j]);
|
||||
#endif
|
||||
y[j] = (celt_norm)iy[j];
|
||||
yy = MAC16_16(yy, y[j],y[j]);
|
||||
xy = MAC16_16(xy, X[j],y[j]);
|
||||
y[j] *= 2;
|
||||
pulsesLeft -= iy[j];
|
||||
} while (++j<N);
|
||||
}
|
||||
celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
|
||||
|
||||
/* This should never happen, but just in case it does (e.g. on silence)
|
||||
we fill the first bin with pulses. */
|
||||
#ifdef FIXED_POINT_DEBUG
|
||||
celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
|
||||
#endif
|
||||
if (pulsesLeft > N+3)
|
||||
{
|
||||
opus_val16 tmp = (opus_val16)pulsesLeft;
|
||||
yy = MAC16_16(yy, tmp, tmp);
|
||||
yy = MAC16_16(yy, tmp, y[0]);
|
||||
iy[0] += pulsesLeft;
|
||||
pulsesLeft=0;
|
||||
}
|
||||
|
||||
s = 1;
|
||||
for (i=0;i<pulsesLeft;i++)
|
||||
{
|
||||
int best_id;
|
||||
opus_val32 best_num = -VERY_LARGE16;
|
||||
opus_val16 best_den = 0;
|
||||
#ifdef FIXED_POINT
|
||||
int rshift;
|
||||
#endif
|
||||
#ifdef FIXED_POINT
|
||||
rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
|
||||
#endif
|
||||
best_id = 0;
|
||||
/* The squared magnitude term gets added anyway, so we might as well
|
||||
add it outside the loop */
|
||||
yy = ADD32(yy, 1);
|
||||
j=0;
|
||||
do {
|
||||
opus_val16 Rxy, Ryy;
|
||||
/* Temporary sums of the new pulse(s) */
|
||||
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
|
||||
/* We're multiplying y[j] by two so we don't have to do it here */
|
||||
Ryy = ADD16(yy, y[j]);
|
||||
|
||||
/* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
|
||||
Rxy is positive because the sign is pre-computed) */
|
||||
Rxy = MULT16_16_Q15(Rxy,Rxy);
|
||||
/* The idea is to check for num/den >= best_num/best_den, but that way
|
||||
we can do it without any division */
|
||||
/* OPT: Make sure to use conditional moves here */
|
||||
if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
|
||||
{
|
||||
best_den = Ryy;
|
||||
best_num = Rxy;
|
||||
best_id = j;
|
||||
}
|
||||
} while (++j<N);
|
||||
|
||||
/* Updating the sums of the new pulse(s) */
|
||||
xy = ADD32(xy, EXTEND32(X[best_id]));
|
||||
/* We're multiplying y[j] by two so we don't have to do it here */
|
||||
yy = ADD16(yy, y[best_id]);
|
||||
|
||||
/* Only now that we've made the final choice, update y/iy */
|
||||
/* Multiplying y[j] by 2 so we don't have to do it everywhere else */
|
||||
y[best_id] += 2*s;
|
||||
iy[best_id]++;
|
||||
}
|
||||
|
||||
/* Put the original sign back */
|
||||
j=0;
|
||||
do {
|
||||
X[j] = MULT16_16(signx[j],X[j]);
|
||||
if (signx[j] < 0)
|
||||
iy[j] = -iy[j];
|
||||
} while (++j<N);
|
||||
encode_pulses(iy, N, K, enc);
|
||||
|
||||
#ifdef RESYNTH
|
||||
normalise_residual(iy, X, N, yy, gain);
|
||||
exp_rotation(X, N, -1, B, K, spread);
|
||||
#endif
|
||||
|
||||
collapse_mask = extract_collapse_mask(iy, N, B);
|
||||
RESTORE_STACK;
|
||||
return collapse_mask;
|
||||
}
|
||||
|
||||
/** Decode pulse vector and combine the result with the pitch vector to produce
|
||||
the final normalised signal in the current band. */
|
||||
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
|
||||
ec_dec *dec, opus_val16 gain)
|
||||
{
|
||||
int i;
|
||||
opus_val32 Ryy;
|
||||
unsigned collapse_mask;
|
||||
VARDECL(int, iy);
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert2(K>0, "alg_unquant() needs at least one pulse");
|
||||
celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
|
||||
ALLOC(iy, N, int);
|
||||
decode_pulses(iy, N, K, dec);
|
||||
Ryy = 0;
|
||||
i=0;
|
||||
do {
|
||||
Ryy = MAC16_16(Ryy, iy[i], iy[i]);
|
||||
} while (++i < N);
|
||||
normalise_residual(iy, X, N, Ryy, gain);
|
||||
exp_rotation(X, N, -1, B, K, spread);
|
||||
collapse_mask = extract_collapse_mask(iy, N, B);
|
||||
RESTORE_STACK;
|
||||
return collapse_mask;
|
||||
}
|
||||
|
||||
void renormalise_vector(celt_norm *X, int N, opus_val16 gain)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
int k;
|
||||
#endif
|
||||
opus_val32 E = EPSILON;
|
||||
opus_val16 g;
|
||||
opus_val32 t;
|
||||
celt_norm *xptr = X;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
E = MAC16_16(E, *xptr, *xptr);
|
||||
xptr++;
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
k = celt_ilog2(E)>>1;
|
||||
#endif
|
||||
t = VSHR32(E, 2*(k-7));
|
||||
g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
|
||||
|
||||
xptr = X;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
*xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
|
||||
xptr++;
|
||||
}
|
||||
/*return celt_sqrt(E);*/
|
||||
}
|
||||
|
||||
int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N)
|
||||
{
|
||||
int i;
|
||||
int itheta;
|
||||
opus_val16 mid, side;
|
||||
opus_val32 Emid, Eside;
|
||||
|
||||
Emid = Eside = EPSILON;
|
||||
if (stereo)
|
||||
{
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
celt_norm m, s;
|
||||
m = ADD16(SHR16(X[i],1),SHR16(Y[i],1));
|
||||
s = SUB16(SHR16(X[i],1),SHR16(Y[i],1));
|
||||
Emid = MAC16_16(Emid, m, m);
|
||||
Eside = MAC16_16(Eside, s, s);
|
||||
}
|
||||
} else {
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
celt_norm m, s;
|
||||
m = X[i];
|
||||
s = Y[i];
|
||||
Emid = MAC16_16(Emid, m, m);
|
||||
Eside = MAC16_16(Eside, s, s);
|
||||
}
|
||||
}
|
||||
mid = celt_sqrt(Emid);
|
||||
side = celt_sqrt(Eside);
|
||||
#ifdef FIXED_POINT
|
||||
/* 0.63662 = 2/pi */
|
||||
itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
|
||||
#else
|
||||
itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
|
||||
#endif
|
||||
|
||||
return itheta;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file vq.h
|
||||
@brief Vector quantisation of the residual
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VQ_H
|
||||
#define VQ_H
|
||||
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "modes.h"
|
||||
|
||||
/** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
|
||||
* the pitch and a combination of pulses such that its norm is still equal
|
||||
* to 1. This is the function that will typically require the most CPU.
|
||||
* @param x Residual signal to quantise/encode (returns quantised version)
|
||||
* @param W Perceptual weight to use when optimising (currently unused)
|
||||
* @param N Number of samples to encode
|
||||
* @param K Number of pulses to use
|
||||
* @param p Pitch vector (it is assumed that p+x is a unit vector)
|
||||
* @param enc Entropy encoder state
|
||||
* @ret A mask indicating which blocks in the band received pulses
|
||||
*/
|
||||
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
|
||||
ec_enc *enc
|
||||
#ifdef RESYNTH
|
||||
, opus_val16 gain
|
||||
#endif
|
||||
);
|
||||
|
||||
/** Algebraic pulse decoder
|
||||
* @param x Decoded normalised spectrum (returned)
|
||||
* @param N Number of samples to decode
|
||||
* @param K Number of pulses to use
|
||||
* @param p Pitch vector (automatically added to x)
|
||||
* @param dec Entropy decoder state
|
||||
* @ret A mask indicating which blocks in the band received pulses
|
||||
*/
|
||||
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
|
||||
ec_dec *dec, opus_val16 gain);
|
||||
|
||||
void renormalise_vector(celt_norm *X, int N, opus_val16 gain);
|
||||
|
||||
int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N);
|
||||
|
||||
#endif /* VQ_H */
|
|
@ -0,0 +1,903 @@
|
|||
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus.h
|
||||
* @brief Opus reference implementation API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_H
|
||||
#define OPUS_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @mainpage Opus
|
||||
*
|
||||
* The Opus codec is designed for interactive speech and audio transmission over the Internet.
|
||||
* It is designed by the IETF Codec Working Group and incorporates technology from
|
||||
* Skype's SILK codec and Xiph.Org's CELT codec.
|
||||
*
|
||||
* The Opus codec is designed to handle a wide range of interactive audio applications,
|
||||
* including Voice over IP, videoconferencing, in-game chat, and even remote live music
|
||||
* performances. It can scale from low bit-rate narrowband speech to very high quality
|
||||
* stereo music. Its main features are:
|
||||
|
||||
* @li Sampling rates from 8 to 48 kHz
|
||||
* @li Bit-rates from 6 kb/s to 510 kb/s
|
||||
* @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
|
||||
* @li Audio bandwidth from narrowband to full-band
|
||||
* @li Support for speech and music
|
||||
* @li Support for mono and stereo
|
||||
* @li Support for multichannel (up to 255 channels)
|
||||
* @li Frame sizes from 2.5 ms to 60 ms
|
||||
* @li Good loss robustness and packet loss concealment (PLC)
|
||||
* @li Floating point and fixed-point implementation
|
||||
*
|
||||
* Documentation sections:
|
||||
* @li @ref opus_encoder
|
||||
* @li @ref opus_decoder
|
||||
* @li @ref opus_repacketizer
|
||||
* @li @ref opus_multistream
|
||||
* @li @ref opus_libinfo
|
||||
* @li @ref opus_custom
|
||||
*/
|
||||
|
||||
/** @defgroup opus_encoder Opus Encoder
|
||||
* @{
|
||||
*
|
||||
* @brief This page describes the process and functions used to encode Opus.
|
||||
*
|
||||
* Since Opus is a stateful codec, the encoding process starts with creating an encoder
|
||||
* state. This can be done with:
|
||||
*
|
||||
* @code
|
||||
* int error;
|
||||
* OpusEncoder *enc;
|
||||
* enc = opus_encoder_create(Fs, channels, application, &error);
|
||||
* @endcode
|
||||
*
|
||||
* From this point, @c enc can be used for encoding an audio stream. An encoder state
|
||||
* @b must @b not be used for more than one stream at the same time. Similarly, the encoder
|
||||
* state @b must @b not be re-initialized for each frame.
|
||||
*
|
||||
* While opus_encoder_create() allocates memory for the state, it's also possible
|
||||
* to initialize pre-allocated memory:
|
||||
*
|
||||
* @code
|
||||
* int size;
|
||||
* int error;
|
||||
* OpusEncoder *enc;
|
||||
* size = opus_encoder_get_size(channels);
|
||||
* enc = malloc(size);
|
||||
* error = opus_encoder_init(enc, Fs, channels, application);
|
||||
* @endcode
|
||||
*
|
||||
* where opus_encoder_get_size() returns the required size for the encoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
*
|
||||
* The encoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
*
|
||||
* It is possible to change some of the encoder's settings using the opus_encoder_ctl()
|
||||
* interface. All these settings already default to the recommended value, so they should
|
||||
* only be changed when necessary. The most common settings one may want to change are:
|
||||
*
|
||||
* @code
|
||||
* opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
|
||||
* opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
|
||||
* opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
|
||||
* @endcode
|
||||
*
|
||||
* where
|
||||
*
|
||||
* @arg bitrate is in bits per second (b/s)
|
||||
* @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
|
||||
* @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
|
||||
*
|
||||
* See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
|
||||
*
|
||||
* To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
|
||||
* @code
|
||||
* len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
|
||||
* @endcode
|
||||
*
|
||||
* where
|
||||
* <ul>
|
||||
* <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
|
||||
* <li>frame_size is the duration of the frame in samples (per channel)</li>
|
||||
* <li>packet is the byte array to which the compressed data is written</li>
|
||||
* <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
|
||||
* Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li>
|
||||
* </ul>
|
||||
*
|
||||
* opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
|
||||
* The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
|
||||
* is 1 byte, then the packet does not need to be transmitted (DTX).
|
||||
*
|
||||
* Once the encoder state if no longer needed, it can be destroyed with
|
||||
*
|
||||
* @code
|
||||
* opus_encoder_destroy(enc);
|
||||
* @endcode
|
||||
*
|
||||
* If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
|
||||
* then no action is required aside from potentially freeing the memory that was manually
|
||||
* allocated for it (calling free(enc) for the example above)
|
||||
*
|
||||
*/
|
||||
|
||||
/** Opus encoder state.
|
||||
* This contains the complete state of an Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_encoder_create,opus_encoder_init
|
||||
*/
|
||||
typedef struct OpusEncoder OpusEncoder;
|
||||
|
||||
/** Gets the size of an <code>OpusEncoder</code> structure.
|
||||
* @param[in] channels <tt>int</tt>: Number of channels.
|
||||
* This must be 1 or 2.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
/** Allocates and initializes an encoder state.
|
||||
* There are three coding modes:
|
||||
*
|
||||
* @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
|
||||
* signals. It enhances the input signal by high-pass filtering and
|
||||
* emphasizing formants and harmonics. Optionally it includes in-band
|
||||
* forward error correction to protect against packet loss. Use this
|
||||
* mode for typical VoIP applications. Because of the enhancement,
|
||||
* even at high bitrates the output may sound different from the input.
|
||||
*
|
||||
* @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
|
||||
* non-voice signals like music. Use this mode for music and mixed
|
||||
* (music/voice) content, broadcast, and applications requiring less
|
||||
* than 15 ms of coding delay.
|
||||
*
|
||||
* @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
|
||||
* disables the speech-optimized mode in exchange for slightly reduced delay.
|
||||
* This mode can only be set on an newly initialized or freshly reset encoder
|
||||
* because it changes the codec delay.
|
||||
*
|
||||
* This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
|
||||
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
|
||||
* can switch to a lower audio bandwidth or number of channels if the bitrate
|
||||
* selected is too low. This also means that it is safe to always use 48 kHz stereo input
|
||||
* and let the encoder optimize the encoding.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int application,
|
||||
int *error
|
||||
);
|
||||
|
||||
/** Initializes a previously allocated encoder state
|
||||
* The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_encoder_create(),opus_encoder_get_size()
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_init(
|
||||
OpusEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Encodes an Opus frame.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
|
||||
* input signal.
|
||||
* This must be an Opus frame size for
|
||||
* the encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted
|
||||
* values are 120, 240, 480, 960, 1920,
|
||||
* and 2880.
|
||||
* Passing in a duration of less than
|
||||
* 10 ms (480 samples at 48 kHz) will
|
||||
* prevent the encoder from using the LPC
|
||||
* or hybrid modes.
|
||||
* @param [out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
|
||||
OpusEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes an Opus frame from floating point input.
|
||||
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
|
||||
* Samples with a range beyond +/-1.0 are supported but will
|
||||
* be clipped by decoders using the integer API and should
|
||||
* only be used if it is known that the far end supports
|
||||
* extended dynamic range.
|
||||
* length is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
|
||||
* input signal.
|
||||
* This must be an Opus frame size for
|
||||
* the encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted
|
||||
* values are 120, 240, 480, 960, 1920,
|
||||
* and 2880.
|
||||
* Passing in a duration of less than
|
||||
* 10 ms (480 samples at 48 kHz) will
|
||||
* prevent the encoder from using the LPC
|
||||
* or hybrid modes.
|
||||
* @param [out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
|
||||
OpusEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create().
|
||||
* @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
|
||||
|
||||
/** Perform a CTL function on an Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @param st <tt>OpusEncoder*</tt>: Encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls or
|
||||
* @ref opus_encoderctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoder Opus Decoder
|
||||
* @{
|
||||
*
|
||||
* @brief This page describes the process and functions used to decode Opus.
|
||||
*
|
||||
* The decoding process also starts with creating a decoder
|
||||
* state. This can be done with:
|
||||
* @code
|
||||
* int error;
|
||||
* OpusDecoder *dec;
|
||||
* dec = opus_decoder_create(Fs, channels, &error);
|
||||
* @endcode
|
||||
* where
|
||||
* @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
|
||||
* @li channels is the number of channels (1 or 2)
|
||||
* @li error will hold the error code in case of failure (or #OPUS_OK on success)
|
||||
* @li the return value is a newly created decoder state to be used for decoding
|
||||
*
|
||||
* While opus_decoder_create() allocates memory for the state, it's also possible
|
||||
* to initialize pre-allocated memory:
|
||||
* @code
|
||||
* int size;
|
||||
* int error;
|
||||
* OpusDecoder *dec;
|
||||
* size = opus_decoder_get_size(channels);
|
||||
* dec = malloc(size);
|
||||
* error = opus_decoder_init(dec, Fs, channels);
|
||||
* @endcode
|
||||
* where opus_decoder_get_size() returns the required size for the decoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
*
|
||||
* The decoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
*
|
||||
* To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
|
||||
* @code
|
||||
* frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
|
||||
* @endcode
|
||||
* where
|
||||
*
|
||||
* @li packet is the byte array containing the compressed data
|
||||
* @li len is the exact number of bytes contained in the packet
|
||||
* @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
|
||||
* @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
|
||||
*
|
||||
* opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
|
||||
* If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
|
||||
* buffer is too small to hold the decoded audio.
|
||||
*
|
||||
* Opus is a stateful codec with overlapping blocks and as a result Opus
|
||||
* packets are not coded independently of each other. Packets must be
|
||||
* passed into the decoder serially and in the correct order for a correct
|
||||
* decode. Lost packets can be replaced with loss concealment by calling
|
||||
* the decoder with a null pointer and zero length for the missing packet.
|
||||
*
|
||||
* A single codec state may only be accessed from a single thread at
|
||||
* a time and any required locking must be performed by the caller. Separate
|
||||
* streams must be decoded with separate decoder states and can be decoded
|
||||
* in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
|
||||
* defined.
|
||||
*
|
||||
*/
|
||||
|
||||
/** Opus decoder state.
|
||||
* This contains the complete state of an Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_decoder_create,opus_decoder_init
|
||||
*/
|
||||
typedef struct OpusDecoder OpusDecoder;
|
||||
|
||||
/** Gets the size of an <code>OpusDecoder</code> structure.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels.
|
||||
* This must be 1 or 2.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
|
||||
|
||||
/** Allocates and initializes a decoder state.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
|
||||
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
|
||||
*
|
||||
* Internally Opus stores data at 48000 Hz, so that should be the default
|
||||
* value for Fs. However, the decoder can efficiently decode to buffers
|
||||
* at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
|
||||
* data at the full sample rate, or knows the compressed data doesn't
|
||||
* use the full frequency range, it can request decoding at a reduced
|
||||
* rate. Likewise, the decoder is capable of filling in either mono or
|
||||
* interleaved stereo pcm buffers, at the caller's request.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int *error
|
||||
);
|
||||
|
||||
/** Initializes a previously allocated decoder state.
|
||||
* The state must be at least the size returned by opus_decoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_init(
|
||||
OpusDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Decode an Opus packet.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
|
||||
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
|
||||
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
|
||||
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
|
||||
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
|
||||
* decoded. If no such data is available, the frame is decoded as if it were lost.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
|
||||
OpusDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode an Opus packet with floating point output.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
|
||||
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
|
||||
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
|
||||
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
|
||||
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
|
||||
* decoded. If no such data is available the frame is decoded as if it were lost.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
|
||||
OpusDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @param st <tt>OpusDecoder*</tt>: Decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls or
|
||||
* @ref opus_decoderctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create().
|
||||
* @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
|
||||
|
||||
/** Parse an opus packet into one or more frames.
|
||||
* Opus_decode will perform this operation internally so most applications do
|
||||
* not need to use this function.
|
||||
* This function does not copy the frames, the returned pointers are pointers into
|
||||
* the input packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet to be parsed
|
||||
* @param [in] len <tt>opus_int32</tt>: size of data
|
||||
* @param [out] out_toc <tt>char*</tt>: TOC pointer
|
||||
* @param [out] frames <tt>char*[48]</tt> encapsulated frames
|
||||
* @param [out] size <tt>short[48]</tt> sizes of the encapsulated frames
|
||||
* @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
|
||||
* @returns number of frames
|
||||
*/
|
||||
OPUS_EXPORT int opus_packet_parse(
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
unsigned char *out_toc,
|
||||
const unsigned char *frames[48],
|
||||
short size[48],
|
||||
int *payload_offset
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Gets the bandwidth of an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet
|
||||
* @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
|
||||
* @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples per frame from an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet.
|
||||
* This must contain at least one byte of
|
||||
* data.
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
|
||||
* This must be a multiple of 400, or
|
||||
* inaccurate results will be returned.
|
||||
* @returns Number of samples per frame.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of channels from an Opus packet.
|
||||
* @param [in] data <tt>char*</tt>: Opus packet
|
||||
* @returns Number of channels
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of frames in an Opus packet.
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @returns Number of frames
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples of an Opus packet.
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
|
||||
* This must be a multiple of 400, or
|
||||
* inaccurate results will be returned.
|
||||
* @returns Number of samples
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Gets the number of samples of an Opus packet.
|
||||
* @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @returns Number of samples
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_repacketizer Repacketizer
|
||||
* @{
|
||||
*
|
||||
* The repacketizer can be used to merge multiple Opus packets into a single
|
||||
* packet or alternatively to split Opus packets that have previously been
|
||||
* merged. Splitting valid Opus packets is always guaranteed to succeed,
|
||||
* whereas merging valid packets only succeeds if all frames have the same
|
||||
* mode, bandwidth, and frame size, and when the total duration of the merged
|
||||
* packet is no more than 120 ms.
|
||||
* The repacketizer currently only operates on elementary Opus
|
||||
* streams. It will not manipualte multistream packets successfully, except in
|
||||
* the degenerate case where they consist of data from a single stream.
|
||||
*
|
||||
* The repacketizing process starts with creating a repacketizer state, either
|
||||
* by calling opus_repacketizer_create() or by allocating the memory yourself,
|
||||
* e.g.,
|
||||
* @code
|
||||
* OpusRepacketizer *rp;
|
||||
* rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
|
||||
* if (rp != NULL)
|
||||
* opus_repacketizer_init(rp);
|
||||
* @endcode
|
||||
*
|
||||
* Then the application should submit packets with opus_repacketizer_cat(),
|
||||
* extract new packets with opus_repacketizer_out() or
|
||||
* opus_repacketizer_out_range(), and then reset the state for the next set of
|
||||
* input packets via opus_repacketizer_init().
|
||||
*
|
||||
* For example, to split a sequence of packets into individual frames:
|
||||
* @code
|
||||
* unsigned char *data;
|
||||
* int len;
|
||||
* while (get_next_packet(&data, &len))
|
||||
* {
|
||||
* unsigned char out[1276];
|
||||
* opus_int32 out_len;
|
||||
* int nb_frames;
|
||||
* int err;
|
||||
* int i;
|
||||
* err = opus_repacketizer_cat(rp, data, len);
|
||||
* if (err != OPUS_OK)
|
||||
* {
|
||||
* release_packet(data);
|
||||
* return err;
|
||||
* }
|
||||
* nb_frames = opus_repacketizer_get_nb_frames(rp);
|
||||
* for (i = 0; i < nb_frames; i++)
|
||||
* {
|
||||
* out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
|
||||
* if (out_len < 0)
|
||||
* {
|
||||
* release_packet(data);
|
||||
* return (int)out_len;
|
||||
* }
|
||||
* output_next_packet(out, out_len);
|
||||
* }
|
||||
* opus_repacketizer_init(rp);
|
||||
* release_packet(data);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Alternatively, to combine a sequence of frames into packets that each
|
||||
* contain up to <code>TARGET_DURATION_MS</code> milliseconds of data:
|
||||
* @code
|
||||
* // The maximum number of packets with duration TARGET_DURATION_MS occurs
|
||||
* // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
|
||||
* // packets.
|
||||
* unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
|
||||
* opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
|
||||
* int nb_packets;
|
||||
* unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
|
||||
* opus_int32 out_len;
|
||||
* int prev_toc;
|
||||
* nb_packets = 0;
|
||||
* while (get_next_packet(data+nb_packets, len+nb_packets))
|
||||
* {
|
||||
* int nb_frames;
|
||||
* int err;
|
||||
* nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
|
||||
* if (nb_frames < 1)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return nb_frames;
|
||||
* }
|
||||
* nb_frames += opus_repacketizer_get_nb_frames(rp);
|
||||
* // If adding the next packet would exceed our target, or it has an
|
||||
* // incompatible TOC sequence, output the packets we already have before
|
||||
* // submitting it.
|
||||
* // N.B., The nb_packets > 0 check ensures we've submitted at least one
|
||||
* // packet since the last call to opus_repacketizer_init(). Otherwise a
|
||||
* // single packet longer than TARGET_DURATION_MS would cause us to try to
|
||||
* // output an (invalid) empty packet. It also ensures that prev_toc has
|
||||
* // been set to a valid value. Additionally, len[nb_packets] > 0 is
|
||||
* // guaranteed by the call to opus_packet_get_nb_frames() above, so the
|
||||
* // reference to data[nb_packets][0] should be valid.
|
||||
* if (nb_packets > 0 && (
|
||||
* ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
|
||||
* opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
|
||||
* TARGET_DURATION_MS*48))
|
||||
* {
|
||||
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
|
||||
* if (out_len < 0)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return (int)out_len;
|
||||
* }
|
||||
* output_next_packet(out, out_len);
|
||||
* opus_repacketizer_init(rp);
|
||||
* release_packets(data, nb_packets);
|
||||
* data[0] = data[nb_packets];
|
||||
* len[0] = len[nb_packets];
|
||||
* nb_packets = 0;
|
||||
* }
|
||||
* err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
|
||||
* if (err != OPUS_OK)
|
||||
* {
|
||||
* release_packets(data, nb_packets+1);
|
||||
* return err;
|
||||
* }
|
||||
* prev_toc = data[nb_packets][0];
|
||||
* nb_packets++;
|
||||
* }
|
||||
* // Output the final, partial packet.
|
||||
* if (nb_packets > 0)
|
||||
* {
|
||||
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
|
||||
* release_packets(data, nb_packets);
|
||||
* if (out_len < 0)
|
||||
* return (int)out_len;
|
||||
* output_next_packet(out, out_len);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* An alternate way of merging packets is to simply call opus_repacketizer_cat()
|
||||
* unconditionally until it fails. At that point, the merged packet can be
|
||||
* obtained with opus_repacketizer_out() and the input packet for which
|
||||
* opus_repacketizer_cat() needs to be re-added to a newly reinitialized
|
||||
* repacketizer state.
|
||||
*/
|
||||
|
||||
typedef struct OpusRepacketizer OpusRepacketizer;
|
||||
|
||||
/** Gets the size of an <code>OpusRepacketizer</code> structure.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
|
||||
|
||||
/** (Re)initializes a previously allocated repacketizer state.
|
||||
* The state must be at least the size returned by opus_repacketizer_get_size().
|
||||
* This can be used for applications which use their own allocator instead of
|
||||
* malloc().
|
||||
* It must also be called to reset the queue of packets waiting to be
|
||||
* repacketized, which is necessary if the maximum packet duration of 120 ms
|
||||
* is reached or if you wish to submit packets with a different Opus
|
||||
* configuration (coding mode, audio bandwidth, frame size, or channel count).
|
||||
* Failure to do so will prevent a new packet from being added with
|
||||
* opus_repacketizer_cat().
|
||||
* @see opus_repacketizer_create
|
||||
* @see opus_repacketizer_get_size
|
||||
* @see opus_repacketizer_cat
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to
|
||||
* (re)initialize.
|
||||
* @returns A pointer to the same repacketizer state that was passed in.
|
||||
*/
|
||||
OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Allocates memory and initializes the new repacketizer with
|
||||
* opus_repacketizer_init().
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
|
||||
|
||||
/** Frees an <code>OpusRepacketizer</code> allocated by
|
||||
* opus_repacketizer_create().
|
||||
* @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
|
||||
|
||||
/** Add a packet to the current repacketizer state.
|
||||
* This packet must match the configuration of any packets already submitted
|
||||
* for repacketization since the last call to opus_repacketizer_init().
|
||||
* This means that it must have the same coding mode, audio bandwidth, frame
|
||||
* size, and channel count.
|
||||
* This can be checked in advance by examining the top 6 bits of the first
|
||||
* byte of the packet, and ensuring they match the top 6 bits of the first
|
||||
* byte of any previously submitted packet.
|
||||
* The total duration of audio in the repacketizer state also must not exceed
|
||||
* 120 ms, the maximum duration of a single packet, after adding this packet.
|
||||
*
|
||||
* The contents of the current repacketizer state can be extracted into new
|
||||
* packets using opus_repacketizer_out() or opus_repacketizer_out_range().
|
||||
*
|
||||
* In order to add a packet with a different configuration or to add more
|
||||
* audio beyond 120 ms, you must clear the repacketizer state by calling
|
||||
* opus_repacketizer_init().
|
||||
* If a packet is too large to add to the current repacketizer state, no part
|
||||
* of it is added, even if it contains multiple frames, some of which might
|
||||
* fit.
|
||||
* If you wish to be able to add parts of such packets, you should first use
|
||||
* another repacketizer to split the packet into pieces and add them
|
||||
* individually.
|
||||
* @see opus_repacketizer_out_range
|
||||
* @see opus_repacketizer_out
|
||||
* @see opus_repacketizer_init
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to
|
||||
* add the packet.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: The packet data.
|
||||
* The application must ensure
|
||||
* this pointer remains valid
|
||||
* until the next call to
|
||||
* opus_repacketizer_init() or
|
||||
* opus_repacketizer_destroy().
|
||||
* @param len <tt>opus_int32</tt>: The number of bytes in the packet data.
|
||||
* @returns An error code indicating whether or not the operation succeeded.
|
||||
* @retval #OPUS_OK The packet's contents have been added to the repacketizer
|
||||
* state.
|
||||
* @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
|
||||
* the packet's TOC sequence was not compatible
|
||||
* with previously submitted packets (because
|
||||
* the coding mode, audio bandwidth, frame size,
|
||||
* or channel count did not match), or adding
|
||||
* this packet would increase the total amount of
|
||||
* audio stored in the repacketizer state to more
|
||||
* than 120 ms.
|
||||
*/
|
||||
OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
|
||||
/** Construct a new packet from data previously submitted to the repacketizer
|
||||
* state via opus_repacketizer_cat().
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
|
||||
* construct the new packet.
|
||||
* @param begin <tt>int</tt>: The index of the first frame in the current
|
||||
* repacketizer state to include in the output.
|
||||
* @param end <tt>int</tt>: One past the index of the last frame in the
|
||||
* current repacketizer state to include in the
|
||||
* output.
|
||||
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
|
||||
* store the output packet.
|
||||
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
|
||||
* the output buffer. In order to guarantee
|
||||
* success, this should be at least
|
||||
* <code>1276</code> for a single frame,
|
||||
* or for multiple frames,
|
||||
* <code>1277*(end-begin)</code>.
|
||||
* However, <code>1*(end-begin)</code> plus
|
||||
* the size of all packet data submitted to
|
||||
* the repacketizer since the last call to
|
||||
* opus_repacketizer_init() or
|
||||
* opus_repacketizer_create() is also
|
||||
* sufficient, and possibly much smaller.
|
||||
* @returns The total size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of
|
||||
* frames (begin < 0, begin >= end, or end >
|
||||
* opus_repacketizer_get_nb_frames()).
|
||||
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
|
||||
* complete output packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Return the total number of frames contained in packet data submitted to
|
||||
* the repacketizer state so far via opus_repacketizer_cat() since the last
|
||||
* call to opus_repacketizer_init() or opus_repacketizer_create().
|
||||
* This defines the valid range of packets that can be extracted with
|
||||
* opus_repacketizer_out_range() or opus_repacketizer_out().
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the
|
||||
* frames.
|
||||
* @returns The total number of frames contained in the packet data submitted
|
||||
* to the repacketizer state.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Construct a new packet from data previously submitted to the repacketizer
|
||||
* state via opus_repacketizer_cat().
|
||||
* This is a convenience routine that returns all the data submitted so far
|
||||
* in a single packet.
|
||||
* It is equivalent to calling
|
||||
* @code
|
||||
* opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
|
||||
* data, maxlen)
|
||||
* @endcode
|
||||
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
|
||||
* construct the new packet.
|
||||
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
|
||||
* store the output packet.
|
||||
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
|
||||
* the output buffer. In order to guarantee
|
||||
* success, this should be at least
|
||||
* <code>1277*opus_repacketizer_get_nb_frames(rp)</code>.
|
||||
* However,
|
||||
* <code>1*opus_repacketizer_get_nb_frames(rp)</code>
|
||||
* plus the size of all packet data
|
||||
* submitted to the repacketizer since the
|
||||
* last call to opus_repacketizer_init() or
|
||||
* opus_repacketizer_create() is also
|
||||
* sufficient, and possibly much smaller.
|
||||
* @returns The total size of the output packet on success, or an error code
|
||||
* on failure.
|
||||
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
|
||||
* complete output packet.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_H */
|
|
@ -0,0 +1,329 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008-2012 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file opus_custom.h
|
||||
@brief Opus-Custom reference implementation API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_CUSTOM_H
|
||||
#define OPUS_CUSTOM_H
|
||||
|
||||
#include "opus_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
#define OPUS_CUSTOM_EXPORT OPUS_EXPORT
|
||||
#define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
|
||||
#else
|
||||
#define OPUS_CUSTOM_EXPORT
|
||||
#ifdef CELT_C
|
||||
#define OPUS_CUSTOM_EXPORT_STATIC static inline
|
||||
#else
|
||||
#define OPUS_CUSTOM_EXPORT_STATIC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_custom Opus Custom
|
||||
* @{
|
||||
* Opus Custom is an optional part of the Opus specification and
|
||||
* reference implementation which uses a distinct API from the regular
|
||||
* API and supports frame sizes that are not normally supported.\ Use
|
||||
* of Opus Custom is discouraged for all but very special applications
|
||||
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
|
||||
* (for either complexity or latency reasons) and where interoperability
|
||||
* is less important.
|
||||
*
|
||||
* In addition to the interoperability limitations the use of Opus custom
|
||||
* disables a substantial chunk of the codec and generally lowers the
|
||||
* quality available at a given bitrate. Normally when an application needs
|
||||
* a different frame size from the codec it should buffer to match the
|
||||
* sizes but this adds a small amount of delay which may be important
|
||||
* in some very low latency applications. Some transports (especially
|
||||
* constant rate RF transports) may also work best with frames of
|
||||
* particular durations.
|
||||
*
|
||||
* Libopus only supports custom modes if they are enabled at compile time.
|
||||
*
|
||||
* The Opus Custom API is similar to the regular API but the
|
||||
* @ref opus_encoder_create and @ref opus_decoder_create calls take
|
||||
* an additional mode parameter which is a structure produced by
|
||||
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
|
||||
* must create a mode using the same sample rate (fs) and frame size
|
||||
* (frame size) so these parameters must either be signaled out of band
|
||||
* or fixed in a particular implementation.
|
||||
*
|
||||
* Similar to regular Opus the custom modes support on the fly frame size
|
||||
* switching, but the sizes available depend on the particular frame size in
|
||||
* use. For some initial frame sizes on a single on the fly size is available.
|
||||
*/
|
||||
|
||||
/** Contains the state of an encoder. One encoder state is needed
|
||||
for each stream. It is initialized once at the beginning of the
|
||||
stream. Do *not* re-initialize the state for every frame.
|
||||
@brief Encoder state
|
||||
*/
|
||||
typedef struct OpusCustomEncoder OpusCustomEncoder;
|
||||
|
||||
/** State of the decoder. One decoder state is needed for each stream.
|
||||
It is initialized once at the beginning of the stream. Do *not*
|
||||
re-initialize the state for every frame.
|
||||
@brief Decoder state
|
||||
*/
|
||||
typedef struct OpusCustomDecoder OpusCustomDecoder;
|
||||
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialized
|
||||
with exactly the same mode, otherwise the output will be
|
||||
corrupted.
|
||||
@brief Mode configuration
|
||||
*/
|
||||
typedef struct OpusCustomMode OpusCustomMode;
|
||||
|
||||
/** Creates a new mode struct. This will be passed to an encoder or
|
||||
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
|
||||
* decoders that use it are destroyed as well.
|
||||
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
|
||||
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
|
||||
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
|
||||
* @return A newly created mode
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
|
||||
|
||||
/** Destroys a mode struct. Only call this after all encoders and
|
||||
* decoders using this mode are destroyed as well.
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
|
||||
|
||||
/* Encoder */
|
||||
/** Gets the size of an OpusCustomEncoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Creates a new encoder state. Each stream needs its own encoder
|
||||
* state (can't be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created encoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Initializes a previously allocated encoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_encoder_init(
|
||||
OpusCustomEncoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
/** Destroys a an encoder state.
|
||||
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
|
||||
* Samples with a range beyond +/-1.0 are supported but will
|
||||
* be clipped by decoders using the integer API and should
|
||||
* only be used if it is known that the far end supports
|
||||
* extended dynamic range. There must be exactly
|
||||
* frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
|
||||
OpusCustomEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
|
||||
* There must be exactly frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
|
||||
OpusCustomEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_encoderctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/* Decoder */
|
||||
|
||||
/** Gets the size of an OpusCustomDecoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Creates a new decoder state. Each stream needs its own decoder state (can't
|
||||
* be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
|
||||
* stream (must be the same characteristics as used for the encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created decoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Initializes a previously allocated decoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
|
||||
OpusCustomDecoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
/** Destroys a an decoder state.
|
||||
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
|
||||
|
||||
/** Decode an opus custom frame with floating point output
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
float *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode an opus custom frame
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_genericctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_CUSTOM_H */
|
|
@ -0,0 +1,655 @@
|
|||
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_defines.h
|
||||
* @brief Opus reference implementation constants
|
||||
*/
|
||||
|
||||
#ifndef OPUS_DEFINES_H
|
||||
#define OPUS_DEFINES_H
|
||||
|
||||
#include "opus_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_errorcodes Error codes
|
||||
* @{
|
||||
*/
|
||||
/** No error @hideinitializer*/
|
||||
#define OPUS_OK 0
|
||||
/** One or more invalid/out of range arguments @hideinitializer*/
|
||||
#define OPUS_BAD_ARG -1
|
||||
/** The mode struct passed is invalid @hideinitializer*/
|
||||
#define OPUS_BUFFER_TOO_SMALL -2
|
||||
/** An internal error was detected @hideinitializer*/
|
||||
#define OPUS_INTERNAL_ERROR -3
|
||||
/** The compressed data passed is corrupted @hideinitializer*/
|
||||
#define OPUS_INVALID_PACKET -4
|
||||
/** Invalid/unsupported request number @hideinitializer*/
|
||||
#define OPUS_UNIMPLEMENTED -5
|
||||
/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
|
||||
#define OPUS_INVALID_STATE -6
|
||||
/** Memory allocation has failed @hideinitializer*/
|
||||
#define OPUS_ALLOC_FAIL -7
|
||||
/**@}*/
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
/**Export control for opus functions */
|
||||
|
||||
#ifndef OPUS_EXPORT
|
||||
# if defined(__GNUC__) && defined(OPUS_BUILD)
|
||||
# define OPUS_EXPORT __attribute__ ((visibility ("default")))
|
||||
# elif defined(WIN32) && !defined(__MINGW32__)
|
||||
# ifdef OPUS_BUILD
|
||||
# define OPUS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# if !defined(OPUS_GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if OPUS_GNUC_PREREQ(3,0)
|
||||
# define OPUS_RESTRICT __restrict__
|
||||
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define OPUS_RESTRICT __restrict
|
||||
# else
|
||||
# define OPUS_RESTRICT
|
||||
# endif
|
||||
#else
|
||||
# define OPUS_RESTRICT restrict
|
||||
#endif
|
||||
|
||||
/**Warning attributes for opus functions
|
||||
* NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
|
||||
* some paranoid null checks. */
|
||||
#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define OPUS_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
|
||||
#else
|
||||
# define OPUS_ARG_NONNULL(_x)
|
||||
#endif
|
||||
|
||||
/** These are the actual Encoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
#define OPUS_SET_APPLICATION_REQUEST 4000
|
||||
#define OPUS_GET_APPLICATION_REQUEST 4001
|
||||
#define OPUS_SET_BITRATE_REQUEST 4002
|
||||
#define OPUS_GET_BITRATE_REQUEST 4003
|
||||
#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
|
||||
#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
|
||||
#define OPUS_SET_VBR_REQUEST 4006
|
||||
#define OPUS_GET_VBR_REQUEST 4007
|
||||
#define OPUS_SET_BANDWIDTH_REQUEST 4008
|
||||
#define OPUS_GET_BANDWIDTH_REQUEST 4009
|
||||
#define OPUS_SET_COMPLEXITY_REQUEST 4010
|
||||
#define OPUS_GET_COMPLEXITY_REQUEST 4011
|
||||
#define OPUS_SET_INBAND_FEC_REQUEST 4012
|
||||
#define OPUS_GET_INBAND_FEC_REQUEST 4013
|
||||
#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
|
||||
#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
|
||||
#define OPUS_SET_DTX_REQUEST 4016
|
||||
#define OPUS_GET_DTX_REQUEST 4017
|
||||
#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
|
||||
#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
|
||||
#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
|
||||
#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
|
||||
#define OPUS_SET_SIGNAL_REQUEST 4024
|
||||
#define OPUS_GET_SIGNAL_REQUEST 4025
|
||||
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
|
||||
/* #define OPUS_RESET_STATE 4028 */
|
||||
#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
|
||||
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
|
||||
#define OPUS_GET_PITCH_REQUEST 4033
|
||||
#define OPUS_SET_GAIN_REQUEST 4034
|
||||
#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
|
||||
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
|
||||
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
|
||||
|
||||
#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
|
||||
|
||||
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
|
||||
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
|
||||
* @see opus_genericctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
/* Values for the various encoder CTLs */
|
||||
#define OPUS_AUTO -1000 /**<Auto/default setting @hideinitializer*/
|
||||
#define OPUS_BITRATE_MAX -1 /**<Maximum bitrate @hideinitializer*/
|
||||
|
||||
/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_VOIP 2048
|
||||
/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_AUDIO 2049
|
||||
/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
|
||||
|
||||
#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
|
||||
#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
|
||||
#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @defgroup opus_encoderctls Encoder related CTLs
|
||||
*
|
||||
* These are convenience macros for use with the \c opus_encode_ctl
|
||||
* interface. They are used to generate the appropriate series of
|
||||
* arguments for that call, passing the correct type, size and so
|
||||
* on as expected for each particular request.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
|
||||
* if (ret != OPUS_OK) return ret;
|
||||
*
|
||||
* opus_int32 rate;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_genericctls, opus_encoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures the encoder's computational complexity.
|
||||
* The supported range is 0-10 inclusive with 10 representing the highest complexity.
|
||||
* @see OPUS_GET_COMPLEXITY
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's complexity configuration.
|
||||
* @see OPUS_SET_COMPLEXITY
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
|
||||
* inclusive.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the bitrate in the encoder.
|
||||
* Rates from 500 to 512000 bits per second are meaningful, as well as the
|
||||
* special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
|
||||
* The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
|
||||
* rate as it can, which is useful for controlling the rate by adjusting the
|
||||
* output buffer size.
|
||||
* @see OPUS_GET_BITRATE
|
||||
* @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
|
||||
* is determined based on the number of
|
||||
* channels and the input sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's bitrate configuration.
|
||||
* @see OPUS_SET_BITRATE
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
|
||||
* The default is determined based on the
|
||||
* number of channels and the input
|
||||
* sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables variable bitrate (VBR) in the encoder.
|
||||
* The configured bitrate may not be met exactly because frames must
|
||||
* be an integer number of bytes in length.
|
||||
* @warning Only the MDCT mode of Opus can provide hard CBR behavior.
|
||||
* @see OPUS_GET_VBR
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
|
||||
* cause noticeable quality degradation.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
|
||||
* #OPUS_SET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
|
||||
/** Determine if variable bitrate (VBR) is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
|
||||
* #OPUS_GET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables constrained VBR in the encoder.
|
||||
* This setting is ignored when the encoder is in CBR mode.
|
||||
* @warning Only the MDCT mode of Opus currently heeds the constraint.
|
||||
* Speech mode ignores it completely, hybrid mode may fail to obey it
|
||||
* if the LPC layer uses more bitrate than the constraint would have
|
||||
* permitted.
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @see OPUS_SET_VBR
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
|
||||
* frame of buffering delay assuming a transport with a
|
||||
* serialization speed of the nominal bitrate.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
|
||||
/** Determine if constrained VBR is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @see OPUS_GET_VBR
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default).</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures mono/stereo forcing in the encoder.
|
||||
* This can force the encoder to produce packets encoded as either mono or
|
||||
* stereo, regardless of the format of the input audio. This is useful when
|
||||
* the caller knows that the input signal is currently a mono source embedded
|
||||
* in a stereo stream.
|
||||
* @see OPUS_GET_FORCE_CHANNELS
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's forced channel configuration.
|
||||
* @see OPUS_SET_FORCE_CHANNELS
|
||||
* @param[out] x <tt>opus_int32 *</tt>:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the maximum bandpass that the encoder will select automatically.
|
||||
* Applications should normally use this instead of #OPUS_SET_BANDWIDTH
|
||||
* (leaving that set to the default, #OPUS_AUTO). This allows the
|
||||
* application to set an upper bound based on the type of input it is
|
||||
* providing, but still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_MAX_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Gets the encoder's configured maximum allowed bandpass.
|
||||
* @see OPUS_SET_MAX_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Sets the encoder's bandpass to a specific value.
|
||||
* This prevents the encoder from automatically selecting the bandpass based
|
||||
* on the available bitrate. If an application knows the bandpass of the input
|
||||
* audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
|
||||
* instead, which still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Configures the type of signal being encoded.
|
||||
* This is a hint which helps the encoder's mode selection.
|
||||
* @see OPUS_GET_SIGNAL
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal type.
|
||||
* @see OPUS_SET_SIGNAL
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
|
||||
/** Configures the encoder's intended application.
|
||||
* The initial value is a mandatory argument to the encoder_create function.
|
||||
* @see OPUS_GET_APPLICATION
|
||||
* @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured application.
|
||||
* @see OPUS_SET_APPLICATION
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the sampling rate the encoder or decoder was initialized with.
|
||||
* This simply returns the <code>Fs</code> value passed to opus_encoder_init()
|
||||
* or opus_decoder_init().
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the total samples of delay added by the entire codec.
|
||||
* This can be queried by the encoder and then the provided number of samples can be
|
||||
* skipped on from the start of the decoder's output to provide time aligned input
|
||||
* and output. From the perspective of a decoding application the real data begins this many
|
||||
* samples late.
|
||||
*
|
||||
* The decoder contribution to this delay is identical for all decoders, but the
|
||||
* encoder portion of the delay may vary from implementation to implementation,
|
||||
* version to version, or even depend on the encoder's initial configuration.
|
||||
* Applications needing delay compensation should call this CTL rather than
|
||||
* hard-coding a value.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of inband forward error correction (FEC).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_INBAND_FEC
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
|
||||
* <dt>1</dt><dd>Enable inband FEC.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of inband forward error correction.
|
||||
* @see OPUS_SET_INBAND_FEC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's expected packet loss percentage.
|
||||
* Higher values with trigger progressively more loss resistant behavior in the encoder
|
||||
* at the expense of quality at a given bitrate in the lossless case, but greater quality
|
||||
* under loss.
|
||||
* @see OPUS_GET_PACKET_LOSS_PERC
|
||||
* @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured packet loss percentage.
|
||||
* @see OPUS_SET_PACKET_LOSS_PERC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
|
||||
* in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of discontinuous transmission (DTX).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_DTX
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable DTX (default).</dd>
|
||||
* <dt>1</dt><dd>Enabled DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of discontinuous transmission.
|
||||
* @see OPUS_SET_DTX
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>DTX disabled (default).</dd>
|
||||
* <dt>1</dt><dd>DTX enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Configures the depth of signal being encoded.
|
||||
* This is a hint which helps the encoder identify silence and near-silence.
|
||||
* @see OPUS_GET_LSB_DEPTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
|
||||
* (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal depth.
|
||||
* @see OPUS_SET_LSB_DEPTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
|
||||
* 24 (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_genericctls Generic CTLs
|
||||
*
|
||||
* These macros are used with the \c opus_decoder_ctl and
|
||||
* \c opus_encoder_ctl calls to generate a particular
|
||||
* request.
|
||||
*
|
||||
* When called on an \c OpusDecoder they apply to that
|
||||
* particular decoder instance. When called on an
|
||||
* \c OpusEncoder they apply to the corresponding setting
|
||||
* on that encoder instance, if present.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* opus_int32 pitch;
|
||||
* ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
|
||||
* if (ret == OPUS_OK) return ret;
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
|
||||
*
|
||||
* opus_int32 enc_bw, dec_bw;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
|
||||
* if (enc_bw != dec_bw) {
|
||||
* printf("packet bandwidth mismatch!\n");
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Resets the codec state to be equivalent to a freshly initialized state.
|
||||
* This should be called when switching streams in order to prevent
|
||||
* the back to back decoding from giving different results from
|
||||
* one at a time decoding.
|
||||
* @hideinitializer */
|
||||
#define OPUS_RESET_STATE 4028
|
||||
|
||||
/** Gets the final state of the codec's entropy coder.
|
||||
* This is used for testing purposes,
|
||||
* The encoder and decoder state should be identical after coding a payload
|
||||
* (assuming no data corruption or software bugs)
|
||||
*
|
||||
* @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
|
||||
|
||||
/** Gets the pitch of the last decoded frame, if available.
|
||||
* This can be used for any post-processing algorithm requiring the use of pitch,
|
||||
* e.g. time stretching/shortening. If the last frame was not voiced, or if the
|
||||
* pitch was not coded in the frame, then zero is returned.
|
||||
*
|
||||
* This CTL is only implemented for decoder instances.
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the encoder's configured bandpass or the decoder's last bandpass.
|
||||
* @see OPUS_SET_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoderctls Decoder related CTLs
|
||||
* @see opus_genericctls, opus_encoderctls, opus_decoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures decoder gain adjustment.
|
||||
* Scales the decoded output by a factor specified in Q8 dB units.
|
||||
* This has a maximum range of -32768 to 32767 inclusive, and returns
|
||||
* OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
|
||||
* This setting survives decoder reset.
|
||||
*
|
||||
* gain = pow(10, x/(20.0*256))
|
||||
*
|
||||
* @param[in] x <tt>opus_int32</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
|
||||
/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_libinfo Opus library information functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Converts an opus error code into a human readable string.
|
||||
*
|
||||
* @param[in] error <tt>int</tt>: Error number
|
||||
* @returns Error string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_strerror(int error);
|
||||
|
||||
/** Gets the libopus version string.
|
||||
*
|
||||
* @returns Version string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_get_version_string(void);
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_DEFINES_H */
|
|
@ -0,0 +1,632 @@
|
|||
/* Copyright (c) 2011 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_multistream.h
|
||||
* @brief Opus reference implementation multistream API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_MULTISTREAM_H
|
||||
#define OPUS_MULTISTREAM_H
|
||||
|
||||
#include "opus.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
|
||||
/** Macros to trigger compilation errors when the wrong types are provided to a
|
||||
* CTL. */
|
||||
/**@{*/
|
||||
#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
|
||||
#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
|
||||
/**@}*/
|
||||
|
||||
/** These are the actual encoder and decoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
/**@{*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
|
||||
/**@}*/
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
|
||||
*
|
||||
* These are convenience macros that are specific to the
|
||||
* opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
|
||||
* interface.
|
||||
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
|
||||
* @ref opus_decoderctls may be applied to a multistream encoder or decoder as
|
||||
* well.
|
||||
* In addition, you may retrieve the encoder or decoder state for an specific
|
||||
* stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
|
||||
* #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/** Gets the encoder state for an individual stream of a multistream encoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the encoder.
|
||||
* @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
|
||||
* encoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
|
||||
|
||||
/** Gets the decoder state for an individual stream of a multistream decoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the decoder.
|
||||
* @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
|
||||
* decoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_multistream Opus Multistream API
|
||||
* @{
|
||||
*
|
||||
* The multistream API allows individual Opus streams to be combined into a
|
||||
* single packet, enabling support for up to 255 channels. Unlike an
|
||||
* elementary Opus stream, the encoder and decoder must negotiate the channel
|
||||
* configuration before the decoder can successfully interpret the data in the
|
||||
* packets produced by the encoder. Some basic information, such as packet
|
||||
* duration, can be computed without any special negotiation.
|
||||
*
|
||||
* The format for multistream Opus packets is defined in the
|
||||
* <a href="http://tools.ietf.org/html/draft-terriberry-oggopus">Ogg
|
||||
* encapsulation specification</a> and is based on the self-delimited Opus
|
||||
* framing described in Appendix B of <a href="http://tools.ietf.org/html/rfc6716">RFC 6716</a>.
|
||||
* Normal Opus packets are just a degenerate case of multistream Opus packets,
|
||||
* and can be encoded or decoded with the multistream API by setting
|
||||
* <code>streams</code> to <code>1</code> when initializing the encoder or
|
||||
* decoder.
|
||||
*
|
||||
* Multistream Opus streams can contain up to 255 elementary Opus streams.
|
||||
* These may be either "uncoupled" or "coupled", indicating that the decoder
|
||||
* is configured to decode them to either 1 or 2 channels, respectively.
|
||||
* The streams are ordered so that all coupled streams appear at the
|
||||
* beginning.
|
||||
*
|
||||
* A <code>mapping</code> table defines which decoded channel <code>i</code>
|
||||
* should be used for each input/output (I/O) channel <code>j</code>. This table is
|
||||
* typically provided as an unsigned char array.
|
||||
* Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
|
||||
* If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
|
||||
* encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
|
||||
* is even, or as the right channel of stream <code>(i/2)</code> if
|
||||
* <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
|
||||
* mono in stream <code>(i - coupled_streams)</code>, unless it has the special
|
||||
* value 255, in which case it is omitted from the encoding entirely (the
|
||||
* decoder will reproduce it as silence). Each value <code>i</code> must either
|
||||
* be the special value 255 or be less than <code>streams + coupled_streams</code>.
|
||||
*
|
||||
* The output channels specified by the encoder
|
||||
* should use the
|
||||
* <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
|
||||
* channel ordering</a>. A decoder may wish to apply an additional permutation
|
||||
* to the mapping the encoder used to achieve a different output channel
|
||||
* order (e.g. for outputing in WAV order).
|
||||
*
|
||||
* Each multistream packet contains an Opus packet for each stream, and all of
|
||||
* the Opus packets in a single multistream packet must have the same
|
||||
* duration. Therefore the duration of a multistream packet can be extracted
|
||||
* from the TOC sequence of the first stream, which is located at the
|
||||
* beginning of the packet, just like an elementary Opus stream:
|
||||
*
|
||||
* @code
|
||||
* int nb_samples;
|
||||
* int nb_frames;
|
||||
* nb_frames = opus_packet_get_nb_frames(data, len);
|
||||
* if (nb_frames < 1)
|
||||
* return nb_frames;
|
||||
* nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
|
||||
* @endcode
|
||||
*
|
||||
* The general encoding and decoding process proceeds exactly the same as in
|
||||
* the normal @ref opus_encoder and @ref opus_decoder APIs.
|
||||
* See their documentation for an overview of how to use the corresponding
|
||||
* multistream functions.
|
||||
*/
|
||||
|
||||
/** Opus multistream encoder state.
|
||||
* This contains the complete state of a multistream Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_init
|
||||
*/
|
||||
typedef struct OpusMSEncoder OpusMSEncoder;
|
||||
|
||||
/** Opus multistream decoder state.
|
||||
* This contains the complete state of a multistream Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_decoder_init
|
||||
*/
|
||||
typedef struct OpusMSDecoder OpusMSDecoder;
|
||||
|
||||
/**\name Multistream encoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an OpusMSEncoder structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
/** Allocates and initializes a multistream encoder state.
|
||||
* Call opus_multistream_encoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
/** Initialize a previously allocated multistream encoder state.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_init(
|
||||
OpusMSEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Encodes a multistream Opus frame.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
|
||||
* samples.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
|
||||
OpusMSEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a multistream Opus frame from floating point input.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
|
||||
* samples with a normal range of
|
||||
* +/-1.0.
|
||||
* Samples with a range beyond +/-1.0
|
||||
* are supported but will be clipped by
|
||||
* decoders using the integer API and
|
||||
* should only be used if it is known
|
||||
* that the far end supports extended
|
||||
* dynamic range.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
|
||||
OpusMSEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Frees an <code>OpusMSEncoder</code> allocated by
|
||||
* opus_multistream_encoder_create().
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_encoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**\name Multistream decoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an <code>OpusMSDecoder</code> structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
/** Allocates and initializes a multistream decoder state.
|
||||
* Call opus_multistream_decoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
/** Intialize a previously allocated decoder state object.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_deocder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_init(
|
||||
OpusMSDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Decode a multistream Opus packet.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode a multistream Opus packet with floating point output.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_decoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Frees an <code>OpusMSDecoder</code> allocated by
|
||||
* opus_multistream_decoder_create().
|
||||
* @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_MULTISTREAM_H */
|
|
@ -0,0 +1,159 @@
|
|||
/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
|
||||
/* Modified by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* opus_types.h based on ogg_types.h from libogg */
|
||||
|
||||
/**
|
||||
@file opus_types.h
|
||||
@brief Opus reference implementation types
|
||||
*/
|
||||
#ifndef OPUS_TYPES_H
|
||||
#define OPUS_TYPES_H
|
||||
|
||||
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
|
||||
#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int16_t opus_int16;
|
||||
typedef uint16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef uint32_t opus_uint32;
|
||||
#elif defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <_G_config.h>
|
||||
typedef _G_int32_t opus_int32;
|
||||
typedef _G_uint32_t opus_uint32;
|
||||
typedef _G_int16 opus_int16;
|
||||
typedef _G_uint16 opus_uint16;
|
||||
# elif defined(__MINGW32__)
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int32 opus_int32;
|
||||
typedef unsigned __int32 opus_uint32;
|
||||
typedef __int16 opus_int16;
|
||||
typedef unsigned __int16 opus_uint16;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 opus_int16;
|
||||
typedef UInt16 opus_uint16;
|
||||
typedef SInt32 opus_int32;
|
||||
typedef UInt32 opus_uint32;
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t opus_int16;
|
||||
typedef u_int16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16 opus_int16;
|
||||
typedef u_int16 opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef int opus_int32;
|
||||
typedef unsigned opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef signed int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef long opus_int32;
|
||||
typedef unsigned long opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C6X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#else
|
||||
|
||||
/* Give up, take a reasonable guess */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#endif
|
||||
|
||||
#define opus_int int /* used for counters etc; at least 16 bits */
|
||||
#define opus_int64 long long
|
||||
#define opus_int8 signed char
|
||||
|
||||
#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
|
||||
#define opus_uint64 unsigned long long
|
||||
#define opus_uint8 unsigned char
|
||||
|
||||
#endif /* OPUS_TYPES_H */
|
|
@ -0,0 +1,252 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
/* Conversion between prediction filter coefficients and NLSFs */
|
||||
/* Requires the order to be an even number */
|
||||
/* A piecewise linear approximation maps LSF <-> cos(LSF) */
|
||||
/* Therefore the result is not accurate NLSFs, but the two */
|
||||
/* functions are accurate inverses of each other */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
#include "tables.h"
|
||||
|
||||
/* Number of binary divisions, when not in low complexity mode */
|
||||
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
|
||||
#define MAX_ITERATIONS_A2NLSF_FIX 30
|
||||
|
||||
/* Helper function for A2NLSF(..) */
|
||||
/* Transforms polynomials from cos(n*f) to cos(f)^n */
|
||||
static inline void silk_A2NLSF_trans_poly(
|
||||
opus_int32 *p, /* I/O Polynomial */
|
||||
const opus_int dd /* I Polynomial order (= filter order / 2 ) */
|
||||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
|
||||
for( k = 2; k <= dd; k++ ) {
|
||||
for( n = dd; n > k; n-- ) {
|
||||
p[ n - 2 ] -= p[ n ];
|
||||
}
|
||||
p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
|
||||
}
|
||||
}
|
||||
/* Helper function for A2NLSF(..) */
|
||||
/* Polynomial evaluation */
|
||||
static inline opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */
|
||||
opus_int32 *p, /* I Polynomial, Q16 */
|
||||
const opus_int32 x, /* I Evaluation point, Q12 */
|
||||
const opus_int dd /* I Order */
|
||||
)
|
||||
{
|
||||
opus_int n;
|
||||
opus_int32 x_Q16, y32;
|
||||
|
||||
y32 = p[ dd ]; /* Q16 */
|
||||
x_Q16 = silk_LSHIFT( x, 4 );
|
||||
for( n = dd - 1; n >= 0; n-- ) {
|
||||
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
|
||||
}
|
||||
return y32;
|
||||
}
|
||||
|
||||
static inline void silk_A2NLSF_init(
|
||||
const opus_int32 *a_Q16,
|
||||
opus_int32 *P,
|
||||
opus_int32 *Q,
|
||||
const opus_int dd
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
|
||||
/* Convert filter coefs to even and odd polynomials */
|
||||
P[dd] = silk_LSHIFT( 1, 16 );
|
||||
Q[dd] = silk_LSHIFT( 1, 16 );
|
||||
for( k = 0; k < dd; k++ ) {
|
||||
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */
|
||||
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */
|
||||
}
|
||||
|
||||
/* Divide out zeros as we have that for even filter orders, */
|
||||
/* z = 1 is always a root in Q, and */
|
||||
/* z = -1 is always a root in P */
|
||||
for( k = dd; k > 0; k-- ) {
|
||||
P[ k - 1 ] -= P[ k ];
|
||||
Q[ k - 1 ] += Q[ k ];
|
||||
}
|
||||
|
||||
/* Transform polynomials from cos(n*f) to cos(f)^n */
|
||||
silk_A2NLSF_trans_poly( P, dd );
|
||||
silk_A2NLSF_trans_poly( Q, dd );
|
||||
}
|
||||
|
||||
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
|
||||
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
|
||||
void silk_A2NLSF(
|
||||
opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
|
||||
opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
|
||||
const opus_int d /* I Filter order (must be even) */
|
||||
)
|
||||
{
|
||||
opus_int i, k, m, dd, root_ix, ffrac;
|
||||
opus_int32 xlo, xhi, xmid;
|
||||
opus_int32 ylo, yhi, ymid, thr;
|
||||
opus_int32 nom, den;
|
||||
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
|
||||
opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
|
||||
opus_int32 *PQ[ 2 ];
|
||||
opus_int32 *p;
|
||||
|
||||
/* Store pointers to array */
|
||||
PQ[ 0 ] = P;
|
||||
PQ[ 1 ] = Q;
|
||||
|
||||
dd = silk_RSHIFT( d, 1 );
|
||||
|
||||
silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||
|
||||
/* Find roots, alternating between P and Q */
|
||||
p = P; /* Pointer to polynomial */
|
||||
|
||||
xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
|
||||
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||
|
||||
if( ylo < 0 ) {
|
||||
/* Set the first NLSF to zero and move on to the next */
|
||||
NLSF[ 0 ] = 0;
|
||||
p = Q; /* Pointer to polynomial */
|
||||
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||
root_ix = 1; /* Index of current root */
|
||||
} else {
|
||||
root_ix = 0; /* Index of current root */
|
||||
}
|
||||
k = 1; /* Loop counter */
|
||||
i = 0; /* Counter for bandwidth expansions applied */
|
||||
thr = 0;
|
||||
while( 1 ) {
|
||||
/* Evaluate polynomial */
|
||||
xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
|
||||
yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
|
||||
|
||||
/* Detect zero crossing */
|
||||
if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
|
||||
if( yhi == 0 ) {
|
||||
/* If the root lies exactly at the end of the current */
|
||||
/* interval, look for the next root in the next interval */
|
||||
thr = 1;
|
||||
} else {
|
||||
thr = 0;
|
||||
}
|
||||
/* Binary division */
|
||||
ffrac = -256;
|
||||
for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
|
||||
/* Evaluate polynomial */
|
||||
xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
|
||||
ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
|
||||
|
||||
/* Detect zero crossing */
|
||||
if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
|
||||
/* Reduce frequency */
|
||||
xhi = xmid;
|
||||
yhi = ymid;
|
||||
} else {
|
||||
/* Increase frequency */
|
||||
xlo = xmid;
|
||||
ylo = ymid;
|
||||
ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
|
||||
}
|
||||
}
|
||||
|
||||
/* Interpolate */
|
||||
if( silk_abs( ylo ) < 65536 ) {
|
||||
/* Avoid dividing by zero */
|
||||
den = ylo - yhi;
|
||||
nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
|
||||
if( den != 0 ) {
|
||||
ffrac += silk_DIV32( nom, den );
|
||||
}
|
||||
} else {
|
||||
/* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
|
||||
ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
|
||||
}
|
||||
NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
|
||||
|
||||
silk_assert( NLSF[ root_ix ] >= 0 );
|
||||
|
||||
root_ix++; /* Next root */
|
||||
if( root_ix >= d ) {
|
||||
/* Found all roots */
|
||||
break;
|
||||
}
|
||||
/* Alternate pointer to polynomial */
|
||||
p = PQ[ root_ix & 1 ];
|
||||
|
||||
/* Evaluate polynomial */
|
||||
xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
|
||||
ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
|
||||
} else {
|
||||
/* Increment loop counter */
|
||||
k++;
|
||||
xlo = xhi;
|
||||
ylo = yhi;
|
||||
thr = 0;
|
||||
|
||||
if( k > LSF_COS_TAB_SZ_FIX ) {
|
||||
i++;
|
||||
if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
|
||||
/* Set NLSFs to white spectrum and exit */
|
||||
NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
|
||||
for( k = 1; k < d; k++ ) {
|
||||
NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Error: Apply progressively more bandwidth expansion and run again */
|
||||
silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
|
||||
|
||||
silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||
p = P; /* Pointer to polynomial */
|
||||
xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
|
||||
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||
if( ylo < 0 ) {
|
||||
/* Set the first NLSF to zero and move on to the next */
|
||||
NLSF[ 0 ] = 0;
|
||||
p = Q; /* Pointer to polynomial */
|
||||
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||
root_ix = 1; /* Index of current root */
|
||||
} else {
|
||||
root_ix = 0; /* Index of current root */
|
||||
}
|
||||
k = 1; /* Reset loop counter */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_API_H
|
||||
#define SILK_API_H
|
||||
|
||||
#include "control.h"
|
||||
#include "typedef.h"
|
||||
#include "errors.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define SILK_MAX_FRAMES_PER_PACKET 3
|
||||
|
||||
/* Struct for TOC (Table of Contents) */
|
||||
typedef struct {
|
||||
opus_int VADFlag; /* Voice activity for packet */
|
||||
opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */
|
||||
opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */
|
||||
} silk_TOC_struct;
|
||||
|
||||
/****************************************/
|
||||
/* Encoder functions */
|
||||
/****************************************/
|
||||
|
||||
/***********************************************/
|
||||
/* Get size in bytes of the Silk encoder state */
|
||||
/***********************************************/
|
||||
opus_int silk_Get_Encoder_Size( /* O Returns error code */
|
||||
opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */
|
||||
);
|
||||
|
||||
/*************************/
|
||||
/* Init or reset encoder */
|
||||
/*************************/
|
||||
opus_int silk_InitEncoder( /* O Returns error code */
|
||||
void *encState, /* I/O State */
|
||||
silk_EncControlStruct *encStatus /* O Encoder Status */
|
||||
);
|
||||
|
||||
/**************************/
|
||||
/* Encode frame with Silk */
|
||||
/**************************/
|
||||
/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */
|
||||
/* encControl->payloadSize_ms is set to */
|
||||
opus_int silk_Encode( /* O Returns error code */
|
||||
void *encState, /* I/O State */
|
||||
silk_EncControlStruct *encControl, /* I Control status */
|
||||
const opus_int16 *samplesIn, /* I Speech sample input vector */
|
||||
opus_int nSamplesIn, /* I Number of samples in input vector */
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
|
||||
const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
|
||||
);
|
||||
|
||||
/****************************************/
|
||||
/* Decoder functions */
|
||||
/****************************************/
|
||||
|
||||
/***********************************************/
|
||||
/* Get size in bytes of the Silk decoder state */
|
||||
/***********************************************/
|
||||
opus_int silk_Get_Decoder_Size( /* O Returns error code */
|
||||
opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */
|
||||
);
|
||||
|
||||
/*************************/
|
||||
/* Init or Reset decoder */
|
||||
/*************************/
|
||||
opus_int silk_InitDecoder( /* O Returns error code */
|
||||
void *decState /* I/O State */
|
||||
);
|
||||
|
||||
/******************/
|
||||
/* Decode a frame */
|
||||
/******************/
|
||||
opus_int silk_Decode( /* O Returns error code */
|
||||
void* decState, /* I/O State */
|
||||
silk_DecControlStruct* decControl, /* I/O Control Structure */
|
||||
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
|
||||
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int16 *samplesOut, /* O Decoded output speech vector */
|
||||
opus_int32 *nSamplesOut /* O Number of samples decoded */
|
||||
);
|
||||
|
||||
#if 0
|
||||
/**************************************/
|
||||
/* Get table of contents for a packet */
|
||||
/**************************************/
|
||||
opus_int silk_get_TOC(
|
||||
const opus_uint8 *payload, /* I Payload data */
|
||||
const opus_int nBytesIn, /* I Number of input bytes */
|
||||
const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
|
||||
silk_TOC_struct *Silk_TOC /* O Type of content */
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,167 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Generates excitation for CNG LPC synthesis */
|
||||
static inline void silk_CNG_exc(
|
||||
opus_int32 residual_Q10[], /* O CNG residual signal Q10 */
|
||||
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
|
||||
opus_int32 Gain_Q16, /* I Gain to apply */
|
||||
opus_int length, /* I Length */
|
||||
opus_int32 *rand_seed /* I/O Seed to random index generator */
|
||||
)
|
||||
{
|
||||
opus_int32 seed;
|
||||
opus_int i, idx, exc_mask;
|
||||
|
||||
exc_mask = CNG_BUF_MASK_MAX;
|
||||
while( exc_mask > length ) {
|
||||
exc_mask = silk_RSHIFT( exc_mask, 1 );
|
||||
}
|
||||
|
||||
seed = *rand_seed;
|
||||
for( i = 0; i < length; i++ ) {
|
||||
seed = silk_RAND( seed );
|
||||
idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
|
||||
silk_assert( idx >= 0 );
|
||||
silk_assert( idx <= CNG_BUF_MASK_MAX );
|
||||
residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) );
|
||||
}
|
||||
*rand_seed = seed;
|
||||
}
|
||||
|
||||
void silk_CNG_Reset(
|
||||
silk_decoder_state *psDec /* I/O Decoder state */
|
||||
)
|
||||
{
|
||||
opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
|
||||
|
||||
NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
|
||||
NLSF_acc_Q15 = 0;
|
||||
for( i = 0; i < psDec->LPC_order; i++ ) {
|
||||
NLSF_acc_Q15 += NLSF_step_Q15;
|
||||
psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
|
||||
}
|
||||
psDec->sCNG.CNG_smth_Gain_Q16 = 0;
|
||||
psDec->sCNG.rand_seed = 3176576;
|
||||
}
|
||||
|
||||
/* Updates CNG estimate, and applies the CNG when packet was lost */
|
||||
void silk_CNG(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int16 frame[], /* I/O Signal */
|
||||
opus_int length /* I Length of residual */
|
||||
)
|
||||
{
|
||||
opus_int i, subfr;
|
||||
opus_int32 sum_Q6, max_Gain_Q16;
|
||||
opus_int16 A_Q12[ MAX_LPC_ORDER ];
|
||||
opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ];
|
||||
silk_CNG_struct *psCNG = &psDec->sCNG;
|
||||
|
||||
if( psDec->fs_kHz != psCNG->fs_kHz ) {
|
||||
/* Reset state */
|
||||
silk_CNG_Reset( psDec );
|
||||
|
||||
psCNG->fs_kHz = psDec->fs_kHz;
|
||||
}
|
||||
if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
|
||||
/* Update CNG parameters */
|
||||
|
||||
/* Smoothing of LSF's */
|
||||
for( i = 0; i < psDec->LPC_order; i++ ) {
|
||||
psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
|
||||
}
|
||||
/* Find the subframe with the highest gain */
|
||||
max_Gain_Q16 = 0;
|
||||
subfr = 0;
|
||||
for( i = 0; i < psDec->nb_subfr; i++ ) {
|
||||
if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
|
||||
max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
|
||||
subfr = i;
|
||||
}
|
||||
}
|
||||
/* Update CNG excitation buffer with excitation from this subframe */
|
||||
silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
|
||||
silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
|
||||
|
||||
/* Smooth gains */
|
||||
for( i = 0; i < psDec->nb_subfr; i++ ) {
|
||||
psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Add CNG when packet is lost or during DTX */
|
||||
if( psDec->lossCnt ) {
|
||||
|
||||
/* Generate CNG excitation */
|
||||
silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
|
||||
|
||||
/* Convert CNG NLSF to filter representation */
|
||||
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
|
||||
|
||||
/* Generate CNG signal, by synthesis filtering */
|
||||
silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
for( i = 0; i < length; i++ ) {
|
||||
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
|
||||
if( psDec->LPC_order == 16 ) {
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
|
||||
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
|
||||
}
|
||||
|
||||
/* Update states */
|
||||
CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 );
|
||||
|
||||
frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( sum_Q6, 6 ) );
|
||||
}
|
||||
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
} else {
|
||||
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifdef FIXED_POINT
|
||||
#include "main_FIX.h"
|
||||
#else
|
||||
#include "main_FLP.h"
|
||||
#endif
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
|
||||
void silk_HP_variable_cutoff(
|
||||
silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */
|
||||
)
|
||||
{
|
||||
opus_int quality_Q15;
|
||||
opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
|
||||
silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn;
|
||||
|
||||
/* Adaptive cutoff frequency: estimate low end of pitch frequency range */
|
||||
if( psEncC1->prevSignalType == TYPE_VOICED ) {
|
||||
/* difference, in log domain */
|
||||
pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag );
|
||||
pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 );
|
||||
|
||||
/* adjustment based on quality */
|
||||
quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ];
|
||||
pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ),
|
||||
pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) );
|
||||
|
||||
/* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */
|
||||
delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 );
|
||||
if( delta_freq_Q7 < 0 ) {
|
||||
/* less smoothing for decreasing pitch frequency, to track something close to the minimum */
|
||||
delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 );
|
||||
}
|
||||
|
||||
/* limit delta, to reduce impact of outliers in pitch estimation */
|
||||
delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
|
||||
|
||||
/* update smoother */
|
||||
psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15,
|
||||
silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
|
||||
|
||||
/* limit frequency range */
|
||||
psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15,
|
||||
silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ),
|
||||
silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
/*! \file silk_Inlines.h
|
||||
* \brief silk_Inlines.h defines inline signal processing functions.
|
||||
*/
|
||||
|
||||
#ifndef SILK_FIX_INLINES_H
|
||||
#define SILK_FIX_INLINES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* count leading zeros of opus_int64 */
|
||||
static inline opus_int32 silk_CLZ64( opus_int64 in )
|
||||
{
|
||||
opus_int32 in_upper;
|
||||
|
||||
in_upper = (opus_int32)silk_RSHIFT64(in, 32);
|
||||
if (in_upper == 0) {
|
||||
/* Search in the lower 32 bits */
|
||||
return 32 + silk_CLZ32( (opus_int32) in );
|
||||
} else {
|
||||
/* Search in the upper 32 bits */
|
||||
return silk_CLZ32( in_upper );
|
||||
}
|
||||
}
|
||||
|
||||
/* get number of leading zeros and fractional part (the bits right after the leading one */
|
||||
static inline void silk_CLZ_FRAC(
|
||||
opus_int32 in, /* I input */
|
||||
opus_int32 *lz, /* O number of leading zeros */
|
||||
opus_int32 *frac_Q7 /* O the 7 bits right after the leading one */
|
||||
)
|
||||
{
|
||||
opus_int32 lzeros = silk_CLZ32(in);
|
||||
|
||||
* lz = lzeros;
|
||||
* frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f;
|
||||
}
|
||||
|
||||
/* Approximation of square root */
|
||||
/* Accuracy: < +/- 10% for output values > 15 */
|
||||
/* < +/- 2.5% for output values > 120 */
|
||||
static inline opus_int32 silk_SQRT_APPROX( opus_int32 x )
|
||||
{
|
||||
opus_int32 y, lz, frac_Q7;
|
||||
|
||||
if( x <= 0 ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
silk_CLZ_FRAC(x, &lz, &frac_Q7);
|
||||
|
||||
if( lz & 1 ) {
|
||||
y = 32768;
|
||||
} else {
|
||||
y = 46214; /* 46214 = sqrt(2) * 32768 */
|
||||
}
|
||||
|
||||
/* get scaling right */
|
||||
y >>= silk_RSHIFT(lz, 1);
|
||||
|
||||
/* increment using fractional part of input */
|
||||
y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7));
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* Divide two int32 values and return result as int32 in a given Q-domain */
|
||||
static inline opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
|
||||
const opus_int32 a32, /* I numerator (Q0) */
|
||||
const opus_int32 b32, /* I denominator (Q0) */
|
||||
const opus_int Qres /* I Q-domain of result (>= 0) */
|
||||
)
|
||||
{
|
||||
opus_int a_headrm, b_headrm, lshift;
|
||||
opus_int32 b32_inv, a32_nrm, b32_nrm, result;
|
||||
|
||||
silk_assert( b32 != 0 );
|
||||
silk_assert( Qres >= 0 );
|
||||
|
||||
/* Compute number of bits head room and normalize inputs */
|
||||
a_headrm = silk_CLZ32( silk_abs(a32) ) - 1;
|
||||
a32_nrm = silk_LSHIFT(a32, a_headrm); /* Q: a_headrm */
|
||||
b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
|
||||
b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
|
||||
|
||||
/* Inverse of b32, with 14 bits of precision */
|
||||
b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
|
||||
|
||||
/* First approximation */
|
||||
result = silk_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
|
||||
|
||||
/* Compute residual by subtracting product of denominator and first approximation */
|
||||
/* It's OK to overflow because the final value of a32_nrm should always be small */
|
||||
a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 )); /* Q: a_headrm */
|
||||
|
||||
/* Refinement */
|
||||
result = silk_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
|
||||
|
||||
/* Convert to Qres domain */
|
||||
lshift = 29 + a_headrm - b_headrm - Qres;
|
||||
if( lshift < 0 ) {
|
||||
return silk_LSHIFT_SAT32(result, -lshift);
|
||||
} else {
|
||||
if( lshift < 32){
|
||||
return silk_RSHIFT(result, lshift);
|
||||
} else {
|
||||
/* Avoid undefined result */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Invert int32 value and return result as int32 in a given Q-domain */
|
||||
static inline opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
|
||||
const opus_int32 b32, /* I denominator (Q0) */
|
||||
const opus_int Qres /* I Q-domain of result (> 0) */
|
||||
)
|
||||
{
|
||||
opus_int b_headrm, lshift;
|
||||
opus_int32 b32_inv, b32_nrm, err_Q32, result;
|
||||
|
||||
silk_assert( b32 != 0 );
|
||||
silk_assert( Qres > 0 );
|
||||
|
||||
/* Compute number of bits head room and normalize input */
|
||||
b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
|
||||
b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
|
||||
|
||||
/* Inverse of b32, with 14 bits of precision */
|
||||
b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
|
||||
|
||||
/* First approximation */
|
||||
result = silk_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */
|
||||
|
||||
/* Compute residual by subtracting product of denominator and first approximation from one */
|
||||
err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */
|
||||
|
||||
/* Refinement */
|
||||
result = silk_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */
|
||||
|
||||
/* Convert to Qres domain */
|
||||
lshift = 61 - b_headrm - Qres;
|
||||
if( lshift <= 0 ) {
|
||||
return silk_LSHIFT_SAT32(result, -lshift);
|
||||
} else {
|
||||
if( lshift < 32){
|
||||
return silk_RSHIFT(result, lshift);
|
||||
}else{
|
||||
/* Avoid undefined result */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SILK_FIX_INLINES_H */
|
|
@ -0,0 +1,85 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/*******************************************/
|
||||
/* LPC analysis filter */
|
||||
/* NB! State is kept internally and the */
|
||||
/* filter always starts with zero state */
|
||||
/* first d output samples are set to zero */
|
||||
/*******************************************/
|
||||
|
||||
void silk_LPC_analysis_filter(
|
||||
opus_int16 *out, /* O Output signal */
|
||||
const opus_int16 *in, /* I Input signal */
|
||||
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
|
||||
const opus_int32 len, /* I Signal length */
|
||||
const opus_int32 d /* I Filter order */
|
||||
)
|
||||
{
|
||||
opus_int ix, j;
|
||||
opus_int32 out32_Q12, out32;
|
||||
const opus_int16 *in_ptr;
|
||||
|
||||
silk_assert( d >= 6 );
|
||||
silk_assert( (d & 1) == 0 );
|
||||
silk_assert( d <= len );
|
||||
|
||||
for( ix = d; ix < len; ix++ ) {
|
||||
in_ptr = &in[ ix - 1 ];
|
||||
|
||||
out32_Q12 = silk_SMULBB( in_ptr[ 0 ], B[ 0 ] );
|
||||
/* Allowing wrap around so that two wraps can cancel each other. The rare
|
||||
cases where the result wraps around can only be triggered by invalid streams*/
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
|
||||
for( j = 6; j < d; j += 2 ) {
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j ], B[ j ] );
|
||||
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
|
||||
}
|
||||
|
||||
/* Subtract prediction */
|
||||
out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
|
||||
|
||||
/* Scale to Q0 */
|
||||
out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
|
||||
|
||||
/* Saturate output */
|
||||
out[ ix ] = (opus_int16)silk_SAT16( out32 );
|
||||
}
|
||||
|
||||
/* Set first d output samples to zero */
|
||||
silk_memset( out, 0, d * sizeof( opus_int16 ) );
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
#define QA 24
|
||||
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
|
||||
|
||||
#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
|
||||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k, n, mult2Q;
|
||||
opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
|
||||
opus_int32 *Aold_QA, *Anew_QA;
|
||||
|
||||
Anew_QA = A_QA[ order & 1 ];
|
||||
|
||||
invGain_Q30 = (opus_int32)1 << 30;
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
|
||||
|
||||
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
|
||||
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
|
||||
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
|
||||
|
||||
/* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
|
||||
mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
|
||||
rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* invGain_Q30 range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
|
||||
|
||||
/* Swap pointers */
|
||||
Aold_QA = Anew_QA;
|
||||
Anew_QA = A_QA[ k & 1 ];
|
||||
|
||||
/* Update AR coefficient */
|
||||
for( n = 0; n < k; n++ ) {
|
||||
tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
|
||||
Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
|
||||
|
||||
/* Range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* Range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= 1<<30 );
|
||||
|
||||
return invGain_Q30;
|
||||
}
|
||||
|
||||
/* For input in Q12 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 *Anew_QA;
|
||||
opus_int32 DC_resp = 0;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
DC_resp += (opus_int32)A_Q12[ k ];
|
||||
Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
|
||||
}
|
||||
/* If the DC is unstable, we don't even need to do the full calculations */
|
||||
if( DC_resp >= 4096 ) {
|
||||
return 0;
|
||||
}
|
||||
return LPC_inverse_pred_gain_QA( Atmp_QA, order );
|
||||
}
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
/* For input in Q24 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 *Anew_QA;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
|
||||
}
|
||||
|
||||
return LPC_inverse_pred_gain_QA( Atmp_QA, order );
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,135 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Elliptic/Cauer filters designed with 0.1 dB passband ripple,
|
||||
80 dB minimum stopband attenuation, and
|
||||
[0.95 : 0.15 : 0.35] normalized cut off frequencies.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Helper function, interpolates the filter taps */
|
||||
static inline void silk_LP_interpolate_filter_taps(
|
||||
opus_int32 B_Q28[ TRANSITION_NB ],
|
||||
opus_int32 A_Q28[ TRANSITION_NA ],
|
||||
const opus_int ind,
|
||||
const opus_int32 fac_Q16
|
||||
)
|
||||
{
|
||||
opus_int nb, na;
|
||||
|
||||
if( ind < TRANSITION_INT_NUM - 1 ) {
|
||||
if( fac_Q16 > 0 ) {
|
||||
if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
|
||||
/* Piece-wise linear interpolation of B and A */
|
||||
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
|
||||
B_Q28[ nb ] = silk_SMLAWB(
|
||||
silk_Transition_LP_B_Q28[ ind ][ nb ],
|
||||
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
|
||||
silk_Transition_LP_B_Q28[ ind ][ nb ],
|
||||
fac_Q16 );
|
||||
}
|
||||
for( na = 0; na < TRANSITION_NA; na++ ) {
|
||||
A_Q28[ na ] = silk_SMLAWB(
|
||||
silk_Transition_LP_A_Q28[ ind ][ na ],
|
||||
silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
|
||||
silk_Transition_LP_A_Q28[ ind ][ na ],
|
||||
fac_Q16 );
|
||||
}
|
||||
} else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
|
||||
silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
|
||||
/* Piece-wise linear interpolation of B and A */
|
||||
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
|
||||
B_Q28[ nb ] = silk_SMLAWB(
|
||||
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
|
||||
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
|
||||
silk_Transition_LP_B_Q28[ ind ][ nb ],
|
||||
fac_Q16 - ( (opus_int32)1 << 16 ) );
|
||||
}
|
||||
for( na = 0; na < TRANSITION_NA; na++ ) {
|
||||
A_Q28[ na ] = silk_SMLAWB(
|
||||
silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
|
||||
silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
|
||||
silk_Transition_LP_A_Q28[ ind ][ na ],
|
||||
fac_Q16 - ( (opus_int32)1 << 16 ) );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
|
||||
silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
|
||||
}
|
||||
} else {
|
||||
silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
|
||||
silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Low-pass filter with variable cutoff frequency based on */
|
||||
/* piece-wise linear interpolation between elliptic filters */
|
||||
/* Start by setting psEncC->mode <> 0; */
|
||||
/* Deactivate by setting psEncC->mode = 0; */
|
||||
void silk_LP_variable_cutoff(
|
||||
silk_LP_state *psLP, /* I/O LP filter state */
|
||||
opus_int16 *frame, /* I/O Low-pass filtered output signal */
|
||||
const opus_int frame_length /* I Frame length */
|
||||
)
|
||||
{
|
||||
opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
|
||||
opus_int ind = 0;
|
||||
|
||||
silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
|
||||
|
||||
/* Run filter if needed */
|
||||
if( psLP->mode != 0 ) {
|
||||
/* Calculate index and interpolation factor for interpolation */
|
||||
#if( TRANSITION_INT_STEPS == 64 )
|
||||
fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
|
||||
#else
|
||||
fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
|
||||
#endif
|
||||
ind = silk_RSHIFT( fac_Q16, 16 );
|
||||
fac_Q16 -= silk_LSHIFT( ind, 16 );
|
||||
|
||||
silk_assert( ind >= 0 );
|
||||
silk_assert( ind < TRANSITION_INT_NUM );
|
||||
|
||||
/* Interpolate filter coefficients */
|
||||
silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
|
||||
|
||||
/* Update transition frame number for next frame */
|
||||
psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
|
||||
|
||||
/* ARMA low-pass filtering */
|
||||
silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
|
||||
silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,718 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SIGPROCFIX_API_MACROCOUNT_H
|
||||
#define SIGPROCFIX_API_MACROCOUNT_H
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef silk_MACRO_COUNT
|
||||
#define varDefine opus_int64 ops_count = 0;
|
||||
|
||||
extern opus_int64 ops_count;
|
||||
|
||||
static inline opus_int64 silk_SaveCount(){
|
||||
return(ops_count);
|
||||
}
|
||||
|
||||
static inline opus_int64 silk_SaveResetCount(){
|
||||
opus_int64 ret;
|
||||
|
||||
ret = ops_count;
|
||||
ops_count = 0;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline silk_PrintCount(){
|
||||
printf("ops_count = %d \n ", (opus_int32)ops_count);
|
||||
}
|
||||
|
||||
#undef silk_MUL
|
||||
static inline opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
ops_count += 4;
|
||||
ret = a32 * b32;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_MUL_uint
|
||||
static inline opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
|
||||
opus_uint32 ret;
|
||||
ops_count += 4;
|
||||
ret = a32 * b32;
|
||||
return ret;
|
||||
}
|
||||
#undef silk_MLA
|
||||
static inline opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 4;
|
||||
ret = a32 + b32 * c32;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_MLA_uint
|
||||
static inline opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
|
||||
opus_uint32 ret;
|
||||
ops_count += 4;
|
||||
ret = a32 + b32 * c32;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULWB
|
||||
static inline opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
ops_count += 5;
|
||||
ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
|
||||
return ret;
|
||||
}
|
||||
#undef silk_SMLAWB
|
||||
static inline opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 5;
|
||||
ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULWT
|
||||
static inline opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
ops_count += 4;
|
||||
ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
|
||||
return ret;
|
||||
}
|
||||
#undef silk_SMLAWT
|
||||
static inline opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 4;
|
||||
ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULBB
|
||||
static inline opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32);
|
||||
return ret;
|
||||
}
|
||||
#undef silk_SMLABB
|
||||
static inline opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULBT
|
||||
static inline opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){
|
||||
opus_int32 ret;
|
||||
ops_count += 4;
|
||||
ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLABT
|
||||
static inline opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULTT
|
||||
static inline opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = (a32 >> 16) * (b32 >> 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLATT
|
||||
static inline opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a32 + (b32 >> 16) * (c32 >> 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
|
||||
#undef silk_MLA_ovflw
|
||||
#define silk_MLA_ovflw silk_MLA
|
||||
|
||||
#undef silk_SMLABB_ovflw
|
||||
#define silk_SMLABB_ovflw silk_SMLABB
|
||||
|
||||
#undef silk_SMLABT_ovflw
|
||||
#define silk_SMLABT_ovflw silk_SMLABT
|
||||
|
||||
#undef silk_SMLATT_ovflw
|
||||
#define silk_SMLATT_ovflw silk_SMLATT
|
||||
|
||||
#undef silk_SMLAWB_ovflw
|
||||
#define silk_SMLAWB_ovflw silk_SMLAWB
|
||||
|
||||
#undef silk_SMLAWT_ovflw
|
||||
#define silk_SMLAWT_ovflw silk_SMLAWT
|
||||
|
||||
#undef silk_SMULL
|
||||
static inline opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){
|
||||
opus_int64 ret;
|
||||
ops_count += 8;
|
||||
ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLAL
|
||||
static inline opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){
|
||||
opus_int64 ret;
|
||||
ops_count += 8;
|
||||
ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32));
|
||||
return ret;
|
||||
}
|
||||
#undef silk_SMLALBB
|
||||
static inline opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){
|
||||
opus_int64 ret;
|
||||
ops_count += 4;
|
||||
ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef SigProcFIX_CLZ16
|
||||
static inline opus_int32 SigProcFIX_CLZ16(opus_int16 in16)
|
||||
{
|
||||
opus_int32 out32 = 0;
|
||||
ops_count += 10;
|
||||
if( in16 == 0 ) {
|
||||
return 16;
|
||||
}
|
||||
/* test nibbles */
|
||||
if( in16 & 0xFF00 ) {
|
||||
if( in16 & 0xF000 ) {
|
||||
in16 >>= 12;
|
||||
} else {
|
||||
out32 += 4;
|
||||
in16 >>= 8;
|
||||
}
|
||||
} else {
|
||||
if( in16 & 0xFFF0 ) {
|
||||
out32 += 8;
|
||||
in16 >>= 4;
|
||||
} else {
|
||||
out32 += 12;
|
||||
}
|
||||
}
|
||||
/* test bits and return */
|
||||
if( in16 & 0xC ) {
|
||||
if( in16 & 0x8 )
|
||||
return out32 + 0;
|
||||
else
|
||||
return out32 + 1;
|
||||
} else {
|
||||
if( in16 & 0xE )
|
||||
return out32 + 2;
|
||||
else
|
||||
return out32 + 3;
|
||||
}
|
||||
}
|
||||
|
||||
#undef SigProcFIX_CLZ32
|
||||
static inline opus_int32 SigProcFIX_CLZ32(opus_int32 in32)
|
||||
{
|
||||
/* test highest 16 bits and convert to opus_int16 */
|
||||
ops_count += 2;
|
||||
if( in32 & 0xFFFF0000 ) {
|
||||
return SigProcFIX_CLZ16((opus_int16)(in32 >> 16));
|
||||
} else {
|
||||
return SigProcFIX_CLZ16((opus_int16)in32) + 16;
|
||||
}
|
||||
}
|
||||
|
||||
#undef silk_DIV32
|
||||
static inline opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
|
||||
ops_count += 64;
|
||||
return a32 / b32;
|
||||
}
|
||||
|
||||
#undef silk_DIV32_16
|
||||
static inline opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
|
||||
ops_count += 32;
|
||||
return a32 / b32;
|
||||
}
|
||||
|
||||
#undef silk_SAT8
|
||||
static inline opus_int8 silk_SAT8(opus_int64 a){
|
||||
opus_int8 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX : \
|
||||
((a) < silk_int8_MIN ? silk_int8_MIN : (a)));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_SAT16
|
||||
static inline opus_int16 silk_SAT16(opus_int64 a){
|
||||
opus_int16 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX : \
|
||||
((a) < silk_int16_MIN ? silk_int16_MIN : (a)));
|
||||
return(tmp);
|
||||
}
|
||||
#undef silk_SAT32
|
||||
static inline opus_int32 silk_SAT32(opus_int64 a){
|
||||
opus_int32 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : \
|
||||
((a) < silk_int32_MIN ? silk_int32_MIN : (a)));
|
||||
return(tmp);
|
||||
}
|
||||
#undef silk_POS_SAT32
|
||||
static inline opus_int32 silk_POS_SAT32(opus_int64 a){
|
||||
opus_int32 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_ADD_POS_SAT8
|
||||
static inline opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){
|
||||
opus_int8 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)));
|
||||
return(tmp);
|
||||
}
|
||||
#undef silk_ADD_POS_SAT16
|
||||
static inline opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){
|
||||
opus_int16 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_ADD_POS_SAT32
|
||||
static inline opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
|
||||
opus_int32 tmp;
|
||||
ops_count += 1;
|
||||
tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_ADD_POS_SAT64
|
||||
static inline opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
|
||||
opus_int64 tmp;
|
||||
ops_count += 1;
|
||||
tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT8
|
||||
static inline opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
|
||||
opus_int8 ret;
|
||||
ops_count += 1;
|
||||
ret = a << shift;
|
||||
return ret;
|
||||
}
|
||||
#undef silk_LSHIFT16
|
||||
static inline opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
|
||||
opus_int16 ret;
|
||||
ops_count += 1;
|
||||
ret = a << shift;
|
||||
return ret;
|
||||
}
|
||||
#undef silk_LSHIFT32
|
||||
static inline opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a << shift;
|
||||
return ret;
|
||||
}
|
||||
#undef silk_LSHIFT64
|
||||
static inline opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
|
||||
ops_count += 1;
|
||||
return a << shift;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT_ovflw
|
||||
static inline opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
|
||||
ops_count += 1;
|
||||
return a << shift;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT_uint
|
||||
static inline opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
|
||||
opus_uint32 ret;
|
||||
ops_count += 1;
|
||||
ret = a << shift;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT8
|
||||
static inline opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
|
||||
ops_count += 1;
|
||||
return a >> shift;
|
||||
}
|
||||
#undef silk_RSHIFT16
|
||||
static inline opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
|
||||
ops_count += 1;
|
||||
return a >> shift;
|
||||
}
|
||||
#undef silk_RSHIFT32
|
||||
static inline opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
|
||||
ops_count += 1;
|
||||
return a >> shift;
|
||||
}
|
||||
#undef silk_RSHIFT64
|
||||
static inline opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
|
||||
ops_count += 1;
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_uint
|
||||
static inline opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
|
||||
ops_count += 1;
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_ADD_LSHIFT
|
||||
static inline opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b << shift);
|
||||
return ret; /* shift >= 0*/
|
||||
}
|
||||
#undef silk_ADD_LSHIFT32
|
||||
static inline opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b << shift);
|
||||
return ret; /* shift >= 0*/
|
||||
}
|
||||
#undef silk_ADD_LSHIFT_uint
|
||||
static inline opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
|
||||
opus_uint32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b << shift);
|
||||
return ret; /* shift >= 0*/
|
||||
}
|
||||
#undef silk_ADD_RSHIFT
|
||||
static inline opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b >> shift);
|
||||
return ret; /* shift > 0*/
|
||||
}
|
||||
#undef silk_ADD_RSHIFT32
|
||||
static inline opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b >> shift);
|
||||
return ret; /* shift > 0*/
|
||||
}
|
||||
#undef silk_ADD_RSHIFT_uint
|
||||
static inline opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
|
||||
opus_uint32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + (b >> shift);
|
||||
return ret; /* shift > 0*/
|
||||
}
|
||||
#undef silk_SUB_LSHIFT32
|
||||
static inline opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a - (b << shift);
|
||||
return ret; /* shift >= 0*/
|
||||
}
|
||||
#undef silk_SUB_RSHIFT32
|
||||
static inline opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a - (b >> shift);
|
||||
return ret; /* shift > 0*/
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_ROUND
|
||||
static inline opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
|
||||
opus_int32 ret;
|
||||
ops_count += 3;
|
||||
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_ROUND64
|
||||
static inline opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
|
||||
opus_int64 ret;
|
||||
ops_count += 6;
|
||||
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_abs_int64
|
||||
static inline opus_int64 silk_abs_int64(opus_int64 a){
|
||||
ops_count += 1;
|
||||
return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/
|
||||
}
|
||||
|
||||
#undef silk_abs_int32
|
||||
static inline opus_int32 silk_abs_int32(opus_int32 a){
|
||||
ops_count += 1;
|
||||
return silk_abs(a);
|
||||
}
|
||||
|
||||
|
||||
#undef silk_min
|
||||
static silk_min(a, b){
|
||||
ops_count += 1;
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_max
|
||||
static silk_max(a, b){
|
||||
ops_count += 1;
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_sign
|
||||
static silk_sign(a){
|
||||
ops_count += 1;
|
||||
return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ));
|
||||
}
|
||||
|
||||
#undef silk_ADD16
|
||||
static inline opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
|
||||
opus_int16 ret;
|
||||
ops_count += 1;
|
||||
ret = a + b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD32
|
||||
static inline opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a + b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD64
|
||||
static inline opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
|
||||
opus_int64 ret;
|
||||
ops_count += 2;
|
||||
ret = a + b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB16
|
||||
static inline opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
|
||||
opus_int16 ret;
|
||||
ops_count += 1;
|
||||
ret = a - b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB32
|
||||
static inline opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
|
||||
opus_int32 ret;
|
||||
ops_count += 1;
|
||||
ret = a - b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB64
|
||||
static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
|
||||
opus_int64 ret;
|
||||
ops_count += 2;
|
||||
ret = a - b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT16
|
||||
static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
|
||||
opus_int16 res;
|
||||
/* Nb will be counted in AKP_add32 and silk_SAT16*/
|
||||
res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT32
|
||||
static inline opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 res;
|
||||
ops_count += 1;
|
||||
res = ((((a32) + (b32)) & 0x80000000) == 0 ? \
|
||||
((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
|
||||
((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT64
|
||||
static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
|
||||
opus_int64 res;
|
||||
ops_count += 1;
|
||||
res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
|
||||
((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
|
||||
((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT16
|
||||
static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
|
||||
opus_int16 res;
|
||||
silk_assert(0);
|
||||
/* Nb will be counted in sub-macros*/
|
||||
res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT32
|
||||
static inline opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
|
||||
opus_int32 res;
|
||||
ops_count += 1;
|
||||
res = ((((a32)-(b32)) & 0x80000000) == 0 ? \
|
||||
(( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
|
||||
((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT64
|
||||
static inline opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
|
||||
opus_int64 res;
|
||||
ops_count += 1;
|
||||
res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
|
||||
(( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
|
||||
((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SMULWW
|
||||
static inline opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
|
||||
opus_int32 ret;
|
||||
/* Nb will be counted in sub-macros*/
|
||||
ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLAWW
|
||||
static inline opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
|
||||
opus_int32 ret;
|
||||
/* Nb will be counted in sub-macros*/
|
||||
ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_min_int
|
||||
static inline opus_int silk_min_int(opus_int a, opus_int b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
#undef silk_min_16
|
||||
static inline opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_min_32
|
||||
static inline opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_min_64
|
||||
static inline opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
/* silk_min() versions with typecast in the function call */
|
||||
#undef silk_max_int
|
||||
static inline opus_int silk_max_int(opus_int a, opus_int b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_max_16
|
||||
static inline opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
#undef silk_max_32
|
||||
static inline opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
#undef silk_max_64
|
||||
static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
|
||||
{
|
||||
ops_count += 1;
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
|
||||
#undef silk_LIMIT_int
|
||||
static inline opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2)
|
||||
{
|
||||
opus_int ret;
|
||||
ops_count += 6;
|
||||
|
||||
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
|
||||
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#undef silk_LIMIT_16
|
||||
static inline opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2)
|
||||
{
|
||||
opus_int16 ret;
|
||||
ops_count += 6;
|
||||
|
||||
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
|
||||
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
#undef silk_LIMIT_32
|
||||
static inline opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
|
||||
{
|
||||
opus_int32 ret;
|
||||
ops_count += 6;
|
||||
|
||||
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
|
||||
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#else
|
||||
#define varDefine
|
||||
#define silk_SaveCount()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,952 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Copyright (C) 2012 Xiph.Org Foundation
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef MACRO_DEBUG_H
|
||||
#define MACRO_DEBUG_H
|
||||
|
||||
/* Redefine macro functions with extensive assertion in DEBUG mode.
|
||||
As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
|
||||
|
||||
#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT)
|
||||
|
||||
#undef silk_ADD16
|
||||
#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){
|
||||
opus_int16 ret;
|
||||
|
||||
ret = a + b;
|
||||
if ( ret != silk_ADD_SAT16( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD32
|
||||
#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){
|
||||
opus_int32 ret;
|
||||
|
||||
ret = a + b;
|
||||
if ( ret != silk_ADD_SAT32( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD64
|
||||
#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){
|
||||
opus_int64 ret;
|
||||
|
||||
ret = a + b;
|
||||
if ( ret != silk_ADD_SAT64( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB16
|
||||
#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){
|
||||
opus_int16 ret;
|
||||
|
||||
ret = a - b;
|
||||
if ( ret != silk_SUB_SAT16( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB32
|
||||
#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){
|
||||
opus_int32 ret;
|
||||
|
||||
ret = a - b;
|
||||
if ( ret != silk_SUB_SAT32( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SUB64
|
||||
#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){
|
||||
opus_int64 ret;
|
||||
|
||||
ret = a - b;
|
||||
if ( ret != silk_SUB_SAT64( a, b ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT16
|
||||
#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) {
|
||||
opus_int16 res;
|
||||
res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
|
||||
if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT32
|
||||
#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
opus_int32 res;
|
||||
res = ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ? \
|
||||
((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
|
||||
((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
|
||||
if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_ADD_SAT64
|
||||
#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) {
|
||||
opus_int64 res;
|
||||
int fail = 0;
|
||||
res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
|
||||
((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
|
||||
((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
|
||||
if( res != a64 + b64 ) {
|
||||
/* Check that we saturated to the correct extreme value */
|
||||
if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
|
||||
( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) )
|
||||
{
|
||||
fail = 1;
|
||||
}
|
||||
} else {
|
||||
/* Saturation not necessary */
|
||||
fail = res != a64 + b64;
|
||||
}
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT16
|
||||
#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) {
|
||||
opus_int16 res;
|
||||
res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
|
||||
if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT32
|
||||
#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) {
|
||||
opus_int32 res;
|
||||
res = ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ? \
|
||||
(( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
|
||||
((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
|
||||
if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_SUB_SAT64
|
||||
#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) {
|
||||
opus_int64 res;
|
||||
int fail = 0;
|
||||
res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
|
||||
(( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
|
||||
((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
|
||||
if( res != a64 - b64 ) {
|
||||
/* Check that we saturated to the correct extreme value */
|
||||
if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
|
||||
( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ))
|
||||
{
|
||||
fail = 1;
|
||||
}
|
||||
} else {
|
||||
/* Saturation not necessary */
|
||||
fail = res != a64 - b64;
|
||||
}
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef silk_MUL
|
||||
#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
opus_int64 ret64;
|
||||
ret = a32 * b32;
|
||||
ret64 = (opus_int64)a32 * (opus_int64)b32;
|
||||
if ( (opus_int64)ret != ret64 )
|
||||
{
|
||||
fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_MUL_uint
|
||||
#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){
|
||||
opus_uint32 ret;
|
||||
ret = a32 * b32;
|
||||
if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 )
|
||||
{
|
||||
fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_MLA
|
||||
#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a32 + b32 * c32;
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
|
||||
{
|
||||
fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_MLA_uint
|
||||
#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){
|
||||
opus_uint32 ret;
|
||||
ret = a32 + b32 * c32;
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
|
||||
{
|
||||
fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULWB
|
||||
#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
|
||||
if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 )
|
||||
{
|
||||
fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLAWB
|
||||
#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = silk_ADD32( a32, silk_SMULWB( b32, c32 ) );
|
||||
if ( silk_ADD32( a32, silk_SMULWB( b32, c32 ) ) != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULWT
|
||||
#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
|
||||
if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 )
|
||||
{
|
||||
fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLAWT
|
||||
#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULL
|
||||
#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){
|
||||
opus_int64 ret64;
|
||||
int fail = 0;
|
||||
ret64 = a64 * b64;
|
||||
if( b64 != 0 ) {
|
||||
fail = a64 != (ret64 / b64);
|
||||
} else if( a64 != 0 ) {
|
||||
fail = b64 != (ret64 / a64);
|
||||
}
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret64;
|
||||
}
|
||||
|
||||
/* no checking needed for silk_SMULBB */
|
||||
#undef silk_SMLABB
|
||||
#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* no checking needed for silk_SMULBT */
|
||||
#undef silk_SMLABT
|
||||
#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* no checking needed for silk_SMULTT */
|
||||
#undef silk_SMLATT
|
||||
#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a32 + (b32 >> 16) * (c32 >> 16);
|
||||
if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMULWW
|
||||
#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
opus_int32 ret, tmp1, tmp2;
|
||||
opus_int64 ret64;
|
||||
int fail = 0;
|
||||
|
||||
ret = silk_SMULWB( a32, b32 );
|
||||
tmp1 = silk_RSHIFT_ROUND( b32, 16 );
|
||||
tmp2 = silk_MUL( a32, tmp1 );
|
||||
|
||||
fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1;
|
||||
|
||||
tmp1 = ret;
|
||||
ret = silk_ADD32( tmp1, tmp2 );
|
||||
fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 );
|
||||
|
||||
ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
|
||||
fail |= (opus_int64)ret != ret64;
|
||||
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_SMLAWW
|
||||
#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
|
||||
opus_int32 ret, tmp;
|
||||
|
||||
tmp = silk_SMULWW( b32, c32 );
|
||||
ret = silk_ADD32( a32, tmp );
|
||||
if ( ret != silk_ADD_SAT32( a32, tmp ) )
|
||||
{
|
||||
fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
|
||||
#undef silk_MLA_ovflw
|
||||
#define silk_MLA_ovflw(a32, b32, c32) ((a32) + ((b32) * (c32)))
|
||||
#undef silk_SMLABB_ovflw
|
||||
#define silk_SMLABB_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
|
||||
|
||||
/* no checking needed for silk_SMULL
|
||||
no checking needed for silk_SMLAL
|
||||
no checking needed for silk_SMLALBB
|
||||
no checking needed for SigProcFIX_CLZ16
|
||||
no checking needed for SigProcFIX_CLZ32*/
|
||||
|
||||
#undef silk_DIV32
|
||||
#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
if ( b32 == 0 )
|
||||
{
|
||||
fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a32 / b32;
|
||||
}
|
||||
|
||||
#undef silk_DIV32_16
|
||||
#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){
|
||||
int fail = 0;
|
||||
fail |= b32 == 0;
|
||||
fail |= b32 > silk_int16_MAX;
|
||||
fail |= b32 < silk_int16_MIN;
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a32 / b32;
|
||||
}
|
||||
|
||||
/* no checking needed for silk_SAT8
|
||||
no checking needed for silk_SAT16
|
||||
no checking needed for silk_SAT32
|
||||
no checking needed for silk_POS_SAT32
|
||||
no checking needed for silk_ADD_POS_SAT8
|
||||
no checking needed for silk_ADD_POS_SAT16
|
||||
no checking needed for silk_ADD_POS_SAT32
|
||||
no checking needed for silk_ADD_POS_SAT64 */
|
||||
|
||||
#undef silk_LSHIFT8
|
||||
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
|
||||
opus_int8 ret;
|
||||
int fail = 0;
|
||||
ret = a << shift;
|
||||
fail |= shift < 0;
|
||||
fail |= shift >= 8;
|
||||
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT16
|
||||
#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
|
||||
opus_int16 ret;
|
||||
int fail = 0;
|
||||
ret = a << shift;
|
||||
fail |= shift < 0;
|
||||
fail |= shift >= 16;
|
||||
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT32
|
||||
#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
int fail = 0;
|
||||
ret = a << shift;
|
||||
fail |= shift < 0;
|
||||
fail |= shift >= 32;
|
||||
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT64
|
||||
#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){
|
||||
opus_int64 ret;
|
||||
int fail = 0;
|
||||
ret = a << shift;
|
||||
fail |= shift < 0;
|
||||
fail |= shift >= 64;
|
||||
fail |= (ret>>shift) != ((opus_int64)a);
|
||||
if ( fail )
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT_ovflw
|
||||
#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a << shift;
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT_uint
|
||||
#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
|
||||
opus_uint32 ret;
|
||||
ret = a << shift;
|
||||
if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift))
|
||||
{
|
||||
fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT8
|
||||
#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift>=8) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT16
|
||||
#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift>=16) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT32
|
||||
#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift>=32) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT64
|
||||
#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift>=64) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_uint
|
||||
#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
|
||||
if ( (shift < 0) || (shift>32) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
#undef silk_ADD_LSHIFT
|
||||
#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){
|
||||
opus_int16 ret;
|
||||
ret = a + (b << shift);
|
||||
if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift >= 0 */
|
||||
}
|
||||
|
||||
#undef silk_ADD_LSHIFT32
|
||||
#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a + (b << shift);
|
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift >= 0 */
|
||||
}
|
||||
|
||||
#undef silk_ADD_LSHIFT_uint
|
||||
#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
|
||||
opus_uint32 ret;
|
||||
ret = a + (b << shift);
|
||||
if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift >= 0 */
|
||||
}
|
||||
|
||||
#undef silk_ADD_RSHIFT
|
||||
#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){
|
||||
opus_int16 ret;
|
||||
ret = a + (b >> shift);
|
||||
if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift > 0 */
|
||||
}
|
||||
|
||||
#undef silk_ADD_RSHIFT32
|
||||
#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a + (b >> shift);
|
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift > 0 */
|
||||
}
|
||||
|
||||
#undef silk_ADD_RSHIFT_uint
|
||||
#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
|
||||
opus_uint32 ret;
|
||||
ret = a + (b >> shift);
|
||||
if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift > 0 */
|
||||
}
|
||||
|
||||
#undef silk_SUB_LSHIFT32
|
||||
#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a - (b << shift);
|
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) << shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift >= 0 */
|
||||
}
|
||||
|
||||
#undef silk_SUB_RSHIFT32
|
||||
#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = a - (b >> shift);
|
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) )
|
||||
{
|
||||
fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret; /* shift > 0 */
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_ROUND
|
||||
#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){
|
||||
opus_int32 ret;
|
||||
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
|
||||
/* the marco definition can't handle a shift of zero */
|
||||
if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef silk_RSHIFT_ROUND64
|
||||
#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){
|
||||
opus_int64 ret;
|
||||
/* the marco definition can't handle a shift of zero */
|
||||
if ( (shift <= 0) || (shift>=64) )
|
||||
{
|
||||
fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* silk_abs is used on floats also, so doesn't work... */
|
||||
/*#undef silk_abs
|
||||
static inline opus_int32 silk_abs(opus_int32 a){
|
||||
silk_assert(a != 0x80000000);
|
||||
return (((a) > 0) ? (a) : -(a)); // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
|
||||
}*/
|
||||
|
||||
#undef silk_abs_int64
|
||||
#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__)
|
||||
static inline opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){
|
||||
if ( a == silk_int64_MIN )
|
||||
{
|
||||
fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
|
||||
}
|
||||
|
||||
#undef silk_abs_int32
|
||||
#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){
|
||||
if ( a == silk_int32_MIN )
|
||||
{
|
||||
fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return silk_abs(a);
|
||||
}
|
||||
|
||||
#undef silk_CHECK_FIT8
|
||||
#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__)
|
||||
static inline opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){
|
||||
opus_int8 ret;
|
||||
ret = (opus_int8)a;
|
||||
if ( (opus_int64)ret != a )
|
||||
{
|
||||
fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#undef silk_CHECK_FIT16
|
||||
#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__)
|
||||
static inline opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){
|
||||
opus_int16 ret;
|
||||
ret = (opus_int16)a;
|
||||
if ( (opus_int64)ret != a )
|
||||
{
|
||||
fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#undef silk_CHECK_FIT32
|
||||
#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__)
|
||||
static inline opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){
|
||||
opus_int32 ret;
|
||||
ret = (opus_int32)a;
|
||||
if ( (opus_int64)ret != a )
|
||||
{
|
||||
fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line);
|
||||
#ifdef FIXED_DEBUG_ASSERT
|
||||
silk_assert( 0 );
|
||||
#endif
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* no checking for silk_NSHIFT_MUL_32_32
|
||||
no checking for silk_NSHIFT_MUL_16_16
|
||||
no checking needed for silk_min
|
||||
no checking needed for silk_max
|
||||
no checking needed for silk_sign
|
||||
*/
|
||||
|
||||
#endif
|
||||
#endif /* MACRO_DEBUG_H */
|
|
@ -0,0 +1,178 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* conversion between prediction filter coefficients and LSFs */
|
||||
/* order should be even */
|
||||
/* a piecewise linear approximation maps LSF <-> cos(LSF) */
|
||||
/* therefore the result is not accurate LSFs, but the two */
|
||||
/* functions are accurate inverses of each other */
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
#include "tables.h"
|
||||
|
||||
#define QA 16
|
||||
|
||||
/* helper function for NLSF2A(..) */
|
||||
static inline void silk_NLSF2A_find_poly(
|
||||
opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */
|
||||
const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */
|
||||
opus_int dd /* I polynomial order (= 1/2 * filter order) */
|
||||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
opus_int32 ftmp;
|
||||
|
||||
out[0] = silk_LSHIFT( 1, QA );
|
||||
out[1] = -cLSF[0];
|
||||
for( k = 1; k < dd; k++ ) {
|
||||
ftmp = cLSF[2*k]; /* QA*/
|
||||
out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
|
||||
for( n = k; n > 1; n-- ) {
|
||||
out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
|
||||
}
|
||||
out[1] -= ftmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute whitening filter coefficients from normalized line spectral frequencies */
|
||||
void silk_NLSF2A(
|
||||
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
|
||||
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
|
||||
const opus_int d /* I filter order (should be even) */
|
||||
)
|
||||
{
|
||||
/* This ordering was found to maximize quality. It improves numerical accuracy of
|
||||
silk_NLSF2A_find_poly() compared to "standard" ordering. */
|
||||
static const unsigned char ordering16[16] = {
|
||||
0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
|
||||
};
|
||||
static const unsigned char ordering10[10] = {
|
||||
0, 9, 6, 3, 4, 5, 8, 1, 2, 7
|
||||
};
|
||||
const unsigned char *ordering;
|
||||
opus_int k, i, dd;
|
||||
opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
|
||||
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
|
||||
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 maxabs, absval, idx=0, sc_Q16;
|
||||
|
||||
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
|
||||
silk_assert( d==10||d==16 );
|
||||
|
||||
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
|
||||
ordering = d == 16 ? ordering16 : ordering10;
|
||||
for( k = 0; k < d; k++ ) {
|
||||
silk_assert(NLSF[k] >= 0 );
|
||||
|
||||
/* f_int on a scale 0-127 (rounded down) */
|
||||
f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
|
||||
|
||||
/* f_frac, range: 0..255 */
|
||||
f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
|
||||
|
||||
silk_assert(f_int >= 0);
|
||||
silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
|
||||
|
||||
/* Read start and end value from table */
|
||||
cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */
|
||||
delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */
|
||||
|
||||
/* Linear interpolation */
|
||||
cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
|
||||
}
|
||||
|
||||
dd = silk_RSHIFT( d, 1 );
|
||||
|
||||
/* generate even and odd polynomials using convolution */
|
||||
silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
|
||||
silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
|
||||
|
||||
/* convert even and odd polynomials to opus_int32 Q12 filter coefs */
|
||||
for( k = 0; k < dd; k++ ) {
|
||||
Ptmp = P[ k+1 ] + P[ k ];
|
||||
Qtmp = Q[ k+1 ] - Q[ k ];
|
||||
|
||||
/* the Ptmp and Qtmp values at this stage need to fit in int32 */
|
||||
a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */
|
||||
a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
|
||||
}
|
||||
|
||||
/* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
|
||||
for( i = 0; i < 10; i++ ) {
|
||||
/* Find maximum absolute value and its index */
|
||||
maxabs = 0;
|
||||
for( k = 0; k < d; k++ ) {
|
||||
absval = silk_abs( a32_QA1[k] );
|
||||
if( absval > maxabs ) {
|
||||
maxabs = absval;
|
||||
idx = k;
|
||||
}
|
||||
}
|
||||
maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
|
||||
if( maxabs > silk_int16_MAX ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
|
||||
sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
|
||||
silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
|
||||
silk_bwexpander_32( a32_QA1, d, sc_Q16 );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 10 ) {
|
||||
/* Reached the last iteration, clip the coefficients */
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
|
||||
a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
|
||||
}
|
||||
} else {
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
|
||||
if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
|
||||
/* on the unscaled coefficients, convert to Q12 and measure again */
|
||||
silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
|
||||
void silk_NLSF_VQ(
|
||||
opus_int32 err_Q26[], /* O Quantization errors [K] */
|
||||
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
|
||||
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
|
||||
const opus_int K, /* I Number of codebook vectors */
|
||||
const opus_int LPC_order /* I Number of LPCs */
|
||||
)
|
||||
{
|
||||
opus_int i, m;
|
||||
opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26;
|
||||
|
||||
silk_assert( LPC_order <= 16 );
|
||||
silk_assert( ( LPC_order & 1 ) == 0 );
|
||||
|
||||
/* Loop over codebook */
|
||||
for( i = 0; i < K; i++ ) {
|
||||
sum_error_Q26 = 0;
|
||||
for( m = 0; m < LPC_order; m += 2 ) {
|
||||
/* Compute weighted squared quantization error for index m */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
|
||||
|
||||
/* Compute weighted squared quantization error for index m + 1 */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
|
||||
|
||||
sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );
|
||||
|
||||
silk_assert( sum_error_Q26 >= 0 );
|
||||
silk_assert( sum_error_Q30 >= 0 );
|
||||
}
|
||||
err_Q26[ i ] = sum_error_Q26;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "define.h"
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/*
|
||||
R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
|
||||
Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
|
||||
Signal Processing, pp. 641-644, 1991.
|
||||
*/
|
||||
|
||||
/* Laroia low complexity NLSF weights */
|
||||
void silk_NLSF_VQ_weights_laroia(
|
||||
opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
|
||||
const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
|
||||
const opus_int D /* I Input vector dimension (even) */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 tmp1_int, tmp2_int;
|
||||
|
||||
silk_assert( D > 0 );
|
||||
silk_assert( ( D & 1 ) == 0 );
|
||||
|
||||
/* First value */
|
||||
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
|
||||
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
|
||||
tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
|
||||
tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
|
||||
pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
|
||||
silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 );
|
||||
|
||||
/* Main loop */
|
||||
for( k = 1; k < D - 1; k += 2 ) {
|
||||
tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
|
||||
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
|
||||
pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
|
||||
silk_assert( pNLSFW_Q_OUT[ k ] > 0 );
|
||||
|
||||
tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
|
||||
tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
|
||||
pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
|
||||
silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 );
|
||||
}
|
||||
|
||||
/* Last value */
|
||||
tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
|
||||
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
|
||||
pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
|
||||
silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 );
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Predictive dequantizer for NLSF residuals */
|
||||
static inline void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
|
||||
opus_int16 x_Q10[], /* O Output [ order ] */
|
||||
const opus_int8 indices[], /* I Quantization indices [ order ] */
|
||||
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
|
||||
const opus_int quant_step_size_Q16, /* I Quantization step size */
|
||||
const opus_int16 order /* I Number of input values */
|
||||
)
|
||||
{
|
||||
opus_int i, out_Q10, pred_Q10;
|
||||
|
||||
out_Q10 = 0;
|
||||
for( i = order-1; i >= 0; i-- ) {
|
||||
pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 );
|
||||
out_Q10 = silk_LSHIFT( indices[ i ], 10 );
|
||||
if( out_Q10 > 0 ) {
|
||||
out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
} else if( out_Q10 < 0 ) {
|
||||
out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
}
|
||||
out_Q10 = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 );
|
||||
x_Q10[ i ] = out_Q10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* NLSF vector decoder */
|
||||
/***********************/
|
||||
void silk_NLSF_decode(
|
||||
opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */
|
||||
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
|
||||
const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
opus_int16 res_Q10[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
|
||||
opus_int32 W_tmp_Q9, NLSF_Q15_tmp;
|
||||
const opus_uint8 *pCB_element;
|
||||
|
||||
/* Decode first stage */
|
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 );
|
||||
}
|
||||
|
||||
/* Unpack entropy table indices and predictor for current CB1 index */
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
|
||||
|
||||
/* Predictive residual dequantizer */
|
||||
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
|
||||
|
||||
/* Weights from codebook vector */
|
||||
silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order );
|
||||
|
||||
/* Apply inverse square-rooted weights and add to output */
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
|
||||
NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
|
||||
pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
|
||||
}
|
||||
|
||||
/* NLSF stabilization */
|
||||
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Delayed-decision quantizer for NLSF residuals */
|
||||
opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */
|
||||
opus_int8 indices[], /* O Quantization indices [ order ] */
|
||||
const opus_int16 x_Q10[], /* I Input [ order ] */
|
||||
const opus_int16 w_Q5[], /* I Weights [ order ] */
|
||||
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
|
||||
const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */
|
||||
const opus_uint8 ec_rates_Q5[], /* I Rates [] */
|
||||
const opus_int quant_step_size_Q16, /* I Quantization step size */
|
||||
const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */
|
||||
const opus_int32 mu_Q20, /* I R/D tradeoff */
|
||||
const opus_int16 order /* I Number of input values */
|
||||
)
|
||||
{
|
||||
opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10;
|
||||
opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5;
|
||||
opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16;
|
||||
opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ];
|
||||
opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ];
|
||||
opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
|
||||
opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
|
||||
opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ];
|
||||
opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ];
|
||||
const opus_uint8 *rates_Q5;
|
||||
|
||||
silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */
|
||||
|
||||
nStates = 1;
|
||||
RD_Q25[ 0 ] = 0;
|
||||
prev_out_Q10[ 0 ] = 0;
|
||||
for( i = order - 1; ; i-- ) {
|
||||
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
|
||||
pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 );
|
||||
in_Q10 = x_Q10[ i ];
|
||||
for( j = 0; j < nStates; j++ ) {
|
||||
pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] );
|
||||
res_Q10 = silk_SUB16( in_Q10, pred_Q10 );
|
||||
ind_tmp = silk_SMULWB( (opus_int32)inv_quant_step_size_Q6, res_Q10 );
|
||||
ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 );
|
||||
ind[ j ][ i ] = (opus_int8)ind_tmp;
|
||||
|
||||
/* compute outputs for ind_tmp and ind_tmp + 1 */
|
||||
out0_Q10 = silk_LSHIFT( ind_tmp, 10 );
|
||||
out1_Q10 = silk_ADD16( out0_Q10, 1024 );
|
||||
if( ind_tmp > 0 ) {
|
||||
out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
} else if( ind_tmp == 0 ) {
|
||||
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
} else if( ind_tmp == -1 ) {
|
||||
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
} else {
|
||||
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
|
||||
}
|
||||
out0_Q10 = silk_SMULWB( (opus_int32)out0_Q10, quant_step_size_Q16 );
|
||||
out1_Q10 = silk_SMULWB( (opus_int32)out1_Q10, quant_step_size_Q16 );
|
||||
out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 );
|
||||
out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 );
|
||||
prev_out_Q10[ j ] = out0_Q10;
|
||||
prev_out_Q10[ j + nStates ] = out1_Q10;
|
||||
|
||||
/* compute RD for ind_tmp and ind_tmp + 1 */
|
||||
if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ];
|
||||
rate1_Q5 = 280;
|
||||
} else {
|
||||
rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp );
|
||||
rate1_Q5 = silk_ADD16( rate0_Q5, 43 );
|
||||
}
|
||||
} else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
rate0_Q5 = 280;
|
||||
rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
|
||||
} else {
|
||||
rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp );
|
||||
rate1_Q5 = silk_SUB16( rate0_Q5, 43 );
|
||||
}
|
||||
} else {
|
||||
rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ];
|
||||
rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
|
||||
}
|
||||
RD_tmp_Q25 = RD_Q25[ j ];
|
||||
diff_Q10 = silk_SUB16( in_Q10, out0_Q10 );
|
||||
RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 );
|
||||
diff_Q10 = silk_SUB16( in_Q10, out1_Q10 );
|
||||
RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
|
||||
}
|
||||
|
||||
if( nStates < NLSF_QUANT_DEL_DEC_STATES ) {
|
||||
/* double number of states and copy */
|
||||
for( j = 0; j < nStates; j++ ) {
|
||||
ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
|
||||
}
|
||||
nStates = silk_LSHIFT( nStates, 1 );
|
||||
for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
ind[ j ][ i ] = ind[ j - nStates ][ i ];
|
||||
}
|
||||
} else if( i > 0 ) {
|
||||
/* sort lower and upper half of RD_Q25, pairwise */
|
||||
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
|
||||
RD_max_Q25[ j ] = RD_Q25[ j ];
|
||||
RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
|
||||
RD_Q25[ j ] = RD_min_Q25[ j ];
|
||||
RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ];
|
||||
/* swap prev_out values */
|
||||
out0_Q10 = prev_out_Q10[ j ];
|
||||
prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ];
|
||||
prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10;
|
||||
ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES;
|
||||
} else {
|
||||
RD_min_Q25[ j ] = RD_Q25[ j ];
|
||||
RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
|
||||
ind_sort[ j ] = j;
|
||||
}
|
||||
}
|
||||
/* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */
|
||||
/* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */
|
||||
while( 1 ) {
|
||||
min_max_Q25 = silk_int32_MAX;
|
||||
max_min_Q25 = 0;
|
||||
ind_min_max = 0;
|
||||
ind_max_min = 0;
|
||||
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
if( min_max_Q25 > RD_max_Q25[ j ] ) {
|
||||
min_max_Q25 = RD_max_Q25[ j ];
|
||||
ind_min_max = j;
|
||||
}
|
||||
if( max_min_Q25 < RD_min_Q25[ j ] ) {
|
||||
max_min_Q25 = RD_min_Q25[ j ];
|
||||
ind_max_min = j;
|
||||
}
|
||||
}
|
||||
if( min_max_Q25 >= max_min_Q25 ) {
|
||||
break;
|
||||
}
|
||||
/* copy ind_min_max to ind_max_min */
|
||||
ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES;
|
||||
RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
|
||||
prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
|
||||
RD_min_Q25[ ind_max_min ] = 0;
|
||||
RD_max_Q25[ ind_min_max ] = silk_int32_MAX;
|
||||
silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) );
|
||||
}
|
||||
/* increment index if it comes from the upper half */
|
||||
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
|
||||
}
|
||||
} else { /* i == 0 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* last sample: find winner, copy indices and return RD value */
|
||||
ind_tmp = 0;
|
||||
min_Q25 = silk_int32_MAX;
|
||||
for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
if( min_Q25 > RD_Q25[ j ] ) {
|
||||
min_Q25 = RD_Q25[ j ];
|
||||
ind_tmp = j;
|
||||
}
|
||||
}
|
||||
for( j = 0; j < order; j++ ) {
|
||||
indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ];
|
||||
silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT );
|
||||
silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT );
|
||||
}
|
||||
indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 );
|
||||
silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT );
|
||||
silk_assert( min_Q25 >= 0 );
|
||||
return min_Q25;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/***********************/
|
||||
/* NLSF vector encoder */
|
||||
/***********************/
|
||||
opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
|
||||
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
|
||||
opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
|
||||
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
|
||||
const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */
|
||||
const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
|
||||
const opus_int nSurvivors, /* I Max survivors after first stage */
|
||||
const opus_int signalType /* I Signal type: 0/1/2 */
|
||||
)
|
||||
{
|
||||
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
|
||||
opus_int32 W_tmp_Q9;
|
||||
opus_int32 err_Q26[ NLSF_VQ_MAX_VECTORS ];
|
||||
opus_int32 RD_Q25[ NLSF_VQ_MAX_SURVIVORS ];
|
||||
opus_int tempIndices1[ NLSF_VQ_MAX_SURVIVORS ];
|
||||
opus_int8 tempIndices2[ NLSF_VQ_MAX_SURVIVORS * MAX_LPC_ORDER ];
|
||||
opus_int16 res_Q15[ MAX_LPC_ORDER ];
|
||||
opus_int16 res_Q10[ MAX_LPC_ORDER ];
|
||||
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
|
||||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
const opus_uint8 *pCB_element, *iCDF_ptr;
|
||||
|
||||
silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
|
||||
silk_assert( signalType >= 0 && signalType <= 2 );
|
||||
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
|
||||
|
||||
/* NLSF stabilization */
|
||||
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
|
||||
|
||||
/* First stage: VQ */
|
||||
silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
|
||||
|
||||
/* Sort the quantization errors */
|
||||
silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
|
||||
|
||||
/* Loop over survivors */
|
||||
for( s = 0; s < nSurvivors; s++ ) {
|
||||
ind1 = tempIndices1[ s ];
|
||||
|
||||
/* Residual after first stage */
|
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
|
||||
res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
|
||||
}
|
||||
|
||||
/* Weights from codebook vector */
|
||||
silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
|
||||
|
||||
/* Apply square-rooted weights */
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
|
||||
res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
|
||||
}
|
||||
|
||||
/* Modify input weights accordingly */
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
|
||||
}
|
||||
|
||||
/* Unpack entropy table indices and predictor for current CB1 index */
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
|
||||
|
||||
/* Trellis quantizer */
|
||||
RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix,
|
||||
psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order );
|
||||
|
||||
/* Add rate for first stage */
|
||||
iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
|
||||
if( ind1 == 0 ) {
|
||||
prob_Q8 = 256 - iCDF_ptr[ ind1 ];
|
||||
} else {
|
||||
prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
|
||||
}
|
||||
bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
|
||||
RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) );
|
||||
}
|
||||
|
||||
/* Find the lowest rate-distortion error */
|
||||
silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 );
|
||||
|
||||
NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ];
|
||||
silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
|
||||
|
||||
/* Decode */
|
||||
silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
|
||||
|
||||
return RD_Q25[ 0 ];
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* NLSF stabilizer: */
|
||||
/* */
|
||||
/* - Moves NLSFs further apart if they are too close */
|
||||
/* - Moves NLSFs away from borders if they are too close */
|
||||
/* - High effort to achieve a modification with minimum */
|
||||
/* Euclidean distance to input vector */
|
||||
/* - Output are sorted NLSF coefficients */
|
||||
/* */
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Constant Definitions */
|
||||
#define MAX_LOOPS 20
|
||||
|
||||
/* NLSF stabilizer, for a single input data vector */
|
||||
void silk_NLSF_stabilize(
|
||||
opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
|
||||
const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
|
||||
const opus_int L /* I Number of NLSF parameters in the input vector */
|
||||
)
|
||||
{
|
||||
opus_int i, I=0, k, loops;
|
||||
opus_int16 center_freq_Q15;
|
||||
opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;
|
||||
|
||||
/* This is necessary to ensure an output within range of a opus_int16 */
|
||||
silk_assert( NDeltaMin_Q15[L] >= 1 );
|
||||
|
||||
for( loops = 0; loops < MAX_LOOPS; loops++ ) {
|
||||
/**************************/
|
||||
/* Find smallest distance */
|
||||
/**************************/
|
||||
/* First element */
|
||||
min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
|
||||
I = 0;
|
||||
/* Middle elements */
|
||||
for( i = 1; i <= L-1; i++ ) {
|
||||
diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
|
||||
if( diff_Q15 < min_diff_Q15 ) {
|
||||
min_diff_Q15 = diff_Q15;
|
||||
I = i;
|
||||
}
|
||||
}
|
||||
/* Last element */
|
||||
diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
|
||||
if( diff_Q15 < min_diff_Q15 ) {
|
||||
min_diff_Q15 = diff_Q15;
|
||||
I = L;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
/* Now check if the smallest distance non-negative */
|
||||
/***************************************************/
|
||||
if( min_diff_Q15 >= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( I == 0 ) {
|
||||
/* Move away from lower limit */
|
||||
NLSF_Q15[0] = NDeltaMin_Q15[0];
|
||||
|
||||
} else if( I == L) {
|
||||
/* Move away from higher limit */
|
||||
NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L];
|
||||
|
||||
} else {
|
||||
/* Find the lower extreme for the location of the current center frequency */
|
||||
min_center_Q15 = 0;
|
||||
for( k = 0; k < I; k++ ) {
|
||||
min_center_Q15 += NDeltaMin_Q15[k];
|
||||
}
|
||||
min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 );
|
||||
|
||||
/* Find the upper extreme for the location of the current center frequency */
|
||||
max_center_Q15 = 1 << 15;
|
||||
for( k = L; k > I; k-- ) {
|
||||
max_center_Q15 -= NDeltaMin_Q15[k];
|
||||
}
|
||||
max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 );
|
||||
|
||||
/* Move apart, sorted by value, keeping the same center frequency */
|
||||
center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ),
|
||||
min_center_Q15, max_center_Q15 );
|
||||
NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 );
|
||||
NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
|
||||
}
|
||||
}
|
||||
|
||||
/* Safe and simple fall back method, which is less ideal than the above */
|
||||
if( loops == MAX_LOOPS )
|
||||
{
|
||||
/* Insertion sort (fast for already almost sorted arrays): */
|
||||
/* Best case: O(n) for an already sorted array */
|
||||
/* Worst case: O(n^2) for an inversely sorted array */
|
||||
silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L );
|
||||
|
||||
/* First NLSF should be no less than NDeltaMin[0] */
|
||||
NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
|
||||
|
||||
/* Keep delta_min distance between the NLSFs */
|
||||
for( i = 1; i < L; i++ )
|
||||
NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
|
||||
|
||||
/* Last NLSF should be no higher than 1 - NDeltaMin[L] */
|
||||
NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
|
||||
|
||||
/* Keep NDeltaMin distance between the NLSFs */
|
||||
for( i = L-2; i >= 0; i-- )
|
||||
NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Unpack predictor values and indices for entropy coding tables */
|
||||
void silk_NLSF_unpack(
|
||||
opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
|
||||
opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
|
||||
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
|
||||
const opus_int CB1_index /* I Index of vector in first LSF codebook */
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_uint8 entry;
|
||||
const opus_uint8 *ec_sel_ptr;
|
||||
|
||||
ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ];
|
||||
for( i = 0; i < psNLSF_CB->order; i += 2 ) {
|
||||
entry = *ec_sel_ptr++;
|
||||
ec_ix [ i ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
|
||||
pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ];
|
||||
ec_ix [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
|
||||
pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,439 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
static inline void silk_nsq_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const opus_int32 x_Q3[], /* I input in Q3 */
|
||||
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
opus_int subfr, /* I subframe number */
|
||||
const opus_int LTP_scale_Q14, /* I */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
|
||||
const opus_int signal_type /* I Signal type */
|
||||
);
|
||||
|
||||
static inline void silk_noise_shape_quantizer(
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
opus_int signalType, /* I Signal type */
|
||||
const opus_int32 x_sc_Q10[], /* I */
|
||||
opus_int8 pulses[], /* O */
|
||||
opus_int16 xq[], /* O */
|
||||
opus_int32 sLTP_Q15[], /* I/O LTP state */
|
||||
const opus_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
const opus_int16 b_Q14[], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
|
||||
opus_int lag, /* I Pitch lag */
|
||||
opus_int32 HarmShapeFIRPacked_Q14, /* I */
|
||||
opus_int Tilt_Q14, /* I Spectral tilt */
|
||||
opus_int32 LF_shp_Q14, /* I */
|
||||
opus_int32 Gain_Q16, /* I */
|
||||
opus_int Lambda_Q10, /* I */
|
||||
opus_int offset_Q10, /* I */
|
||||
opus_int length, /* I Input length */
|
||||
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
|
||||
opus_int predictLPCOrder /* I Prediction filter order */
|
||||
);
|
||||
|
||||
void silk_NSQ(
|
||||
const silk_encoder_state *psEncC, /* I/O Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int32 x_Q3[], /* I Prefiltered input signal */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
)
|
||||
{
|
||||
opus_int k, lag, start_idx, LSF_interpolation_flag;
|
||||
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
|
||||
opus_int16 *pxq;
|
||||
opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
|
||||
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
|
||||
opus_int32 HarmShapeFIRPacked_Q14;
|
||||
opus_int offset_Q10;
|
||||
opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
|
||||
|
||||
NSQ->rand_seed = psIndices->Seed;
|
||||
|
||||
/* Set unvoiced lag to the previous one, overwrite later for voiced */
|
||||
lag = NSQ->lagPrev;
|
||||
|
||||
silk_assert( NSQ->prev_gain_Q16 != 0 );
|
||||
|
||||
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
|
||||
|
||||
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
|
||||
LSF_interpolation_flag = 0;
|
||||
} else {
|
||||
LSF_interpolation_flag = 1;
|
||||
}
|
||||
|
||||
/* Set up pointers to start of sub frame */
|
||||
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
|
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
|
||||
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
|
||||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
|
||||
|
||||
NSQ->rewhite_flag = 0;
|
||||
if( psIndices->signalType == TYPE_VOICED ) {
|
||||
/* Voiced */
|
||||
lag = pitchL[ k ];
|
||||
|
||||
/* Re-whitening */
|
||||
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
|
||||
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
|
||||
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
|
||||
|
||||
NSQ->rewhite_flag = 1;
|
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
|
||||
}
|
||||
}
|
||||
|
||||
silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
|
||||
|
||||
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
|
||||
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
|
||||
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder );
|
||||
|
||||
x_Q3 += psEncC->subfr_length;
|
||||
pulses += psEncC->subfr_length;
|
||||
pxq += psEncC->subfr_length;
|
||||
}
|
||||
|
||||
/* Update lagPrev for next frame */
|
||||
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
|
||||
|
||||
/* Save quantized speech and noise shaping signals */
|
||||
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
|
||||
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
|
||||
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
/* silk_noise_shape_quantizer */
|
||||
/***********************************/
|
||||
static inline void silk_noise_shape_quantizer(
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
opus_int signalType, /* I Signal type */
|
||||
const opus_int32 x_sc_Q10[], /* I */
|
||||
opus_int8 pulses[], /* O */
|
||||
opus_int16 xq[], /* O */
|
||||
opus_int32 sLTP_Q15[], /* I/O LTP state */
|
||||
const opus_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
const opus_int16 b_Q14[], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
|
||||
opus_int lag, /* I Pitch lag */
|
||||
opus_int32 HarmShapeFIRPacked_Q14, /* I */
|
||||
opus_int Tilt_Q14, /* I Spectral tilt */
|
||||
opus_int32 LF_shp_Q14, /* I */
|
||||
opus_int32 Gain_Q16, /* I */
|
||||
opus_int Lambda_Q10, /* I */
|
||||
opus_int offset_Q10, /* I */
|
||||
opus_int length, /* I Input length */
|
||||
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
|
||||
opus_int predictLPCOrder /* I Prediction filter order */
|
||||
)
|
||||
{
|
||||
opus_int i, j;
|
||||
opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
|
||||
opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
|
||||
opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
|
||||
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
|
||||
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
|
||||
|
||||
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
|
||||
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
|
||||
|
||||
/* Set up short term AR state */
|
||||
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
/* Generate dither */
|
||||
NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
|
||||
|
||||
/* Short-term prediction */
|
||||
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q10 = silk_RSHIFT( predictLPCOrder, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ 0 ], a_Q12[ 0 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
|
||||
if( predictLPCOrder == 16 ) {
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
|
||||
}
|
||||
|
||||
/* Long-term prediction */
|
||||
if( signalType == TYPE_VOICED ) {
|
||||
/* Unrolled loop */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LTP_pred_Q13 = 2;
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
|
||||
pred_lag_ptr++;
|
||||
} else {
|
||||
LTP_pred_Q13 = 0;
|
||||
}
|
||||
|
||||
/* Noise shape feedback */
|
||||
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
tmp2 = psLPC_Q14[ 0 ];
|
||||
tmp1 = NSQ->sAR2_Q14[ 0 ];
|
||||
NSQ->sAR2_Q14[ 0 ] = tmp2;
|
||||
n_AR_Q12 = silk_RSHIFT( shapingLPCOrder, 1 );
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ 0 ] );
|
||||
for( j = 2; j < shapingLPCOrder; j += 2 ) {
|
||||
tmp2 = NSQ->sAR2_Q14[ j - 1 ];
|
||||
NSQ->sAR2_Q14[ j - 1 ] = tmp1;
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ j - 1 ] );
|
||||
tmp1 = NSQ->sAR2_Q14[ j + 0 ];
|
||||
NSQ->sAR2_Q14[ j + 0 ] = tmp2;
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ j ] );
|
||||
}
|
||||
NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
|
||||
|
||||
n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
|
||||
|
||||
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
|
||||
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
|
||||
|
||||
silk_assert( lag > 0 || signalType != TYPE_VOICED );
|
||||
|
||||
/* Combine prediction and noise shaping signals */
|
||||
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
|
||||
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
|
||||
if( lag > 0 ) {
|
||||
/* Symmetric, packed FIR coefficients */
|
||||
n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
|
||||
shp_lag_ptr++;
|
||||
|
||||
tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */
|
||||
tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */
|
||||
tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */
|
||||
} else {
|
||||
tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */
|
||||
}
|
||||
|
||||
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
|
||||
|
||||
/* Flip sign depending on dither */
|
||||
if ( NSQ->rand_seed < 0 ) {
|
||||
r_Q10 = -r_Q10;
|
||||
}
|
||||
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
|
||||
|
||||
/* Find two quantization level candidates and measure their rate-distortion */
|
||||
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
|
||||
if( q1_Q0 > 0 ) {
|
||||
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
|
||||
rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
|
||||
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else if( q1_Q0 == 0 ) {
|
||||
q1_Q10 = offset_Q10;
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
|
||||
rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
|
||||
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else if( q1_Q0 == -1 ) {
|
||||
q2_Q10 = offset_Q10;
|
||||
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
|
||||
rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
|
||||
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else { /* Q1_Q0 < -1 */
|
||||
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
|
||||
rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
|
||||
rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
|
||||
}
|
||||
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
|
||||
rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 );
|
||||
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
|
||||
rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 );
|
||||
|
||||
if( rd2_Q20 < rd1_Q20 ) {
|
||||
q1_Q10 = q2_Q10;
|
||||
}
|
||||
|
||||
pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
|
||||
|
||||
/* Excitation */
|
||||
exc_Q14 = silk_LSHIFT( q1_Q10, 4 );
|
||||
if ( NSQ->rand_seed < 0 ) {
|
||||
exc_Q14 = -exc_Q14;
|
||||
}
|
||||
|
||||
/* Add predictions */
|
||||
LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 );
|
||||
xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 );
|
||||
|
||||
/* Scale XQ back to normal level before saving */
|
||||
xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) );
|
||||
|
||||
/* Update states */
|
||||
psLPC_Q14++;
|
||||
*psLPC_Q14 = xq_Q14;
|
||||
sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
|
||||
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
|
||||
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
|
||||
sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
|
||||
NSQ->sLTP_shp_buf_idx++;
|
||||
NSQ->sLTP_buf_idx++;
|
||||
|
||||
/* Make dither dependent on quantized signal */
|
||||
NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] );
|
||||
}
|
||||
|
||||
/* Update LPC synth buffer */
|
||||
silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
|
||||
}
|
||||
|
||||
static inline void silk_nsq_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const opus_int32 x_Q3[], /* I input in Q3 */
|
||||
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
opus_int subfr, /* I subframe number */
|
||||
const opus_int LTP_scale_Q14, /* I */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
|
||||
const opus_int signal_type /* I Signal type */
|
||||
)
|
||||
{
|
||||
opus_int i, lag;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
|
||||
|
||||
lag = pitchL[ subfr ];
|
||||
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
|
||||
silk_assert( inv_gain_Q31 != 0 );
|
||||
|
||||
/* Calculate gain adjustment factor */
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
} else {
|
||||
gain_adj_Q16 = (opus_int32)1 << 16;
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
|
||||
for( i = 0; i < psEncC->subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
if( subfr == 0 ) {
|
||||
/* Do LTP downscaling */
|
||||
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
|
||||
}
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
silk_assert( i < MAX_FRAME_LENGTH );
|
||||
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust for changing gain */
|
||||
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
|
||||
}
|
||||
|
||||
/* Scale long-term prediction state */
|
||||
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
|
||||
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
|
||||
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,705 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
typedef struct {
|
||||
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
|
||||
opus_int32 RandState[ DECISION_DELAY ];
|
||||
opus_int32 Q_Q10[ DECISION_DELAY ];
|
||||
opus_int32 Xq_Q14[ DECISION_DELAY ];
|
||||
opus_int32 Pred_Q15[ DECISION_DELAY ];
|
||||
opus_int32 Shape_Q14[ DECISION_DELAY ];
|
||||
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 LF_AR_Q14;
|
||||
opus_int32 Seed;
|
||||
opus_int32 SeedInit;
|
||||
opus_int32 RD_Q10;
|
||||
} NSQ_del_dec_struct;
|
||||
|
||||
typedef struct {
|
||||
opus_int32 Q_Q10;
|
||||
opus_int32 RD_Q10;
|
||||
opus_int32 xq_Q14;
|
||||
opus_int32 LF_AR_Q14;
|
||||
opus_int32 sLTP_shp_Q14;
|
||||
opus_int32 LPC_exc_Q14;
|
||||
} NSQ_sample_struct;
|
||||
|
||||
static inline void silk_nsq_del_dec_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const opus_int32 x_Q3[], /* I Input in Q3 */
|
||||
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
opus_int subfr, /* I Subframe number */
|
||||
opus_int nStatesDelayedDecision, /* I Number of del dec states */
|
||||
const opus_int LTP_scale_Q14, /* I LTP state scaling */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
|
||||
const opus_int signal_type, /* I Signal type */
|
||||
const opus_int decisionDelay /* I Decision delay */
|
||||
);
|
||||
|
||||
/******************************************/
|
||||
/* Noise shape quantizer for one subframe */
|
||||
/******************************************/
|
||||
static inline void silk_noise_shape_quantizer_del_dec(
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
opus_int signalType, /* I Signal type */
|
||||
const opus_int32 x_Q10[], /* I */
|
||||
opus_int8 pulses[], /* O */
|
||||
opus_int16 xq[], /* O */
|
||||
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
|
||||
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
|
||||
const opus_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
const opus_int16 b_Q14[], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
|
||||
opus_int lag, /* I Pitch lag */
|
||||
opus_int32 HarmShapeFIRPacked_Q14, /* I */
|
||||
opus_int Tilt_Q14, /* I Spectral tilt */
|
||||
opus_int32 LF_shp_Q14, /* I */
|
||||
opus_int32 Gain_Q16, /* I */
|
||||
opus_int Lambda_Q10, /* I */
|
||||
opus_int offset_Q10, /* I */
|
||||
opus_int length, /* I Input length */
|
||||
opus_int subfr, /* I Subframe number */
|
||||
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
|
||||
opus_int predictLPCOrder, /* I Prediction filter order */
|
||||
opus_int warping_Q16, /* I */
|
||||
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
opus_int decisionDelay /* I */
|
||||
);
|
||||
|
||||
void silk_NSQ_del_dec(
|
||||
const silk_encoder_state *psEncC, /* I/O Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int32 x_Q3[], /* I Prefiltered input signal */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
)
|
||||
{
|
||||
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
|
||||
opus_int last_smple_idx, smpl_buf_idx, decisionDelay;
|
||||
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
|
||||
opus_int16 *pxq;
|
||||
opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
|
||||
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
|
||||
opus_int32 HarmShapeFIRPacked_Q14;
|
||||
opus_int offset_Q10;
|
||||
opus_int32 RDmin_Q10, Gain_Q10;
|
||||
opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
|
||||
opus_int32 delayedGain_Q10[ DECISION_DELAY ];
|
||||
NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ];
|
||||
NSQ_del_dec_struct *psDD;
|
||||
|
||||
/* Set unvoiced lag to the previous one, overwrite later for voiced */
|
||||
lag = NSQ->lagPrev;
|
||||
|
||||
silk_assert( NSQ->prev_gain_Q16 != 0 );
|
||||
|
||||
/* Initialize delayed decision states */
|
||||
silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
|
||||
for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
|
||||
psDD = &psDelDec[ k ];
|
||||
psDD->Seed = ( k + psIndices->Seed ) & 3;
|
||||
psDD->SeedInit = psDD->Seed;
|
||||
psDD->RD_Q10 = 0;
|
||||
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
|
||||
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
|
||||
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
|
||||
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
|
||||
}
|
||||
|
||||
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
|
||||
smpl_buf_idx = 0; /* index of oldest samples */
|
||||
|
||||
decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
|
||||
|
||||
/* For voiced frames limit the decision delay to lower than the pitch lag */
|
||||
if( psIndices->signalType == TYPE_VOICED ) {
|
||||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 );
|
||||
}
|
||||
} else {
|
||||
if( lag > 0 ) {
|
||||
decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
|
||||
LSF_interpolation_flag = 0;
|
||||
} else {
|
||||
LSF_interpolation_flag = 1;
|
||||
}
|
||||
|
||||
/* Set up pointers to start of sub frame */
|
||||
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
|
||||
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
|
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
|
||||
subfr = 0;
|
||||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
|
||||
|
||||
NSQ->rewhite_flag = 0;
|
||||
if( psIndices->signalType == TYPE_VOICED ) {
|
||||
/* Voiced */
|
||||
lag = pitchL[ k ];
|
||||
|
||||
/* Re-whitening */
|
||||
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
|
||||
if( k == 2 ) {
|
||||
/* RESET DELAYED DECISIONS */
|
||||
/* Find winner */
|
||||
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
|
||||
Winner_ind = 0;
|
||||
for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
|
||||
if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) {
|
||||
RDmin_Q10 = psDelDec[ i ].RD_Q10;
|
||||
Winner_ind = i;
|
||||
}
|
||||
}
|
||||
for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) {
|
||||
if( i != Winner_ind ) {
|
||||
psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 );
|
||||
silk_assert( psDelDec[ i ].RD_Q10 >= 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy final part of signals from winner state to output and long-term filter states */
|
||||
psDD = &psDelDec[ Winner_ind ];
|
||||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
|
||||
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
|
||||
}
|
||||
|
||||
subfr = 0;
|
||||
}
|
||||
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
|
||||
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
|
||||
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
|
||||
|
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
|
||||
NSQ->rewhite_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
|
||||
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
|
||||
|
||||
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
|
||||
delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
|
||||
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
|
||||
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
|
||||
|
||||
x_Q3 += psEncC->subfr_length;
|
||||
pulses += psEncC->subfr_length;
|
||||
pxq += psEncC->subfr_length;
|
||||
}
|
||||
|
||||
/* Find winner */
|
||||
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
|
||||
Winner_ind = 0;
|
||||
for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
|
||||
if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) {
|
||||
RDmin_Q10 = psDelDec[ k ].RD_Q10;
|
||||
Winner_ind = k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy final part of signals from winner state to output and long-term filter states */
|
||||
psDD = &psDelDec[ Winner_ind ];
|
||||
psIndices->Seed = psDD->SeedInit;
|
||||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
|
||||
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
|
||||
}
|
||||
silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
|
||||
silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
|
||||
|
||||
/* Update states */
|
||||
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
|
||||
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
|
||||
|
||||
/* Save quantized speech signal */
|
||||
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
|
||||
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
|
||||
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
/* Noise shape quantizer for one subframe */
|
||||
/******************************************/
|
||||
static inline void silk_noise_shape_quantizer_del_dec(
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
opus_int signalType, /* I Signal type */
|
||||
const opus_int32 x_Q10[], /* I */
|
||||
opus_int8 pulses[], /* O */
|
||||
opus_int16 xq[], /* O */
|
||||
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
|
||||
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
|
||||
const opus_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
const opus_int16 b_Q14[], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
|
||||
opus_int lag, /* I Pitch lag */
|
||||
opus_int32 HarmShapeFIRPacked_Q14, /* I */
|
||||
opus_int Tilt_Q14, /* I Spectral tilt */
|
||||
opus_int32 LF_shp_Q14, /* I */
|
||||
opus_int32 Gain_Q16, /* I */
|
||||
opus_int Lambda_Q10, /* I */
|
||||
opus_int offset_Q10, /* I */
|
||||
opus_int length, /* I Input length */
|
||||
opus_int subfr, /* I Subframe number */
|
||||
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
|
||||
opus_int predictLPCOrder, /* I Prediction filter order */
|
||||
opus_int warping_Q16, /* I */
|
||||
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
opus_int decisionDelay /* I */
|
||||
)
|
||||
{
|
||||
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
|
||||
opus_int32 Winner_rand_state;
|
||||
opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14;
|
||||
opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
|
||||
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
|
||||
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
|
||||
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
|
||||
NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
|
||||
NSQ_del_dec_struct *psDD;
|
||||
NSQ_sample_struct *psSS;
|
||||
|
||||
silk_assert( nStatesDelayedDecision > 0 );
|
||||
|
||||
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
|
||||
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
/* Perform common calculations used in all states */
|
||||
|
||||
/* Long-term prediction */
|
||||
if( signalType == TYPE_VOICED ) {
|
||||
/* Unrolled loop */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LTP_pred_Q14 = 2;
|
||||
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
|
||||
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
|
||||
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
|
||||
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
|
||||
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
|
||||
LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
|
||||
pred_lag_ptr++;
|
||||
} else {
|
||||
LTP_pred_Q14 = 0;
|
||||
}
|
||||
|
||||
/* Long-term shaping */
|
||||
if( lag > 0 ) {
|
||||
/* Symmetric, packed FIR coefficients */
|
||||
n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
|
||||
shp_lag_ptr++;
|
||||
} else {
|
||||
n_LTP_Q14 = 0;
|
||||
}
|
||||
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
/* Delayed decision state */
|
||||
psDD = &psDelDec[ k ];
|
||||
|
||||
/* Sample state */
|
||||
psSS = psSampleState[ k ];
|
||||
|
||||
/* Generate dither */
|
||||
psDD->Seed = silk_RAND( psDD->Seed );
|
||||
|
||||
/* Pointer used in short term prediction and shaping */
|
||||
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
|
||||
/* Short-term prediction */
|
||||
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ 0 ], a_Q12[ 0 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
|
||||
if( predictLPCOrder == 16 ) {
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
|
||||
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
|
||||
}
|
||||
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
|
||||
|
||||
/* Noise shape feedback */
|
||||
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
/* Output of lowpass section */
|
||||
tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
|
||||
psDD->sAR2_Q14[ 0 ] = tmp2;
|
||||
n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 );
|
||||
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] );
|
||||
/* Loop over allpass sections */
|
||||
for( j = 2; j < shapingLPCOrder; j += 2 ) {
|
||||
/* Output of allpass section */
|
||||
tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
|
||||
psDD->sAR2_Q14[ j - 1 ] = tmp1;
|
||||
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
|
||||
psDD->sAR2_Q14[ j + 0 ] = tmp2;
|
||||
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] );
|
||||
}
|
||||
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
|
||||
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
|
||||
|
||||
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */
|
||||
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */
|
||||
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */
|
||||
|
||||
n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */
|
||||
n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */
|
||||
n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */
|
||||
|
||||
/* Input minus prediction plus noise feedback */
|
||||
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
|
||||
tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
|
||||
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
|
||||
tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
|
||||
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
|
||||
|
||||
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
|
||||
|
||||
/* Flip sign depending on dither */
|
||||
if ( psDD->Seed < 0 ) {
|
||||
r_Q10 = -r_Q10;
|
||||
}
|
||||
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
|
||||
|
||||
/* Find two quantization level candidates and measure their rate-distortion */
|
||||
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
|
||||
if( q1_Q0 > 0 ) {
|
||||
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
|
||||
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
|
||||
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else if( q1_Q0 == 0 ) {
|
||||
q1_Q10 = offset_Q10;
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
|
||||
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
|
||||
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else if( q1_Q0 == -1 ) {
|
||||
q2_Q10 = offset_Q10;
|
||||
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
|
||||
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
|
||||
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
|
||||
} else { /* q1_Q0 < -1 */
|
||||
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
|
||||
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
|
||||
rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
|
||||
}
|
||||
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
|
||||
rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
|
||||
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
|
||||
rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
|
||||
|
||||
if( rd1_Q10 < rd2_Q10 ) {
|
||||
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
|
||||
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
|
||||
psSS[ 0 ].Q_Q10 = q1_Q10;
|
||||
psSS[ 1 ].Q_Q10 = q2_Q10;
|
||||
} else {
|
||||
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
|
||||
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
|
||||
psSS[ 0 ].Q_Q10 = q2_Q10;
|
||||
psSS[ 1 ].Q_Q10 = q1_Q10;
|
||||
}
|
||||
|
||||
/* Update states for best quantization */
|
||||
|
||||
/* Quantized excitation */
|
||||
exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 );
|
||||
if ( psDD->Seed < 0 ) {
|
||||
exc_Q14 = -exc_Q14;
|
||||
}
|
||||
|
||||
/* Add predictions */
|
||||
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
|
||||
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
|
||||
|
||||
/* Update states */
|
||||
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
|
||||
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
|
||||
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
|
||||
psSS[ 0 ].xq_Q14 = xq_Q14;
|
||||
|
||||
/* Update states for second best quantization */
|
||||
|
||||
/* Quantized excitation */
|
||||
exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 );
|
||||
if ( psDD->Seed < 0 ) {
|
||||
exc_Q14 = -exc_Q14;
|
||||
}
|
||||
|
||||
|
||||
/* Add predictions */
|
||||
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
|
||||
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
|
||||
|
||||
/* Update states */
|
||||
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
|
||||
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
|
||||
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
|
||||
psSS[ 1 ].xq_Q14 = xq_Q14;
|
||||
}
|
||||
|
||||
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
|
||||
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
|
||||
|
||||
/* Find winner */
|
||||
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
|
||||
Winner_ind = 0;
|
||||
for( k = 1; k < nStatesDelayedDecision; k++ ) {
|
||||
if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
|
||||
RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
|
||||
Winner_ind = k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increase RD values of expired states */
|
||||
Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
|
||||
psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 );
|
||||
psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 );
|
||||
silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Find worst in first set and best in second set */
|
||||
RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
|
||||
RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10;
|
||||
RDmax_ind = 0;
|
||||
RDmin_ind = 0;
|
||||
for( k = 1; k < nStatesDelayedDecision; k++ ) {
|
||||
/* find worst in first set */
|
||||
if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
|
||||
RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
|
||||
RDmax_ind = k;
|
||||
}
|
||||
/* find best in second set */
|
||||
if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
|
||||
RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10;
|
||||
RDmin_ind = k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace a state if best from second set outperforms worst in first set */
|
||||
if( RDmin_Q10 < RDmax_Q10 ) {
|
||||
silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i,
|
||||
( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) );
|
||||
silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
|
||||
}
|
||||
|
||||
/* Write samples from winner to output and long-term filter states */
|
||||
psDD = &psDelDec[ Winner_ind ];
|
||||
if( subfr > 0 || i >= decisionDelay ) {
|
||||
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
|
||||
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ];
|
||||
sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ];
|
||||
}
|
||||
NSQ->sLTP_shp_buf_idx++;
|
||||
NSQ->sLTP_buf_idx++;
|
||||
|
||||
/* Update states */
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
psDD = &psDelDec[ k ];
|
||||
psSS = &psSampleState[ k ][ 0 ];
|
||||
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
|
||||
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
|
||||
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
|
||||
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
|
||||
psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 );
|
||||
psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14;
|
||||
psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
|
||||
psDD->RandState[ *smpl_buf_idx ] = psDD->Seed;
|
||||
psDD->RD_Q10 = psSS->RD_Q10;
|
||||
}
|
||||
delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
|
||||
}
|
||||
/* Update LPC states */
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
psDD = &psDelDec[ k ];
|
||||
silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
|
||||
}
|
||||
}
|
||||
|
||||
static inline void silk_nsq_del_dec_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const opus_int32 x_Q3[], /* I Input in Q3 */
|
||||
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
opus_int subfr, /* I Subframe number */
|
||||
opus_int nStatesDelayedDecision, /* I Number of del dec states */
|
||||
const opus_int LTP_scale_Q14, /* I LTP state scaling */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
|
||||
const opus_int signal_type, /* I Signal type */
|
||||
const opus_int decisionDelay /* I Decision delay */
|
||||
)
|
||||
{
|
||||
opus_int i, k, lag;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
|
||||
NSQ_del_dec_struct *psDD;
|
||||
|
||||
lag = pitchL[ subfr ];
|
||||
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
|
||||
silk_assert( inv_gain_Q31 != 0 );
|
||||
|
||||
/* Calculate gain adjustment factor */
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
} else {
|
||||
gain_adj_Q16 = (opus_int32)1 << 16;
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
|
||||
for( i = 0; i < psEncC->subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
if( subfr == 0 ) {
|
||||
/* Do LTP downscaling */
|
||||
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
|
||||
}
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
silk_assert( i < MAX_FRAME_LENGTH );
|
||||
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust for changing gain */
|
||||
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
|
||||
}
|
||||
|
||||
/* Scale long-term prediction state */
|
||||
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
|
||||
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
psDD = &psDelDec[ k ];
|
||||
|
||||
/* Scale scalar states */
|
||||
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
|
||||
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
|
||||
psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < DECISION_DELAY; i++ ) {
|
||||
psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] );
|
||||
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,423 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "PLC.h"
|
||||
|
||||
#define NB_ATT 2
|
||||
static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
|
||||
static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
|
||||
static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
|
||||
|
||||
static inline void silk_PLC_update(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl /* I/O Decoder control */
|
||||
);
|
||||
|
||||
static inline void silk_PLC_conceal(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int16 frame[] /* O LPC residual signal */
|
||||
);
|
||||
|
||||
|
||||
void silk_PLC_Reset(
|
||||
silk_decoder_state *psDec /* I/O Decoder state */
|
||||
)
|
||||
{
|
||||
psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 );
|
||||
psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
|
||||
psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
|
||||
psDec->sPLC.subfr_length = 20;
|
||||
psDec->sPLC.nb_subfr = 2;
|
||||
}
|
||||
|
||||
void silk_PLC(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int16 frame[], /* I/O signal */
|
||||
opus_int lost /* I Loss flag */
|
||||
)
|
||||
{
|
||||
/* PLC control function */
|
||||
if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
|
||||
silk_PLC_Reset( psDec );
|
||||
psDec->sPLC.fs_kHz = psDec->fs_kHz;
|
||||
}
|
||||
|
||||
if( lost ) {
|
||||
/****************************/
|
||||
/* Generate Signal */
|
||||
/****************************/
|
||||
silk_PLC_conceal( psDec, psDecCtrl, frame );
|
||||
|
||||
psDec->lossCnt++;
|
||||
} else {
|
||||
/****************************/
|
||||
/* Update state */
|
||||
/****************************/
|
||||
silk_PLC_update( psDec, psDecCtrl );
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Update state of PLC */
|
||||
/**************************************************/
|
||||
static inline void silk_PLC_update(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl /* I/O Decoder control */
|
||||
)
|
||||
{
|
||||
opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
|
||||
opus_int i, j;
|
||||
silk_PLC_struct *psPLC;
|
||||
|
||||
psPLC = &psDec->sPLC;
|
||||
|
||||
/* Update parameters used in case of packet loss */
|
||||
psDec->prevSignalType = psDec->indices.signalType;
|
||||
LTP_Gain_Q14 = 0;
|
||||
if( psDec->indices.signalType == TYPE_VOICED ) {
|
||||
/* Find the parameters for the last subframe which contains a pitch pulse */
|
||||
for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
|
||||
if( j == psDec->nb_subfr ) {
|
||||
break;
|
||||
}
|
||||
temp_LTP_Gain_Q14 = 0;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ];
|
||||
}
|
||||
if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
|
||||
LTP_Gain_Q14 = temp_LTP_Gain_Q14;
|
||||
silk_memcpy( psPLC->LTPCoef_Q14,
|
||||
&psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
|
||||
LTP_ORDER * sizeof( opus_int16 ) );
|
||||
|
||||
psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
|
||||
}
|
||||
}
|
||||
|
||||
silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
|
||||
psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
|
||||
|
||||
/* Limit LT coefs */
|
||||
if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
|
||||
opus_int scale_Q10;
|
||||
opus_int32 tmp;
|
||||
|
||||
tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
|
||||
scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
|
||||
}
|
||||
} else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
|
||||
opus_int scale_Q14;
|
||||
opus_int32 tmp;
|
||||
|
||||
tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
|
||||
scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
|
||||
silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
|
||||
}
|
||||
|
||||
/* Save LPC coeficients */
|
||||
silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
|
||||
|
||||
/* Save last two gains */
|
||||
silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
|
||||
|
||||
psPLC->subfr_length = psDec->subfr_length;
|
||||
psPLC->nb_subfr = psDec->nb_subfr;
|
||||
}
|
||||
|
||||
static inline void silk_PLC_conceal(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int16 frame[] /* O LPC residual signal */
|
||||
)
|
||||
{
|
||||
opus_int i, j, k;
|
||||
opus_int lag, idx, sLTP_buf_idx, shift1, shift2;
|
||||
opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
|
||||
opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
|
||||
opus_int32 LPC_pred_Q10, LTP_pred_Q12;
|
||||
opus_int16 rand_scale_Q14;
|
||||
opus_int16 *B_Q14, *exc_buf_ptr;
|
||||
opus_int32 *sLPC_Q14_ptr;
|
||||
VARDECL( opus_int16, exc_buf );
|
||||
opus_int16 A_Q12[ MAX_LPC_ORDER ];
|
||||
VARDECL( opus_int16, sLTP );
|
||||
VARDECL( opus_int32, sLTP_Q14 );
|
||||
silk_PLC_struct *psPLC = &psDec->sPLC;
|
||||
opus_int32 prevGain_Q10[2];
|
||||
SAVE_STACK;
|
||||
|
||||
ALLOC( exc_buf, 2*psPLC->subfr_length, opus_int16 );
|
||||
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
|
||||
ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
|
||||
|
||||
prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
|
||||
prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
|
||||
|
||||
if( psDec->first_frame_after_reset ) {
|
||||
silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
|
||||
}
|
||||
|
||||
/* Find random noise component */
|
||||
/* Scale previous excitation signal */
|
||||
exc_buf_ptr = exc_buf;
|
||||
for( k = 0; k < 2; k++ ) {
|
||||
for( i = 0; i < psPLC->subfr_length; i++ ) {
|
||||
exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
|
||||
silk_SMULWW( psDec->exc_Q14[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], prevGain_Q10[ k ] ), 8 ) );
|
||||
}
|
||||
exc_buf_ptr += psPLC->subfr_length;
|
||||
}
|
||||
/* Find the subframe with lowest energy of the last two and use that as random noise generator */
|
||||
silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length );
|
||||
silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length );
|
||||
|
||||
if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
|
||||
/* First sub-frame has lowest energy */
|
||||
rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
|
||||
} else {
|
||||
/* Second sub-frame has lowest energy */
|
||||
rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
|
||||
}
|
||||
|
||||
/* Set up Gain to random noise component */
|
||||
B_Q14 = psPLC->LTPCoef_Q14;
|
||||
rand_scale_Q14 = psPLC->randScale_Q14;
|
||||
|
||||
/* Set up attenuation gains */
|
||||
harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
|
||||
if( psDec->prevSignalType == TYPE_VOICED ) {
|
||||
rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
|
||||
} else {
|
||||
rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
|
||||
}
|
||||
|
||||
/* LPC concealment. Apply BWE to previous LPC */
|
||||
silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
|
||||
|
||||
/* Preload LPC coeficients to array on stack. Gives small performance gain */
|
||||
silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
|
||||
/* First Lost frame */
|
||||
if( psDec->lossCnt == 0 ) {
|
||||
rand_scale_Q14 = 1 << 14;
|
||||
|
||||
/* Reduce random noise Gain for voiced frames */
|
||||
if( psDec->prevSignalType == TYPE_VOICED ) {
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
rand_scale_Q14 -= B_Q14[ i ];
|
||||
}
|
||||
rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
|
||||
rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
|
||||
} else {
|
||||
/* Reduce random noise for unvoiced frames with high LPC gain */
|
||||
opus_int32 invGain_Q30, down_scale_Q30;
|
||||
|
||||
invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
|
||||
|
||||
down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
|
||||
down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
|
||||
down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
|
||||
|
||||
rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
|
||||
}
|
||||
}
|
||||
|
||||
rand_seed = psPLC->rand_seed;
|
||||
lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
|
||||
sLTP_buf_idx = psDec->ltp_mem_length;
|
||||
|
||||
/* Rewhiten LTP state */
|
||||
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
|
||||
silk_assert( idx > 0 );
|
||||
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order );
|
||||
/* Scale LTP state */
|
||||
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
|
||||
inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
|
||||
for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
|
||||
sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* LTP synthesis filtering */
|
||||
/***************************/
|
||||
for( k = 0; k < psDec->nb_subfr; k++ ) {
|
||||
/* Set up pointer */
|
||||
pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
for( i = 0; i < psDec->subfr_length; i++ ) {
|
||||
/* Unrolled loop */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LTP_pred_Q12 = 2;
|
||||
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
|
||||
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
|
||||
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
|
||||
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
|
||||
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
|
||||
pred_lag_ptr++;
|
||||
|
||||
/* Generate LPC excitation */
|
||||
rand_seed = silk_RAND( rand_seed );
|
||||
idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
|
||||
sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
|
||||
sLTP_buf_idx++;
|
||||
}
|
||||
|
||||
/* Gradually reduce LTP gain */
|
||||
for( j = 0; j < LTP_ORDER; j++ ) {
|
||||
B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
|
||||
}
|
||||
/* Gradually reduce excitation gain */
|
||||
rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
|
||||
|
||||
/* Slowly increase pitch lag */
|
||||
psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
|
||||
psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
|
||||
lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* LPC synthesis filtering */
|
||||
/***************************/
|
||||
sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
|
||||
|
||||
/* Copy LPC state */
|
||||
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
|
||||
silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
|
||||
for( i = 0; i < psDec->frame_length; i++ ) {
|
||||
/* partly unrolled */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
|
||||
for( j = 10; j < psDec->LPC_order; j++ ) {
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
|
||||
}
|
||||
|
||||
/* Add prediction to LPC excitation */
|
||||
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
|
||||
|
||||
/* Scale with Gain */
|
||||
frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
|
||||
}
|
||||
|
||||
/* Save LPC state */
|
||||
silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
|
||||
/**************************************/
|
||||
/* Update states */
|
||||
/**************************************/
|
||||
psPLC->rand_seed = rand_seed;
|
||||
psPLC->randScale_Q14 = rand_scale_Q14;
|
||||
for( i = 0; i < MAX_NB_SUBFR; i++ ) {
|
||||
psDecCtrl->pitchL[ i ] = lag;
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
/* Glues concealed frames with new good received frames */
|
||||
void silk_PLC_glue_frames(
|
||||
silk_decoder_state *psDec, /* I/O decoder state */
|
||||
opus_int16 frame[], /* I/O signal */
|
||||
opus_int length /* I length of signal */
|
||||
)
|
||||
{
|
||||
opus_int i, energy_shift;
|
||||
opus_int32 energy;
|
||||
silk_PLC_struct *psPLC;
|
||||
psPLC = &psDec->sPLC;
|
||||
|
||||
if( psDec->lossCnt ) {
|
||||
/* Calculate energy in concealed residual */
|
||||
silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
|
||||
|
||||
psPLC->last_frame_lost = 1;
|
||||
} else {
|
||||
if( psDec->sPLC.last_frame_lost ) {
|
||||
/* Calculate residual in decoded signal if last frame was lost */
|
||||
silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
|
||||
|
||||
/* Normalize energies */
|
||||
if( energy_shift > psPLC->conc_energy_shift ) {
|
||||
psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
|
||||
} else if( energy_shift < psPLC->conc_energy_shift ) {
|
||||
energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
|
||||
}
|
||||
|
||||
/* Fade in the energy difference */
|
||||
if( energy > psPLC->conc_energy ) {
|
||||
opus_int32 frac_Q24, LZ;
|
||||
opus_int32 gain_Q16, slope_Q16;
|
||||
|
||||
LZ = silk_CLZ32( psPLC->conc_energy );
|
||||
LZ = LZ - 1;
|
||||
psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
|
||||
energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
|
||||
|
||||
frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
|
||||
|
||||
gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
|
||||
slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
|
||||
/* Make slope 4x steeper to avoid missing onsets after DTX */
|
||||
slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
|
||||
gain_Q16 += slope_Q16;
|
||||
if( gain_Q16 > (opus_int32)1 << 16 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
psPLC->last_frame_lost = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_PLC_H
|
||||
#define SILK_PLC_H
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define BWE_COEF 0.99
|
||||
#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */
|
||||
#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */
|
||||
#define MAX_PITCH_LAG_MS 18
|
||||
#define RAND_BUF_SIZE 128
|
||||
#define RAND_BUF_MASK ( RAND_BUF_SIZE - 1 )
|
||||
#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */
|
||||
#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */
|
||||
#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */
|
||||
|
||||
void silk_PLC_Reset(
|
||||
silk_decoder_state *psDec /* I/O Decoder state */
|
||||
);
|
||||
|
||||
void silk_PLC(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int16 frame[], /* I/O signal */
|
||||
opus_int lost /* I Loss flag */
|
||||
);
|
||||
|
||||
void silk_PLC_glue_frames(
|
||||
silk_decoder_state *psDec, /* I/O decoder state */
|
||||
opus_int16 frame[], /* I/O signal */
|
||||
opus_int length /* I length of signal */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,589 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_SIGPROC_FIX_H
|
||||
#define SILK_SIGPROC_FIX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
|
||||
|
||||
#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
|
||||
|
||||
#include <string.h> /* for memset(), memcpy(), memmove() */
|
||||
#include "typedef.h"
|
||||
#include "resampler_structs.h"
|
||||
#include "macros.h"
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/* SIGNAL PROCESSING FUNCTIONS */
|
||||
/********************************************************************/
|
||||
|
||||
/*!
|
||||
* Initialize/reset the resampler state for a given pair of input/output sampling rates
|
||||
*/
|
||||
opus_int silk_resampler_init(
|
||||
silk_resampler_state_struct *S, /* I/O Resampler state */
|
||||
opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
|
||||
opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */
|
||||
opus_int forEnc /* I If 1: encoder; if 0: decoder */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resampler: convert from one sampling rate to another
|
||||
*/
|
||||
opus_int silk_resampler(
|
||||
silk_resampler_state_struct *S, /* I/O Resampler state */
|
||||
opus_int16 out[], /* O Output signal */
|
||||
const opus_int16 in[], /* I Input signal */
|
||||
opus_int32 inLen /* I Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Downsample 2x, mediocre quality
|
||||
*/
|
||||
void silk_resampler_down2(
|
||||
opus_int32 *S, /* I/O State vector [ 2 ] */
|
||||
opus_int16 *out, /* O Output signal [ len ] */
|
||||
const opus_int16 *in, /* I Input signal [ floor(len/2) ] */
|
||||
opus_int32 inLen /* I Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Downsample by a factor 2/3, low quality
|
||||
*/
|
||||
void silk_resampler_down2_3(
|
||||
opus_int32 *S, /* I/O State vector [ 6 ] */
|
||||
opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */
|
||||
const opus_int16 *in, /* I Input signal [ inLen ] */
|
||||
opus_int32 inLen /* I Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* second order ARMA filter;
|
||||
* slower than biquad() but uses more precise coefficients
|
||||
* can handle (slowly) varying coefficients
|
||||
*/
|
||||
void silk_biquad_alt(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len, /* I signal length (must be even) */
|
||||
opus_int stride /* I Operate on interleaved signal if > 1 */
|
||||
);
|
||||
|
||||
/* Variable order MA prediction error filter. */
|
||||
void silk_LPC_analysis_filter(
|
||||
opus_int16 *out, /* O Output signal */
|
||||
const opus_int16 *in, /* I Input signal */
|
||||
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
|
||||
const opus_int32 len, /* I Signal length */
|
||||
const opus_int32 d /* I Filter order */
|
||||
);
|
||||
|
||||
/* Chirp (bandwidth expand) LP AR filter */
|
||||
void silk_bwexpander(
|
||||
opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
|
||||
const opus_int d, /* I Length of ar */
|
||||
opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
|
||||
);
|
||||
|
||||
/* Chirp (bandwidth expand) LP AR filter */
|
||||
void silk_bwexpander_32(
|
||||
opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
|
||||
const opus_int d, /* I Length of ar */
|
||||
opus_int32 chirp_Q16 /* I Chirp factor in Q16 */
|
||||
);
|
||||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* For input in Q24 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* Split signal in two decimated bands using first-order allpass filters */
|
||||
void silk_ana_filt_bank_1(
|
||||
const opus_int16 *in, /* I Input signal [N] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *outL, /* O Low band [N/2] */
|
||||
opus_int16 *outH, /* O High band [N/2] */
|
||||
const opus_int32 N /* I Number of input samples */
|
||||
);
|
||||
|
||||
/********************************************************************/
|
||||
/* SCALAR FUNCTIONS */
|
||||
/********************************************************************/
|
||||
|
||||
/* Approximation of 128 * log2() (exact inverse of approx 2^() below) */
|
||||
/* Convert input to a log scale */
|
||||
opus_int32 silk_lin2log(
|
||||
const opus_int32 inLin /* I input in linear scale */
|
||||
);
|
||||
|
||||
/* Approximation of a sigmoid function */
|
||||
opus_int silk_sigm_Q15(
|
||||
opus_int in_Q5 /* I */
|
||||
);
|
||||
|
||||
/* Approximation of 2^() (exact inverse of approx log2() above) */
|
||||
/* Convert input to a linear scale */
|
||||
opus_int32 silk_log2lin(
|
||||
const opus_int32 inLog_Q7 /* I input on log scale */
|
||||
);
|
||||
|
||||
/* Function that returns the maximum absolut value of the input vector */
|
||||
opus_int16 silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */
|
||||
const opus_int16 *vec, /* I Input vector [len] */
|
||||
const opus_int32 len /* I Length of input vector */
|
||||
);
|
||||
|
||||
/* Compute number of bits to right shift the sum of squares of a vector */
|
||||
/* of int16s to make it fit in an int32 */
|
||||
void silk_sum_sqr_shift(
|
||||
opus_int32 *energy, /* O Energy of x, after shifting to the right */
|
||||
opus_int *shift, /* O Number of bits right shift applied to energy */
|
||||
const opus_int16 *x, /* I Input vector */
|
||||
opus_int len /* I Length of input vector */
|
||||
);
|
||||
|
||||
/* Calculates the reflection coefficients from the correlation sequence */
|
||||
/* Faster than schur64(), but much less accurate. */
|
||||
/* uses SMLAWB(), requiring armv5E and higher. */
|
||||
opus_int32 silk_schur( /* O Returns residual energy */
|
||||
opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */
|
||||
const opus_int32 *c, /* I correlations [order+1] */
|
||||
const opus_int32 order /* I prediction order */
|
||||
);
|
||||
|
||||
/* Calculates the reflection coefficients from the correlation sequence */
|
||||
/* Slower than schur(), but more accurate. */
|
||||
/* Uses SMULL(), available on armv4 */
|
||||
opus_int32 silk_schur64( /* O returns residual energy */
|
||||
opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */
|
||||
const opus_int32 c[], /* I Correlations [order+1] */
|
||||
opus_int32 order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* Step up function, converts reflection coefficients to prediction coefficients */
|
||||
void silk_k2a(
|
||||
opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
|
||||
const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */
|
||||
const opus_int32 order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* Step up function, converts reflection coefficients to prediction coefficients */
|
||||
void silk_k2a_Q16(
|
||||
opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
|
||||
const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */
|
||||
const opus_int32 order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* Apply sine window to signal vector. */
|
||||
/* Window types: */
|
||||
/* 1 -> sine window from 0 to pi/2 */
|
||||
/* 2 -> sine window from pi/2 to pi */
|
||||
/* every other sample of window is linearly interpolated, for speed */
|
||||
void silk_apply_sine_window(
|
||||
opus_int16 px_win[], /* O Pointer to windowed signal */
|
||||
const opus_int16 px[], /* I Pointer to input signal */
|
||||
const opus_int win_type, /* I Selects a window type */
|
||||
const opus_int length /* I Window length, multiple of 4 */
|
||||
);
|
||||
|
||||
/* Compute autocorrelation */
|
||||
void silk_autocorr(
|
||||
opus_int32 *results, /* O Result (length correlationCount) */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *inputData, /* I Input data to correlate */
|
||||
const opus_int inputDataSize, /* I Length of input */
|
||||
const opus_int correlationCount /* I Number of correlation taps to compute */
|
||||
);
|
||||
|
||||
void silk_decode_pitch(
|
||||
opus_int16 lagIndex, /* I */
|
||||
opus_int8 contourIndex, /* O */
|
||||
opus_int pitch_lags[], /* O 4 pitch values */
|
||||
const opus_int Fs_kHz, /* I sampling frequency (kHz) */
|
||||
const opus_int nb_subfr /* I number of sub frames */
|
||||
);
|
||||
|
||||
opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
|
||||
const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
|
||||
opus_int *pitch_out, /* O 4 pitch lag values */
|
||||
opus_int16 *lagIndex, /* O Lag Index */
|
||||
opus_int8 *contourIndex, /* O Pitch contour Index */
|
||||
opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
|
||||
opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
|
||||
const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
|
||||
const opus_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */
|
||||
const opus_int Fs_kHz, /* I Sample frequency (kHz) */
|
||||
const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
|
||||
const opus_int nb_subfr /* I number of 5 ms subframes */
|
||||
);
|
||||
|
||||
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
|
||||
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
|
||||
void silk_A2NLSF(
|
||||
opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
|
||||
opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
|
||||
const opus_int d /* I Filter order (must be even) */
|
||||
);
|
||||
|
||||
/* compute whitening filter coefficients from normalized line spectral frequencies */
|
||||
void silk_NLSF2A(
|
||||
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
|
||||
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
|
||||
const opus_int d /* I filter order (should be even) */
|
||||
);
|
||||
|
||||
void silk_insertion_sort_increasing(
|
||||
opus_int32 *a, /* I/O Unsorted / Sorted vector */
|
||||
opus_int *idx, /* O Index vector for the sorted elements */
|
||||
const opus_int L, /* I Vector length */
|
||||
const opus_int K /* I Number of correctly sorted positions */
|
||||
);
|
||||
|
||||
void silk_insertion_sort_decreasing_int16(
|
||||
opus_int16 *a, /* I/O Unsorted / Sorted vector */
|
||||
opus_int *idx, /* O Index vector for the sorted elements */
|
||||
const opus_int L, /* I Vector length */
|
||||
const opus_int K /* I Number of correctly sorted positions */
|
||||
);
|
||||
|
||||
void silk_insertion_sort_increasing_all_values_int16(
|
||||
opus_int16 *a, /* I/O Unsorted / Sorted vector */
|
||||
const opus_int L /* I Vector length */
|
||||
);
|
||||
|
||||
/* NLSF stabilizer, for a single input data vector */
|
||||
void silk_NLSF_stabilize(
|
||||
opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
|
||||
const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
|
||||
const opus_int L /* I Number of NLSF parameters in the input vector */
|
||||
);
|
||||
|
||||
/* Laroia low complexity NLSF weights */
|
||||
void silk_NLSF_VQ_weights_laroia(
|
||||
opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
|
||||
const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
|
||||
const opus_int D /* I Input vector dimension (even) */
|
||||
);
|
||||
|
||||
/* Compute reflection coefficients from input signal */
|
||||
void silk_burg_modified(
|
||||
opus_int32 *res_nrg, /* O Residual energy */
|
||||
opus_int *res_nrg_Q, /* O Residual energy Q value */
|
||||
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
|
||||
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
|
||||
const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
|
||||
const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
|
||||
const opus_int nb_subfr, /* I Number of subframes stacked in x */
|
||||
const opus_int D /* I Order */
|
||||
);
|
||||
|
||||
/* Copy and multiply a vector by a constant */
|
||||
void silk_scale_copy_vector16(
|
||||
opus_int16 *data_out,
|
||||
const opus_int16 *data_in,
|
||||
opus_int32 gain_Q16, /* I Gain in Q16 */
|
||||
const opus_int dataSize /* I Length */
|
||||
);
|
||||
|
||||
/* Some for the LTP related function requires Q26 to work.*/
|
||||
void silk_scale_vector32_Q26_lshift_18(
|
||||
opus_int32 *data1, /* I/O Q0/Q18 */
|
||||
opus_int32 gain_Q26, /* I Q26 */
|
||||
opus_int dataSize /* I length */
|
||||
);
|
||||
|
||||
/********************************************************************/
|
||||
/* INLINE ARM MATH */
|
||||
/********************************************************************/
|
||||
|
||||
/* return sum( inVec1[i] * inVec2[i] ) */
|
||||
opus_int32 silk_inner_prod_aligned(
|
||||
const opus_int16 *const inVec1, /* I input vector 1 */
|
||||
const opus_int16 *const inVec2, /* I input vector 2 */
|
||||
const opus_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
opus_int32 silk_inner_prod_aligned_scale(
|
||||
const opus_int16 *const inVec1, /* I input vector 1 */
|
||||
const opus_int16 *const inVec2, /* I input vector 2 */
|
||||
const opus_int scale, /* I number of bits to shift */
|
||||
const opus_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
opus_int64 silk_inner_prod16_aligned_64(
|
||||
const opus_int16 *inVec1, /* I input vector 1 */
|
||||
const opus_int16 *inVec2, /* I input vector 2 */
|
||||
const opus_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
/********************************************************************/
|
||||
/* MACROS */
|
||||
/********************************************************************/
|
||||
|
||||
/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
|
||||
left. Output is 32bit int.
|
||||
Note: contemporary compilers recognize the C expression below and
|
||||
compile it into a 'ror' instruction if available. No need for inline ASM! */
|
||||
static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
|
||||
{
|
||||
opus_uint32 x = (opus_uint32) a32;
|
||||
opus_uint32 r = (opus_uint32) rot;
|
||||
opus_uint32 m = (opus_uint32) -rot;
|
||||
if( rot == 0 ) {
|
||||
return a32;
|
||||
} else if( rot < 0 ) {
|
||||
return (opus_int32) ((x << m) | (x >> (32 - m)));
|
||||
} else {
|
||||
return (opus_int32) ((x << (32 - r)) | (x >> r));
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate opus_int16 aligned to 4-byte memory address */
|
||||
#if EMBEDDED_ARM
|
||||
#define silk_DWORD_ALIGN __attribute__((aligned(4)))
|
||||
#else
|
||||
#define silk_DWORD_ALIGN
|
||||
#endif
|
||||
|
||||
/* Useful Macros that can be adjusted to other platforms */
|
||||
#define silk_memcpy(dest, src, size) memcpy((dest), (src), (size))
|
||||
#define silk_memset(dest, src, size) memset((dest), (src), (size))
|
||||
#define silk_memmove(dest, src, size) memmove((dest), (src), (size))
|
||||
|
||||
/* Fixed point macros */
|
||||
|
||||
/* (a32 * b32) output have to be 32bit int */
|
||||
#define silk_MUL(a32, b32) ((a32) * (b32))
|
||||
|
||||
/* (a32 * b32) output have to be 32bit uint */
|
||||
#define silk_MUL_uint(a32, b32) silk_MUL(a32, b32)
|
||||
|
||||
/* a32 + (b32 * c32) output have to be 32bit int */
|
||||
#define silk_MLA(a32, b32, c32) silk_ADD32((a32),((b32) * (c32)))
|
||||
|
||||
/* a32 + (b32 * c32) output have to be 32bit uint */
|
||||
#define silk_MLA_uint(a32, b32, c32) silk_MLA(a32, b32, c32)
|
||||
|
||||
/* ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
|
||||
#define silk_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16))
|
||||
|
||||
/* a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
|
||||
#define silk_SMLATT(a32, b32, c32) silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
|
||||
|
||||
#define silk_SMLALBB(a64, b16, c16) silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16)))
|
||||
|
||||
/* (a32 * b32) */
|
||||
#define silk_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32))
|
||||
|
||||
/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
|
||||
(just standard two's complement implementation-specific behaviour) */
|
||||
#define silk_ADD32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
|
||||
/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
|
||||
(just standard two's complement implementation-specific behaviour) */
|
||||
#define silk_SUB32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
|
||||
|
||||
/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
|
||||
#define silk_MLA_ovflw(a32, b32, c32) silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
|
||||
#define silk_SMLABB_ovflw(a32, b32, c32) (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))))
|
||||
|
||||
#define silk_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16)))
|
||||
#define silk_DIV32(a32, b32) ((opus_int32)((a32) / (b32)))
|
||||
|
||||
/* These macros enables checking for overflow in silk_API_Debug.h*/
|
||||
#define silk_ADD16(a, b) ((a) + (b))
|
||||
#define silk_ADD32(a, b) ((a) + (b))
|
||||
#define silk_ADD64(a, b) ((a) + (b))
|
||||
|
||||
#define silk_SUB16(a, b) ((a) - (b))
|
||||
#define silk_SUB32(a, b) ((a) - (b))
|
||||
#define silk_SUB64(a, b) ((a) - (b))
|
||||
|
||||
#define silk_SAT8(a) ((a) > silk_int8_MAX ? silk_int8_MAX : \
|
||||
((a) < silk_int8_MIN ? silk_int8_MIN : (a)))
|
||||
#define silk_SAT16(a) ((a) > silk_int16_MAX ? silk_int16_MAX : \
|
||||
((a) < silk_int16_MIN ? silk_int16_MIN : (a)))
|
||||
#define silk_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : \
|
||||
((a) < silk_int32_MIN ? silk_int32_MIN : (a)))
|
||||
|
||||
#define silk_CHECK_FIT8(a) (a)
|
||||
#define silk_CHECK_FIT16(a) (a)
|
||||
#define silk_CHECK_FIT32(a) (a)
|
||||
|
||||
#define silk_ADD_SAT16(a, b) (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) )
|
||||
#define silk_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \
|
||||
((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) : \
|
||||
((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) )
|
||||
|
||||
#define silk_SUB_SAT16(a, b) (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) )
|
||||
#define silk_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \
|
||||
(( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) : \
|
||||
((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) )
|
||||
|
||||
/* Saturation for positive input values */
|
||||
#define silk_POS_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : (a))
|
||||
|
||||
/* Add with saturation for positive input values */
|
||||
#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
|
||||
|
||||
#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
|
||||
#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
|
||||
#define silk_LSHIFT32(a, shift) ((opus_int32)((opus_uint32)(a)<<(shift))) /* shift >= 0, shift < 32 */
|
||||
#define silk_LSHIFT64(a, shift) ((opus_int64)((opus_uint64)(a)<<(shift))) /* shift >= 0, shift < 64 */
|
||||
#define silk_LSHIFT(a, shift) silk_LSHIFT32(a, shift) /* shift >= 0, shift < 32 */
|
||||
|
||||
#define silk_RSHIFT8(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 8 */
|
||||
#define silk_RSHIFT16(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 16 */
|
||||
#define silk_RSHIFT32(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 32 */
|
||||
#define silk_RSHIFT64(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 64 */
|
||||
#define silk_RSHIFT(a, shift) silk_RSHIFT32(a, shift) /* shift >= 0, shift < 32 */
|
||||
|
||||
/* saturates before shifting */
|
||||
#define silk_LSHIFT_SAT32(a, shift) (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \
|
||||
silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
|
||||
|
||||
#define silk_LSHIFT_ovflw(a, shift) ((opus_int32)((opus_uint32)(a) << (shift))) /* shift >= 0, allowed to overflow */
|
||||
#define silk_LSHIFT_uint(a, shift) ((a) << (shift)) /* shift >= 0 */
|
||||
#define silk_RSHIFT_uint(a, shift) ((a) >> (shift)) /* shift >= 0 */
|
||||
|
||||
#define silk_ADD_LSHIFT(a, b, shift) ((a) + silk_LSHIFT((b), (shift))) /* shift >= 0 */
|
||||
#define silk_ADD_LSHIFT32(a, b, shift) silk_ADD32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
|
||||
#define silk_ADD_LSHIFT_uint(a, b, shift) ((a) + silk_LSHIFT_uint((b), (shift))) /* shift >= 0 */
|
||||
#define silk_ADD_RSHIFT(a, b, shift) ((a) + silk_RSHIFT((b), (shift))) /* shift >= 0 */
|
||||
#define silk_ADD_RSHIFT32(a, b, shift) silk_ADD32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
|
||||
#define silk_ADD_RSHIFT_uint(a, b, shift) ((a) + silk_RSHIFT_uint((b), (shift))) /* shift >= 0 */
|
||||
#define silk_SUB_LSHIFT32(a, b, shift) silk_SUB32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
|
||||
#define silk_SUB_RSHIFT32(a, b, shift) silk_SUB32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
|
||||
|
||||
/* Requires that shift > 0 */
|
||||
#define silk_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
|
||||
#define silk_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
|
||||
|
||||
/* Number of rightshift required to fit the multiplication */
|
||||
#define silk_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) )
|
||||
#define silk_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) )
|
||||
|
||||
|
||||
#define silk_min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define silk_max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/* Macro to convert floating-point constants to fixed-point */
|
||||
#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
|
||||
|
||||
/* silk_min() versions with typecast in the function call */
|
||||
static inline opus_int silk_min_int(opus_int a, opus_int b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
/* silk_min() versions with typecast in the function call */
|
||||
static inline opus_int silk_max_int(opus_int a, opus_int b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
#define silk_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
|
||||
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
|
||||
|
||||
#define silk_LIMIT_int silk_LIMIT
|
||||
#define silk_LIMIT_16 silk_LIMIT
|
||||
#define silk_LIMIT_32 silk_LIMIT
|
||||
|
||||
#define silk_abs(a) (((a) > 0) ? (a) : -(a)) /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
|
||||
#define silk_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
|
||||
#define silk_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
|
||||
#define silk_abs_int64(a) (((a) > 0) ? (a) : -(a))
|
||||
|
||||
#define silk_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
|
||||
|
||||
/* PSEUDO-RANDOM GENERATOR */
|
||||
/* Make sure to store the result as the seed for the next call (also in between */
|
||||
/* frames), otherwise result won't be random at all. When only using some of the */
|
||||
/* bits, take the most significant bits by right-shifting. */
|
||||
#define silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165))
|
||||
|
||||
/* Add some multiplication functions that can be easily mapped to ARM. */
|
||||
|
||||
/* silk_SMMUL: Signed top word multiply.
|
||||
ARMv6 2 instruction cycles.
|
||||
ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/
|
||||
/*#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/
|
||||
/* the following seems faster on x86 */
|
||||
#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
|
||||
|
||||
#include "Inlines.h"
|
||||
#include "MacroCount.h"
|
||||
#include "MacroDebug.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SILK_SIGPROC_FIX_H */
|
|
@ -0,0 +1,330 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Silk VAD noise level estimation */
|
||||
static inline void silk_VAD_GetNoiseLevels(
|
||||
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
|
||||
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
|
||||
);
|
||||
|
||||
/**********************************/
|
||||
/* Initialization of the Silk VAD */
|
||||
/**********************************/
|
||||
opus_int silk_VAD_Init( /* O Return value, 0 if success */
|
||||
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
|
||||
)
|
||||
{
|
||||
opus_int b, ret = 0;
|
||||
|
||||
/* reset state memory */
|
||||
silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) );
|
||||
|
||||
/* init noise levels */
|
||||
/* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
|
||||
}
|
||||
|
||||
/* Initialize state */
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
|
||||
psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] );
|
||||
}
|
||||
psSilk_VAD->counter = 15;
|
||||
|
||||
/* init smoothed energy-to-noise ratio*/
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* Weighting factors for tilt measure */
|
||||
static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
|
||||
|
||||
/***************************************/
|
||||
/* Get the speech activity level in Q8 */
|
||||
/***************************************/
|
||||
opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */
|
||||
silk_encoder_state *psEncC, /* I/O Encoder state */
|
||||
const opus_int16 pIn[] /* I PCM input */
|
||||
)
|
||||
{
|
||||
opus_int SA_Q15, pSNR_dB_Q7, input_tilt;
|
||||
opus_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
|
||||
opus_int32 sumSquared, smooth_coef_Q16;
|
||||
opus_int16 HPstateTmp;
|
||||
opus_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ];
|
||||
opus_int32 Xnrg[ VAD_N_BANDS ];
|
||||
opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
|
||||
opus_int32 speech_nrg, x_tmp;
|
||||
opus_int ret = 0;
|
||||
silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
|
||||
|
||||
/* Safety checks */
|
||||
silk_assert( VAD_N_BANDS == 4 );
|
||||
silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
|
||||
silk_assert( psEncC->frame_length <= 512 );
|
||||
silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
|
||||
|
||||
/***********************/
|
||||
/* Filter and Decimate */
|
||||
/***********************/
|
||||
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */
|
||||
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length );
|
||||
|
||||
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */
|
||||
silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 1 ) );
|
||||
|
||||
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */
|
||||
silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 2 ) );
|
||||
|
||||
/*********************************************/
|
||||
/* HP filter on lowest band (differentiator) */
|
||||
/*********************************************/
|
||||
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
|
||||
X[ 0 ][ decimated_framelength - 1 ] = silk_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 );
|
||||
HPstateTmp = X[ 0 ][ decimated_framelength - 1 ];
|
||||
for( i = decimated_framelength - 1; i > 0; i-- ) {
|
||||
X[ 0 ][ i - 1 ] = silk_RSHIFT( X[ 0 ][ i - 1 ], 1 );
|
||||
X[ 0 ][ i ] -= X[ 0 ][ i - 1 ];
|
||||
}
|
||||
X[ 0 ][ 0 ] -= psSilk_VAD->HPstate;
|
||||
psSilk_VAD->HPstate = HPstateTmp;
|
||||
|
||||
/*************************************/
|
||||
/* Calculate the energy in each band */
|
||||
/*************************************/
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
/* Find the decimated framelength in the non-uniformly divided bands */
|
||||
decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
|
||||
|
||||
/* Split length into subframe lengths */
|
||||
dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
|
||||
dec_subframe_offset = 0;
|
||||
|
||||
/* Compute energy per sub-frame */
|
||||
/* initialize with summed energy of last subframe */
|
||||
Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
|
||||
for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
|
||||
sumSquared = 0;
|
||||
for( i = 0; i < dec_subframe_length; i++ ) {
|
||||
/* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */
|
||||
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
|
||||
x_tmp = silk_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 );
|
||||
sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
|
||||
|
||||
/* Safety check */
|
||||
silk_assert( sumSquared >= 0 );
|
||||
}
|
||||
|
||||
/* Add/saturate summed energy of current subframe */
|
||||
if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
|
||||
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
|
||||
} else {
|
||||
/* Look-ahead subframe */
|
||||
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
|
||||
}
|
||||
|
||||
dec_subframe_offset += dec_subframe_length;
|
||||
}
|
||||
psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* Noise estimation */
|
||||
/********************/
|
||||
silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
|
||||
|
||||
/***********************************************/
|
||||
/* Signal-plus-noise to noise ratio estimation */
|
||||
/***********************************************/
|
||||
sumSquared = 0;
|
||||
input_tilt = 0;
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
|
||||
if( speech_nrg > 0 ) {
|
||||
/* Divide, with sufficient resolution */
|
||||
if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
|
||||
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
|
||||
} else {
|
||||
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
|
||||
}
|
||||
|
||||
/* Convert to log domain */
|
||||
SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
|
||||
|
||||
/* Sum-of-squares */
|
||||
sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */
|
||||
|
||||
/* Tilt measure */
|
||||
if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
|
||||
/* Scale down SNR value for small subband speech energies */
|
||||
SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
|
||||
}
|
||||
input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
|
||||
} else {
|
||||
NrgToNoiseRatio_Q8[ b ] = 256;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mean-of-squares */
|
||||
sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
|
||||
|
||||
/* Root-mean-square approximation, scale to dBs, and write to output pointer */
|
||||
pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
|
||||
|
||||
/*********************************/
|
||||
/* Speech Probability Estimation */
|
||||
/*********************************/
|
||||
SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
|
||||
|
||||
/**************************/
|
||||
/* Frequency Tilt Measure */
|
||||
/**************************/
|
||||
psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
|
||||
|
||||
/**************************************************/
|
||||
/* Scale the sigmoid output based on power levels */
|
||||
/**************************************************/
|
||||
speech_nrg = 0;
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
/* Accumulate signal-without-noise energies, higher frequency bands have more weight */
|
||||
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
|
||||
}
|
||||
|
||||
/* Power scaling */
|
||||
if( speech_nrg <= 0 ) {
|
||||
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
|
||||
} else if( speech_nrg < 32768 ) {
|
||||
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
|
||||
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
|
||||
} else {
|
||||
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
|
||||
}
|
||||
|
||||
/* square-root */
|
||||
speech_nrg = silk_SQRT_APPROX( speech_nrg );
|
||||
SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
|
||||
}
|
||||
|
||||
/* Copy the resulting speech activity in Q8 */
|
||||
psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
|
||||
|
||||
/***********************************/
|
||||
/* Energy Level and SNR estimation */
|
||||
/***********************************/
|
||||
/* Smoothing coefficient */
|
||||
smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
|
||||
|
||||
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
|
||||
smooth_coef_Q16 >>= 1;
|
||||
}
|
||||
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
/* compute smoothed energy-to-noise ratio per band */
|
||||
psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
|
||||
NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
|
||||
|
||||
/* signal to noise ratio in dB per band */
|
||||
SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
|
||||
/* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
|
||||
psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Noise level estimation */
|
||||
/**************************/
|
||||
static inline void silk_VAD_GetNoiseLevels(
|
||||
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
|
||||
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 nl, nrg, inv_nrg;
|
||||
opus_int coef, min_coef;
|
||||
|
||||
/* Initially faster smoothing */
|
||||
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
|
||||
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
|
||||
} else {
|
||||
min_coef = 0;
|
||||
}
|
||||
|
||||
for( k = 0; k < VAD_N_BANDS; k++ ) {
|
||||
/* Get old noise level estimate for current band */
|
||||
nl = psSilk_VAD->NL[ k ];
|
||||
silk_assert( nl >= 0 );
|
||||
|
||||
/* Add bias */
|
||||
nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
|
||||
silk_assert( nrg > 0 );
|
||||
|
||||
/* Invert energies */
|
||||
inv_nrg = silk_DIV32( silk_int32_MAX, nrg );
|
||||
silk_assert( inv_nrg >= 0 );
|
||||
|
||||
/* Less update when subband energy is high */
|
||||
if( nrg > silk_LSHIFT( nl, 3 ) ) {
|
||||
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
|
||||
} else if( nrg < nl ) {
|
||||
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
|
||||
} else {
|
||||
coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
|
||||
}
|
||||
|
||||
/* Initially faster smoothing */
|
||||
coef = silk_max_int( coef, min_coef );
|
||||
|
||||
/* Smooth inverse energies */
|
||||
psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
|
||||
silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
|
||||
|
||||
/* Compute noise level by inverting again */
|
||||
nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] );
|
||||
silk_assert( nl >= 0 );
|
||||
|
||||
/* Limit noise levels (guarantee 7 bits of head room) */
|
||||
nl = silk_min( nl, 0x00FFFFFF );
|
||||
|
||||
/* Store as part of state */
|
||||
psSilk_VAD->NL[ k ] = nl;
|
||||
}
|
||||
|
||||
/* Increment frame counter */
|
||||
psSilk_VAD->counter++;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
|
||||
void silk_VQ_WMat_EC(
|
||||
opus_int8 *ind, /* O index of best codebook vector */
|
||||
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
|
||||
const opus_int16 *in_Q14, /* I input vector to be quantized */
|
||||
const opus_int32 *W_Q18, /* I weighting matrix */
|
||||
const opus_int8 *cb_Q7, /* I codebook */
|
||||
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
|
||||
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
|
||||
opus_int L /* I number of vectors in codebook */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
const opus_int8 *cb_row_Q7;
|
||||
opus_int16 diff_Q14[ 5 ];
|
||||
opus_int32 sum1_Q14, sum2_Q16;
|
||||
|
||||
/* Loop over codebook */
|
||||
*rate_dist_Q14 = silk_int32_MAX;
|
||||
cb_row_Q7 = cb_Q7;
|
||||
for( k = 0; k < L; k++ ) {
|
||||
diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
|
||||
diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
|
||||
diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 );
|
||||
diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 );
|
||||
diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 );
|
||||
|
||||
/* Weighted rate */
|
||||
sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
|
||||
|
||||
silk_assert( sum1_Q14 >= 0 );
|
||||
|
||||
/* first row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
|
||||
|
||||
/* second row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
|
||||
|
||||
/* third row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
|
||||
|
||||
/* fourth row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
|
||||
|
||||
/* last row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
|
||||
|
||||
silk_assert( sum1_Q14 >= 0 );
|
||||
|
||||
/* find best */
|
||||
if( sum1_Q14 < *rate_dist_Q14 ) {
|
||||
*rate_dist_Q14 = sum1_Q14;
|
||||
*ind = (opus_int8)k;
|
||||
}
|
||||
|
||||
/* Go to next cbk vector */
|
||||
cb_row_Q7 += LTP_ORDER;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Coefficients for 2-band filter bank based on first-order allpass filters */
|
||||
static opus_int16 A_fb1_20 = 5394 << 1;
|
||||
static opus_int16 A_fb1_21 = -24290; /* (opus_int16)(20623 << 1) */
|
||||
|
||||
/* Split signal into two decimated bands using first-order allpass filters */
|
||||
void silk_ana_filt_bank_1(
|
||||
const opus_int16 *in, /* I Input signal [N] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *outL, /* O Low band [N/2] */
|
||||
opus_int16 *outH, /* O High band [N/2] */
|
||||
const opus_int32 N /* I Number of input samples */
|
||||
)
|
||||
{
|
||||
opus_int k, N2 = silk_RSHIFT( N, 1 );
|
||||
opus_int32 in32, X, Y, out_1, out_2;
|
||||
|
||||
/* Internal variables and state are in Q10 format */
|
||||
for( k = 0; k < N2; k++ ) {
|
||||
/* Convert to Q10 */
|
||||
in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 );
|
||||
|
||||
/* All-pass section for even input sample */
|
||||
Y = silk_SUB32( in32, S[ 0 ] );
|
||||
X = silk_SMLAWB( Y, Y, A_fb1_21 );
|
||||
out_1 = silk_ADD32( S[ 0 ], X );
|
||||
S[ 0 ] = silk_ADD32( in32, X );
|
||||
|
||||
/* Convert to Q10 */
|
||||
in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 );
|
||||
|
||||
/* All-pass section for odd input sample, and add to output of previous section */
|
||||
Y = silk_SUB32( in32, S[ 1 ] );
|
||||
X = silk_SMULWB( Y, A_fb1_20 );
|
||||
out_2 = silk_ADD32( S[ 1 ], X );
|
||||
S[ 1 ] = silk_ADD32( in32, X );
|
||||
|
||||
/* Add/subtract, convert back to int16 and store to output */
|
||||
outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) );
|
||||
outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
/* *
|
||||
* silk_biquad_alt.c *
|
||||
* *
|
||||
* Second order ARMA filter *
|
||||
* Can handle slowly varying filter coefficients *
|
||||
* */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Second order ARMA filter, alternative implementation */
|
||||
void silk_biquad_alt(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len, /* I signal length (must be even) */
|
||||
opus_int stride /* I Operate on interleaved signal if > 1 */
|
||||
)
|
||||
{
|
||||
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
||||
opus_int k;
|
||||
opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
|
||||
|
||||
/* Negate A_Q28 values and split in two parts */
|
||||
A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
|
||||
A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
|
||||
A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
|
||||
A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
|
||||
|
||||
for( k = 0; k < len; k++ ) {
|
||||
/* S[ 0 ], S[ 1 ]: Q12 */
|
||||
inval = in[ k * stride ];
|
||||
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
|
||||
|
||||
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
|
||||
S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
|
||||
S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
|
||||
|
||||
S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
|
||||
S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
|
||||
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
|
||||
|
||||
/* Scale back to Q0 and saturate */
|
||||
out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Chirp (bandwidth expand) LP AR filter */
|
||||
void silk_bwexpander(
|
||||
opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
|
||||
const opus_int d, /* I Length of ar */
|
||||
opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
|
||||
|
||||
/* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below. */
|
||||
/* Bias in silk_SMULWB can lead to unstable filters */
|
||||
for( i = 0; i < d - 1; i++ ) {
|
||||
ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 );
|
||||
chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
|
||||
}
|
||||
ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Chirp (bandwidth expand) LP AR filter */
|
||||
void silk_bwexpander_32(
|
||||
opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
|
||||
const opus_int d, /* I Length of ar */
|
||||
opus_int32 chirp_Q16 /* I Chirp factor in Q16 */
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
|
||||
|
||||
for( i = 0; i < d - 1; i++ ) {
|
||||
ar[ i ] = silk_SMULWW( chirp_Q16, ar[ i ] );
|
||||
chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
|
||||
}
|
||||
ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] );
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "control.h"
|
||||
#include "errors.h"
|
||||
|
||||
/* Check encoder control struct */
|
||||
opus_int check_control_input(
|
||||
silk_EncControlStruct *encControl /* I Control structure */
|
||||
)
|
||||
{
|
||||
silk_assert( encControl != NULL );
|
||||
|
||||
if( ( ( encControl->API_sampleRate != 8000 ) &&
|
||||
( encControl->API_sampleRate != 12000 ) &&
|
||||
( encControl->API_sampleRate != 16000 ) &&
|
||||
( encControl->API_sampleRate != 24000 ) &&
|
||||
( encControl->API_sampleRate != 32000 ) &&
|
||||
( encControl->API_sampleRate != 44100 ) &&
|
||||
( encControl->API_sampleRate != 48000 ) ) ||
|
||||
( ( encControl->desiredInternalSampleRate != 8000 ) &&
|
||||
( encControl->desiredInternalSampleRate != 12000 ) &&
|
||||
( encControl->desiredInternalSampleRate != 16000 ) ) ||
|
||||
( ( encControl->maxInternalSampleRate != 8000 ) &&
|
||||
( encControl->maxInternalSampleRate != 12000 ) &&
|
||||
( encControl->maxInternalSampleRate != 16000 ) ) ||
|
||||
( ( encControl->minInternalSampleRate != 8000 ) &&
|
||||
( encControl->minInternalSampleRate != 12000 ) &&
|
||||
( encControl->minInternalSampleRate != 16000 ) ) ||
|
||||
( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
|
||||
( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
|
||||
( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_FS_NOT_SUPPORTED;
|
||||
}
|
||||
if( encControl->payloadSize_ms != 10 &&
|
||||
encControl->payloadSize_ms != 20 &&
|
||||
encControl->payloadSize_ms != 40 &&
|
||||
encControl->payloadSize_ms != 60 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
|
||||
}
|
||||
if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_LOSS_RATE;
|
||||
}
|
||||
if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_DTX_SETTING;
|
||||
}
|
||||
if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_CBR_SETTING;
|
||||
}
|
||||
if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_INBAND_FEC_SETTING;
|
||||
}
|
||||
if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->complexity < 0 || encControl->complexity > 10 ) {
|
||||
silk_assert( 0 );
|
||||
return SILK_ENC_INVALID_COMPLEXITY_SETTING;
|
||||
}
|
||||
|
||||
return SILK_NO_ERROR;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/*#define silk_enc_map(a) ((a) > 0 ? 1 : 0)*/
|
||||
/*#define silk_dec_map(a) ((a) > 0 ? 1 : -1)*/
|
||||
/* shifting avoids if-statement */
|
||||
#define silk_enc_map(a) ( silk_RSHIFT( (a), 15 ) + 1 )
|
||||
#define silk_dec_map(a) ( silk_LSHIFT( (a), 1 ) - 1 )
|
||||
|
||||
/* Encodes signs of excitation */
|
||||
void silk_encode_signs(
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
const opus_int8 pulses[], /* I pulse signal */
|
||||
opus_int length, /* I length of input */
|
||||
const opus_int signalType, /* I Signal type */
|
||||
const opus_int quantOffsetType, /* I Quantization offset type */
|
||||
const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
|
||||
)
|
||||
{
|
||||
opus_int i, j, p;
|
||||
opus_uint8 icdf[ 2 ];
|
||||
const opus_int8 *q_ptr;
|
||||
const opus_uint8 *icdf_ptr;
|
||||
|
||||
icdf[ 1 ] = 0;
|
||||
q_ptr = pulses;
|
||||
i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
|
||||
icdf_ptr = &silk_sign_iCDF[ i ];
|
||||
length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
for( i = 0; i < length; i++ ) {
|
||||
p = sum_pulses[ i ];
|
||||
if( p > 0 ) {
|
||||
icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
|
||||
for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
|
||||
if( q_ptr[ j ] != 0 ) {
|
||||
ec_enc_icdf( psRangeEnc, silk_enc_map( q_ptr[ j ]), icdf, 8 );
|
||||
}
|
||||
}
|
||||
}
|
||||
q_ptr += SHELL_CODEC_FRAME_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes signs of excitation */
|
||||
void silk_decode_signs(
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int pulses[], /* I/O pulse signal */
|
||||
opus_int length, /* I length of input */
|
||||
const opus_int signalType, /* I Signal type */
|
||||
const opus_int quantOffsetType, /* I Quantization offset type */
|
||||
const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
|
||||
)
|
||||
{
|
||||
opus_int i, j, p;
|
||||
opus_uint8 icdf[ 2 ];
|
||||
opus_int *q_ptr;
|
||||
const opus_uint8 *icdf_ptr;
|
||||
|
||||
icdf[ 1 ] = 0;
|
||||
q_ptr = pulses;
|
||||
i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
|
||||
icdf_ptr = &silk_sign_iCDF[ i ];
|
||||
length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
for( i = 0; i < length; i++ ) {
|
||||
p = sum_pulses[ i ];
|
||||
if( p > 0 ) {
|
||||
icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
|
||||
for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
|
||||
if( q_ptr[ j ] > 0 ) {
|
||||
/* attach sign */
|
||||
#if 0
|
||||
/* conditional implementation */
|
||||
if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) {
|
||||
q_ptr[ j ] = -q_ptr[ j ];
|
||||
}
|
||||
#else
|
||||
/* implementation with shift, subtraction, multiplication */
|
||||
q_ptr[ j ] *= silk_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
q_ptr += SHELL_CODEC_FRAME_LENGTH;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_CONTROL_H
|
||||
#define SILK_CONTROL_H
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Decoder API flags */
|
||||
#define FLAG_DECODE_NORMAL 0
|
||||
#define FLAG_PACKET_LOST 1
|
||||
#define FLAG_DECODE_LBRR 2
|
||||
|
||||
/***********************************************/
|
||||
/* Structure for controlling encoder operation */
|
||||
/***********************************************/
|
||||
typedef struct {
|
||||
/* I: Number of channels; 1/2 */
|
||||
opus_int32 nChannelsAPI;
|
||||
|
||||
/* I: Number of channels; 1/2 */
|
||||
opus_int32 nChannelsInternal;
|
||||
|
||||
/* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */
|
||||
opus_int32 API_sampleRate;
|
||||
|
||||
/* I: Maximum internal sampling rate in Hertz; 8000/12000/16000 */
|
||||
opus_int32 maxInternalSampleRate;
|
||||
|
||||
/* I: Minimum internal sampling rate in Hertz; 8000/12000/16000 */
|
||||
opus_int32 minInternalSampleRate;
|
||||
|
||||
/* I: Soft request for internal sampling rate in Hertz; 8000/12000/16000 */
|
||||
opus_int32 desiredInternalSampleRate;
|
||||
|
||||
/* I: Number of samples per packet in milliseconds; 10/20/40/60 */
|
||||
opus_int payloadSize_ms;
|
||||
|
||||
/* I: Bitrate during active speech in bits/second; internally limited */
|
||||
opus_int32 bitRate;
|
||||
|
||||
/* I: Uplink packet loss in percent (0-100) */
|
||||
opus_int packetLossPercentage;
|
||||
|
||||
/* I: Complexity mode; 0 is lowest, 10 is highest complexity */
|
||||
opus_int complexity;
|
||||
|
||||
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
|
||||
opus_int useInBandFEC;
|
||||
|
||||
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
|
||||
opus_int useDTX;
|
||||
|
||||
/* I: Flag to use constant bitrate */
|
||||
opus_int useCBR;
|
||||
|
||||
/* I: Maximum number of bits allowed for the frame */
|
||||
opus_int maxBits;
|
||||
|
||||
/* I: Causes a smooth downmix to mono */
|
||||
opus_int toMono;
|
||||
|
||||
/* I: Opus encoder is allowing us to switch bandwidth */
|
||||
opus_int opusCanSwitch;
|
||||
|
||||
/* O: Internal sampling rate used, in Hertz; 8000/12000/16000 */
|
||||
opus_int32 internalSampleRate;
|
||||
|
||||
/* O: Flag that bandwidth switching is allowed (because low voice activity) */
|
||||
opus_int allowBandwidthSwitch;
|
||||
|
||||
/* O: Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */
|
||||
opus_int inWBmodeWithoutVariableLP;
|
||||
|
||||
/* O: Stereo width */
|
||||
opus_int stereoWidth_Q14;
|
||||
|
||||
/* O: Tells the Opus encoder we're ready to switch */
|
||||
opus_int switchReady;
|
||||
|
||||
} silk_EncControlStruct;
|
||||
|
||||
/**************************************************************************/
|
||||
/* Structure for controlling decoder operation and reading decoder status */
|
||||
/**************************************************************************/
|
||||
typedef struct {
|
||||
/* I: Number of channels; 1/2 */
|
||||
opus_int32 nChannelsAPI;
|
||||
|
||||
/* I: Number of channels; 1/2 */
|
||||
opus_int32 nChannelsInternal;
|
||||
|
||||
/* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */
|
||||
opus_int32 API_sampleRate;
|
||||
|
||||
/* I: Internal sampling rate used, in Hertz; 8000/12000/16000 */
|
||||
opus_int32 internalSampleRate;
|
||||
|
||||
/* I: Number of samples per packet in milliseconds; 10/20/40/60 */
|
||||
opus_int payloadSize_ms;
|
||||
|
||||
/* O: Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz */
|
||||
opus_int prevPitchLag;
|
||||
} silk_DecControlStruct;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/* Control SNR of redidual quantizer */
|
||||
opus_int silk_control_SNR(
|
||||
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
|
||||
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
|
||||
)
|
||||
{
|
||||
opus_int k, ret = SILK_NO_ERROR;
|
||||
opus_int32 frac_Q6;
|
||||
const opus_int32 *rateTable;
|
||||
|
||||
/* Set bitrate/coding quality */
|
||||
TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
|
||||
if( TargetRate_bps != psEncC->TargetRate_bps ) {
|
||||
psEncC->TargetRate_bps = TargetRate_bps;
|
||||
|
||||
/* If new TargetRate_bps, translate to SNR_dB value */
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
rateTable = silk_TargetRate_table_NB;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
rateTable = silk_TargetRate_table_MB;
|
||||
} else {
|
||||
rateTable = silk_TargetRate_table_WB;
|
||||
}
|
||||
|
||||
/* Reduce bitrate for 10 ms modes in these calculations */
|
||||
if( psEncC->nb_subfr == 2 ) {
|
||||
TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
|
||||
}
|
||||
|
||||
/* Find bitrate interval in table and interpolate */
|
||||
for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
|
||||
if( TargetRate_bps <= rateTable[ k ] ) {
|
||||
frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
|
||||
rateTable[ k ] - rateTable[ k - 1 ] );
|
||||
psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce coding quality whenever LBRR is enabled, to free up some bits */
|
||||
if( psEncC->LBRR_enabled ) {
|
||||
psEncC->SNR_dB_Q7 = silk_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/* Control internal sampling rate */
|
||||
opus_int silk_control_audio_bandwidth(
|
||||
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl /* I Control structure */
|
||||
)
|
||||
{
|
||||
opus_int fs_kHz;
|
||||
opus_int32 fs_Hz;
|
||||
|
||||
fs_kHz = psEncC->fs_kHz;
|
||||
fs_Hz = silk_SMULBB( fs_kHz, 1000 );
|
||||
if( fs_Hz == 0 ) {
|
||||
/* Encoder has just been initialized */
|
||||
fs_Hz = silk_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz );
|
||||
fs_kHz = silk_DIV32_16( fs_Hz, 1000 );
|
||||
} else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) {
|
||||
/* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
|
||||
fs_Hz = psEncC->API_fs_Hz;
|
||||
fs_Hz = silk_min( fs_Hz, psEncC->maxInternal_fs_Hz );
|
||||
fs_Hz = silk_max( fs_Hz, psEncC->minInternal_fs_Hz );
|
||||
fs_kHz = silk_DIV32_16( fs_Hz, 1000 );
|
||||
} else {
|
||||
/* State machine for the internal sampling rate switching */
|
||||
if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {
|
||||
/* Stop transition phase */
|
||||
psEncC->sLP.mode = 0;
|
||||
}
|
||||
if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) {
|
||||
/* Check if we should switch down */
|
||||
if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
|
||||
{
|
||||
/* Switch down */
|
||||
if( psEncC->sLP.mode == 0 ) {
|
||||
/* New transition */
|
||||
psEncC->sLP.transition_frame_no = TRANSITION_FRAMES;
|
||||
|
||||
/* Reset transition filter state */
|
||||
silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
|
||||
}
|
||||
if( encControl->opusCanSwitch ) {
|
||||
/* Stop transition phase */
|
||||
psEncC->sLP.mode = 0;
|
||||
|
||||
/* Switch to a lower sample frequency */
|
||||
fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
|
||||
} else {
|
||||
if( psEncC->sLP.transition_frame_no <= 0 ) {
|
||||
encControl->switchReady = 1;
|
||||
/* Make room for redundancy */
|
||||
encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 );
|
||||
} else {
|
||||
/* Direction: down (at double speed) */
|
||||
psEncC->sLP.mode = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Check if we should switch up */
|
||||
if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
|
||||
{
|
||||
/* Switch up */
|
||||
if( encControl->opusCanSwitch ) {
|
||||
/* Switch to a higher sample frequency */
|
||||
fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
|
||||
|
||||
/* New transition */
|
||||
psEncC->sLP.transition_frame_no = 0;
|
||||
|
||||
/* Reset transition filter state */
|
||||
silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
|
||||
|
||||
/* Direction: up */
|
||||
psEncC->sLP.mode = 1;
|
||||
} else {
|
||||
if( psEncC->sLP.mode == 0 ) {
|
||||
encControl->switchReady = 1;
|
||||
/* Make room for redundancy */
|
||||
encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 );
|
||||
} else {
|
||||
/* Direction: up */
|
||||
psEncC->sLP.mode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fs_kHz;
|
||||
}
|
|
@ -0,0 +1,411 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifdef FIXED_POINT
|
||||
#include "main_FIX.h"
|
||||
#define silk_encoder_state_Fxx silk_encoder_state_FIX
|
||||
#else
|
||||
#include "main_FLP.h"
|
||||
#define silk_encoder_state_Fxx silk_encoder_state_FLP
|
||||
#endif
|
||||
#include "tuning_parameters.h"
|
||||
#include "pitch_est_defines.h"
|
||||
|
||||
static opus_int silk_setup_resamplers(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O */
|
||||
opus_int fs_kHz /* I */
|
||||
);
|
||||
|
||||
static opus_int silk_setup_fs(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O */
|
||||
opus_int fs_kHz, /* I */
|
||||
opus_int PacketSize_ms /* I */
|
||||
);
|
||||
|
||||
static opus_int silk_setup_complexity(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
opus_int Complexity /* I */
|
||||
);
|
||||
|
||||
static inline opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
);
|
||||
|
||||
|
||||
/* Control encoder */
|
||||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
)
|
||||
{
|
||||
opus_int fs_kHz, ret = 0;
|
||||
|
||||
psEnc->sCmn.useDTX = encControl->useDTX;
|
||||
psEnc->sCmn.useCBR = encControl->useCBR;
|
||||
psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate;
|
||||
psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate;
|
||||
psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate;
|
||||
psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate;
|
||||
psEnc->sCmn.useInBandFEC = encControl->useInBandFEC;
|
||||
psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI;
|
||||
psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal;
|
||||
psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch;
|
||||
psEnc->sCmn.channelNb = channelNb;
|
||||
|
||||
if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) {
|
||||
if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {
|
||||
/* Change in API sampling rate in the middle of encoding a packet */
|
||||
ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Beyond this point we know that there are no previously coded frames in the payload buffer */
|
||||
|
||||
/********************************************/
|
||||
/* Determine internal sampling rate */
|
||||
/********************************************/
|
||||
fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn, encControl );
|
||||
if( force_fs_kHz ) {
|
||||
fs_kHz = force_fs_kHz;
|
||||
}
|
||||
/********************************************/
|
||||
/* Prepare resampler and buffered data */
|
||||
/********************************************/
|
||||
ret += silk_setup_resamplers( psEnc, fs_kHz );
|
||||
|
||||
/********************************************/
|
||||
/* Set internal sampling frequency */
|
||||
/********************************************/
|
||||
ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms );
|
||||
|
||||
/********************************************/
|
||||
/* Set encoding complexity */
|
||||
/********************************************/
|
||||
ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity );
|
||||
|
||||
/********************************************/
|
||||
/* Set packet loss rate measured by farend */
|
||||
/********************************************/
|
||||
psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage;
|
||||
|
||||
/********************************************/
|
||||
/* Set LBRR usage */
|
||||
/********************************************/
|
||||
ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
|
||||
|
||||
psEnc->sCmn.controlled_since_last_payload = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static opus_int silk_setup_resamplers(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O */
|
||||
opus_int fs_kHz /* I */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
opus_int32 nSamples_temp;
|
||||
|
||||
if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz )
|
||||
{
|
||||
if( psEnc->sCmn.fs_kHz == 0 ) {
|
||||
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
|
||||
ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 );
|
||||
} else {
|
||||
/* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */
|
||||
opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ];
|
||||
silk_resampler_state_struct temp_resampler_state;
|
||||
#ifdef FIXED_POINT
|
||||
opus_int16 *x_bufFIX = psEnc->x_buf;
|
||||
#else
|
||||
opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];
|
||||
#endif
|
||||
|
||||
nSamples_temp = silk_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
silk_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp );
|
||||
#endif
|
||||
|
||||
/* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
|
||||
ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 );
|
||||
|
||||
/* Temporary resampling of x_buf data to API_fs_Hz */
|
||||
ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
|
||||
|
||||
/* Calculate number of samples that has been temporarily upsampled */
|
||||
nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
|
||||
|
||||
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
|
||||
ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 );
|
||||
|
||||
/* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */
|
||||
ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp );
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
silk_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static opus_int silk_setup_fs(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O */
|
||||
opus_int fs_kHz, /* I */
|
||||
opus_int PacketSize_ms /* I */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
|
||||
/* Set packet size */
|
||||
if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) {
|
||||
if( ( PacketSize_ms != 10 ) &&
|
||||
( PacketSize_ms != 20 ) &&
|
||||
( PacketSize_ms != 40 ) &&
|
||||
( PacketSize_ms != 60 ) ) {
|
||||
ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
|
||||
}
|
||||
if( PacketSize_ms <= 10 ) {
|
||||
psEnc->sCmn.nFramesPerPacket = 1;
|
||||
psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1;
|
||||
psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz );
|
||||
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
|
||||
if( psEnc->sCmn.fs_kHz == 8 ) {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
|
||||
}
|
||||
} else {
|
||||
psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS );
|
||||
psEnc->sCmn.nb_subfr = MAX_NB_SUBFR;
|
||||
psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz );
|
||||
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
|
||||
if( psEnc->sCmn.fs_kHz == 8 ) {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
|
||||
}
|
||||
}
|
||||
psEnc->sCmn.PacketSize_ms = PacketSize_ms;
|
||||
psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */
|
||||
}
|
||||
|
||||
/* Set internal sampling frequency */
|
||||
silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
|
||||
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
|
||||
/* reset part of the state */
|
||||
silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) );
|
||||
silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) );
|
||||
silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) );
|
||||
silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
||||
silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
|
||||
psEnc->sCmn.inputBufIx = 0;
|
||||
psEnc->sCmn.nFramesEncoded = 0;
|
||||
psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */
|
||||
|
||||
/* Initialize non-zero parameters */
|
||||
psEnc->sCmn.prevLag = 100;
|
||||
psEnc->sCmn.first_frame_after_reset = 1;
|
||||
psEnc->sPrefilt.lagPrev = 100;
|
||||
psEnc->sShape.LastGainIndex = 10;
|
||||
psEnc->sCmn.sNSQ.lagPrev = 100;
|
||||
psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536;
|
||||
psEnc->sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
|
||||
psEnc->sCmn.fs_kHz = fs_kHz;
|
||||
if( psEnc->sCmn.fs_kHz == 8 ) {
|
||||
if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
|
||||
}
|
||||
} else {
|
||||
if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
|
||||
}
|
||||
}
|
||||
if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) {
|
||||
psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER;
|
||||
psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB;
|
||||
} else {
|
||||
psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER;
|
||||
psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB;
|
||||
}
|
||||
psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz;
|
||||
psEnc->sCmn.frame_length = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
|
||||
psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
|
||||
psEnc->sCmn.la_pitch = silk_SMULBB( LA_PITCH_MS, fs_kHz );
|
||||
psEnc->sCmn.max_pitch_lag = silk_SMULBB( 18, fs_kHz );
|
||||
if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
|
||||
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
|
||||
} else {
|
||||
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
|
||||
}
|
||||
if( psEnc->sCmn.fs_kHz == 16 ) {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
|
||||
} else if( psEnc->sCmn.fs_kHz == 12 ) {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that settings are valid */
|
||||
silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static opus_int silk_setup_complexity(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
opus_int Complexity /* I */
|
||||
)
|
||||
{
|
||||
opus_int ret = 0;
|
||||
|
||||
/* Set encoding complexity */
|
||||
silk_assert( Complexity >= 0 && Complexity <= 10 );
|
||||
if( Complexity < 2 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 6;
|
||||
psEncC->shapingLPCOrder = 8;
|
||||
psEncC->la_shape = 3 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 1;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->LTPQuantLowComplexity = 1;
|
||||
psEncC->NLSF_MSVQ_Survivors = 2;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 4 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 8;
|
||||
psEncC->shapingLPCOrder = 10;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 1;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 4;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 6 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 10;
|
||||
psEncC->shapingLPCOrder = 12;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 2;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 8;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
} else if( Complexity < 8 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 12;
|
||||
psEncC->shapingLPCOrder = 14;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 3;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 16;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
} else {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 16;
|
||||
psEncC->shapingLPCOrder = 16;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 32;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
}
|
||||
|
||||
/* Do not allow higher pitch estimation LPC order than predict LPC order */
|
||||
psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder );
|
||||
psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
|
||||
psEncC->Complexity = Complexity;
|
||||
|
||||
silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
|
||||
silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
|
||||
silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
|
||||
silk_assert( psEncC->warping_Q16 <= 32767 );
|
||||
silk_assert( psEncC->la_shape <= LA_SHAPE_MAX );
|
||||
silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
|
||||
silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
opus_int32 LBRR_rate_thres_bps;
|
||||
|
||||
psEncC->LBRR_enabled = 0;
|
||||
if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
|
||||
} else {
|
||||
LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
|
||||
}
|
||||
LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
|
||||
|
||||
if( TargetRate_bps > LBRR_rate_thres_bps ) {
|
||||
/* Set gain increase for coding LBRR excitation */
|
||||
psEncC->LBRR_enabled = 1;
|
||||
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
#if SILK_TIC_TOC
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if (defined(_WIN32) || defined(_WINCE))
|
||||
#include <windows.h> /* timer */
|
||||
#else /* Linux or Mac*/
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/
|
||||
{
|
||||
/* Returns a time counter in microsec */
|
||||
/* the resolution is platform dependent */
|
||||
/* but is typically 1.62 us resolution */
|
||||
LARGE_INTEGER lpPerformanceCount;
|
||||
LARGE_INTEGER lpFrequency;
|
||||
QueryPerformanceCounter(&lpPerformanceCount);
|
||||
QueryPerformanceFrequency(&lpFrequency);
|
||||
return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart);
|
||||
}
|
||||
#else /* Linux or Mac*/
|
||||
unsigned long GetHighResolutionTime(void) /* O time in usec*/
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return((tv.tv_sec*1000000)+(tv.tv_usec));
|
||||
}
|
||||
#endif
|
||||
|
||||
int silk_Timer_nTimers = 0;
|
||||
int silk_Timer_depth_ctr = 0;
|
||||
char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
#else
|
||||
unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
#endif
|
||||
unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX];
|
||||
opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX];
|
||||
opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX];
|
||||
opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX];
|
||||
opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX];
|
||||
|
||||
#ifdef WIN32
|
||||
void silk_TimerSave(char *file_name)
|
||||
{
|
||||
if( silk_Timer_nTimers > 0 )
|
||||
{
|
||||
int k;
|
||||
FILE *fp;
|
||||
LARGE_INTEGER lpFrequency;
|
||||
LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2;
|
||||
int del = 0x7FFFFFFF;
|
||||
double avg, sum_avg;
|
||||
/* estimate overhead of calling performance counters */
|
||||
for( k = 0; k < 1000; k++ ) {
|
||||
QueryPerformanceCounter(&lpPerformanceCount1);
|
||||
QueryPerformanceCounter(&lpPerformanceCount2);
|
||||
lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart;
|
||||
if( (int)lpPerformanceCount2.LowPart < del )
|
||||
del = lpPerformanceCount2.LowPart;
|
||||
}
|
||||
QueryPerformanceFrequency(&lpFrequency);
|
||||
/* print results to file */
|
||||
sum_avg = 0.0f;
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) {
|
||||
if (silk_Timer_depth[k] == 0) {
|
||||
sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k];
|
||||
}
|
||||
}
|
||||
fp = fopen(file_name, "w");
|
||||
fprintf(fp, " min avg %% max count\n");
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) {
|
||||
if (silk_Timer_depth[k] == 0) {
|
||||
fprintf(fp, "%-28s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 1) {
|
||||
fprintf(fp, " %-27s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 2) {
|
||||
fprintf(fp, " %-26s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 3) {
|
||||
fprintf(fp, " %-25s", silk_Timer_tags[k]);
|
||||
} else {
|
||||
fprintf(fp, " %-24s", silk_Timer_tags[k]);
|
||||
}
|
||||
avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart;
|
||||
fprintf(fp, "%8.2f", (1e6 * (silk_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart);
|
||||
fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]);
|
||||
fprintf(fp, "%12.2f", (1e6 * (silk_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart);
|
||||
fprintf(fp, "%10d\n", silk_Timer_cnt[k]);
|
||||
}
|
||||
fprintf(fp, " microseconds\n");
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void silk_TimerSave(char *file_name)
|
||||
{
|
||||
if( silk_Timer_nTimers > 0 )
|
||||
{
|
||||
int k;
|
||||
FILE *fp;
|
||||
/* print results to file */
|
||||
fp = fopen(file_name, "w");
|
||||
fprintf(fp, " min avg max count\n");
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ )
|
||||
{
|
||||
if (silk_Timer_depth[k] == 0) {
|
||||
fprintf(fp, "%-28s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 1) {
|
||||
fprintf(fp, " %-27s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 2) {
|
||||
fprintf(fp, " %-26s", silk_Timer_tags[k]);
|
||||
} else if (silk_Timer_depth[k] == 3) {
|
||||
fprintf(fp, " %-25s", silk_Timer_tags[k]);
|
||||
} else {
|
||||
fprintf(fp, " %-24s", silk_Timer_tags[k]);
|
||||
}
|
||||
fprintf(fp, "%d ", silk_Timer_min[k]);
|
||||
fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]);
|
||||
fprintf(fp, "%d ", silk_Timer_max[k]);
|
||||
fprintf(fp, "%10d\n", silk_Timer_cnt[k]);
|
||||
}
|
||||
fprintf(fp, " microseconds\n");
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SILK_TIC_TOC */
|
||||
|
||||
#if SILK_DEBUG
|
||||
FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
|
||||
int silk_debug_store_count = 0;
|
||||
#endif /* SILK_DEBUG */
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_DEBUG_H
|
||||
#define SILK_DEBUG_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#endif
|
||||
|
||||
#include "typedef.h"
|
||||
#include <stdio.h> /* file writing */
|
||||
#include <string.h> /* strcpy, strcmp */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
unsigned long GetHighResolutionTime(void); /* O time in usec*/
|
||||
|
||||
/* make SILK_DEBUG dependent on compiler's _DEBUG */
|
||||
#if defined _WIN32
|
||||
#ifdef _DEBUG
|
||||
#define SILK_DEBUG 1
|
||||
#else
|
||||
#define SILK_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* overrule the above */
|
||||
#if 0
|
||||
/* #define NO_ASSERTS*/
|
||||
#undef SILK_DEBUG
|
||||
#define SILK_DEBUG 1
|
||||
#endif
|
||||
#else
|
||||
#define SILK_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* Flag for using timers */
|
||||
#define SILK_TIC_TOC 0
|
||||
|
||||
|
||||
#if SILK_TIC_TOC
|
||||
|
||||
#if (defined(_WIN32) || defined(_WINCE))
|
||||
#include <windows.h> /* timer */
|
||||
#pragma warning( disable : 4996 ) /* stop bitching about strcpy in TIC()*/
|
||||
#else /* Linux or Mac*/
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*********************************/
|
||||
/* timer functions for profiling */
|
||||
/*********************************/
|
||||
/* example: */
|
||||
/* */
|
||||
/* TIC(LPC) */
|
||||
/* do_LPC(in_vec, order, acoef); // do LPC analysis */
|
||||
/* TOC(LPC) */
|
||||
/* */
|
||||
/* and call the following just before exiting (from main) */
|
||||
/* */
|
||||
/* silk_TimerSave("silk_TimingData.txt"); */
|
||||
/* */
|
||||
/* results are now in silk_TimingData.txt */
|
||||
|
||||
void silk_TimerSave(char *file_name);
|
||||
|
||||
/* max number of timers (in different locations) */
|
||||
#define silk_NUM_TIMERS_MAX 50
|
||||
/* max length of name tags in TIC(..), TOC(..) */
|
||||
#define silk_NUM_TIMERS_MAX_TAG_LEN 30
|
||||
|
||||
extern int silk_Timer_nTimers;
|
||||
extern int silk_Timer_depth_ctr;
|
||||
extern char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
|
||||
#ifdef _WIN32
|
||||
extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
#else
|
||||
extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
#endif
|
||||
extern unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX];
|
||||
extern opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX];
|
||||
extern opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX];
|
||||
extern opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX];
|
||||
extern opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX];
|
||||
|
||||
/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */
|
||||
#ifdef _WIN32
|
||||
#define TIC(TAG_NAME) { \
|
||||
static int init = 0; \
|
||||
static int ID = -1; \
|
||||
if( init == 0 ) \
|
||||
{ \
|
||||
int k; \
|
||||
init = 1; \
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) { \
|
||||
if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
|
||||
ID = k; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (ID == -1) { \
|
||||
ID = silk_Timer_nTimers; \
|
||||
silk_Timer_nTimers++; \
|
||||
silk_Timer_depth[ID] = silk_Timer_depth_ctr; \
|
||||
strcpy(silk_Timer_tags[ID], #TAG_NAME); \
|
||||
silk_Timer_cnt[ID] = 0; \
|
||||
silk_Timer_sum[ID] = 0; \
|
||||
silk_Timer_min[ID] = 0xFFFFFFFF; \
|
||||
silk_Timer_max[ID] = 0; \
|
||||
} \
|
||||
} \
|
||||
silk_Timer_depth_ctr++; \
|
||||
QueryPerformanceCounter(&silk_Timer_start[ID]); \
|
||||
}
|
||||
#else
|
||||
#define TIC(TAG_NAME) { \
|
||||
static int init = 0; \
|
||||
static int ID = -1; \
|
||||
if( init == 0 ) \
|
||||
{ \
|
||||
int k; \
|
||||
init = 1; \
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) { \
|
||||
if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
|
||||
ID = k; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (ID == -1) { \
|
||||
ID = silk_Timer_nTimers; \
|
||||
silk_Timer_nTimers++; \
|
||||
silk_Timer_depth[ID] = silk_Timer_depth_ctr; \
|
||||
strcpy(silk_Timer_tags[ID], #TAG_NAME); \
|
||||
silk_Timer_cnt[ID] = 0; \
|
||||
silk_Timer_sum[ID] = 0; \
|
||||
silk_Timer_min[ID] = 0xFFFFFFFF; \
|
||||
silk_Timer_max[ID] = 0; \
|
||||
} \
|
||||
} \
|
||||
silk_Timer_depth_ctr++; \
|
||||
silk_Timer_start[ID] = GetHighResolutionTime(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define TOC(TAG_NAME) { \
|
||||
LARGE_INTEGER lpPerformanceCount; \
|
||||
static int init = 0; \
|
||||
static int ID = 0; \
|
||||
if( init == 0 ) \
|
||||
{ \
|
||||
int k; \
|
||||
init = 1; \
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) { \
|
||||
if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
|
||||
ID = k; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
QueryPerformanceCounter(&lpPerformanceCount); \
|
||||
lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \
|
||||
if((lpPerformanceCount.QuadPart < 100000000) && \
|
||||
(lpPerformanceCount.QuadPart >= 0)) { \
|
||||
silk_Timer_cnt[ID]++; \
|
||||
silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \
|
||||
if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \
|
||||
silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \
|
||||
if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \
|
||||
silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \
|
||||
} \
|
||||
silk_Timer_depth_ctr--; \
|
||||
}
|
||||
#else
|
||||
#define TOC(TAG_NAME) { \
|
||||
unsigned long endTime; \
|
||||
static int init = 0; \
|
||||
static int ID = 0; \
|
||||
if( init == 0 ) \
|
||||
{ \
|
||||
int k; \
|
||||
init = 1; \
|
||||
for( k = 0; k < silk_Timer_nTimers; k++ ) { \
|
||||
if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
|
||||
ID = k; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
endTime = GetHighResolutionTime(); \
|
||||
endTime -= silk_Timer_start[ID]; \
|
||||
if((endTime < 100000000) && \
|
||||
(endTime >= 0)) { \
|
||||
silk_Timer_cnt[ID]++; \
|
||||
silk_Timer_sum[ID] += endTime; \
|
||||
if( endTime > silk_Timer_max[ID] ) \
|
||||
silk_Timer_max[ID] = endTime; \
|
||||
if( endTime < silk_Timer_min[ID] ) \
|
||||
silk_Timer_min[ID] = endTime; \
|
||||
} \
|
||||
silk_Timer_depth_ctr--; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* SILK_TIC_TOC */
|
||||
|
||||
/* define macros as empty strings */
|
||||
#define TIC(TAG_NAME)
|
||||
#define TOC(TAG_NAME)
|
||||
#define silk_TimerSave(FILE_NAME)
|
||||
|
||||
#endif /* SILK_TIC_TOC */
|
||||
|
||||
|
||||
#if SILK_DEBUG
|
||||
/************************************/
|
||||
/* write data to file for debugging */
|
||||
/************************************/
|
||||
/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */
|
||||
|
||||
#define silk_NUM_STORES_MAX 100
|
||||
extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
|
||||
extern int silk_debug_store_count;
|
||||
|
||||
/* Faster way of storing the data */
|
||||
#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \
|
||||
static opus_int init = 0, cnt = 0; \
|
||||
static FILE **fp; \
|
||||
if (init == 0) { \
|
||||
init = 1; \
|
||||
cnt = silk_debug_store_count++; \
|
||||
silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \
|
||||
} \
|
||||
fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \
|
||||
}
|
||||
|
||||
/* Call this at the end of main() */
|
||||
#define SILK_DEBUG_STORE_CLOSE_FILES { \
|
||||
opus_int i; \
|
||||
for( i = 0; i < silk_debug_store_count; i++ ) { \
|
||||
fclose( silk_debug_store_fp[ i ] ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else /* SILK_DEBUG */
|
||||
|
||||
/* define macros as empty strings */
|
||||
#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
|
||||
#define SILK_DEBUG_STORE_CLOSE_FILES
|
||||
|
||||
#endif /* SILK_DEBUG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SILK_DEBUG_H */
|
|
@ -0,0 +1,392 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "API.h"
|
||||
#include "main.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
/************************/
|
||||
/* Decoder Super Struct */
|
||||
/************************/
|
||||
typedef struct {
|
||||
silk_decoder_state channel_state[ DECODER_NUM_CHANNELS ];
|
||||
stereo_dec_state sStereo;
|
||||
opus_int nChannelsAPI;
|
||||
opus_int nChannelsInternal;
|
||||
opus_int prev_decode_only_middle;
|
||||
} silk_decoder;
|
||||
|
||||
/*********************/
|
||||
/* Decoder functions */
|
||||
/*********************/
|
||||
|
||||
opus_int silk_Get_Decoder_Size( /* O Returns error code */
|
||||
opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
|
||||
*decSizeBytes = sizeof( silk_decoder );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset decoder state */
|
||||
opus_int silk_InitDecoder( /* O Returns error code */
|
||||
void *decState /* I/O State */
|
||||
)
|
||||
{
|
||||
opus_int n, ret = SILK_NO_ERROR;
|
||||
silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
|
||||
|
||||
for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
|
||||
ret = silk_init_decoder( &channel_state[ n ] );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Decode a frame */
|
||||
opus_int silk_Decode( /* O Returns error code */
|
||||
void* decState, /* I/O State */
|
||||
silk_DecControlStruct* decControl, /* I/O Control Structure */
|
||||
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
|
||||
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int16 *samplesOut, /* O Decoded output speech vector */
|
||||
opus_int32 *nSamplesOut /* O Number of samples decoded */
|
||||
)
|
||||
{
|
||||
opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
|
||||
opus_int32 nSamplesOutDec, LBRR_symbol;
|
||||
opus_int16 *samplesOut1_tmp[ 2 ];
|
||||
VARDECL( opus_int16, samplesOut1_tmp_storage );
|
||||
VARDECL( opus_int16, samplesOut2_tmp );
|
||||
opus_int32 MS_pred_Q13[ 2 ] = { 0 };
|
||||
opus_int16 *resample_out_ptr;
|
||||
silk_decoder *psDec = ( silk_decoder * )decState;
|
||||
silk_decoder_state *channel_state = psDec->channel_state;
|
||||
opus_int has_side;
|
||||
opus_int stereo_to_mono;
|
||||
SAVE_STACK;
|
||||
|
||||
/**********************************/
|
||||
/* Test if first frame in payload */
|
||||
/**********************************/
|
||||
if( newPacketFlag ) {
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
channel_state[ n ].nFramesDecoded = 0; /* Used to count frames in packet */
|
||||
}
|
||||
}
|
||||
|
||||
/* If Mono -> Stereo transition in bitstream: init state of second channel */
|
||||
if( decControl->nChannelsInternal > psDec->nChannelsInternal ) {
|
||||
ret += silk_init_decoder( &channel_state[ 1 ] );
|
||||
}
|
||||
|
||||
stereo_to_mono = decControl->nChannelsInternal == 1 && psDec->nChannelsInternal == 2 &&
|
||||
( decControl->internalSampleRate == 1000*channel_state[ 0 ].fs_kHz );
|
||||
|
||||
if( channel_state[ 0 ].nFramesDecoded == 0 ) {
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
opus_int fs_kHz_dec;
|
||||
if( decControl->payloadSize_ms == 0 ) {
|
||||
/* Assuming packet loss, use 10 ms */
|
||||
channel_state[ n ].nFramesPerPacket = 1;
|
||||
channel_state[ n ].nb_subfr = 2;
|
||||
} else if( decControl->payloadSize_ms == 10 ) {
|
||||
channel_state[ n ].nFramesPerPacket = 1;
|
||||
channel_state[ n ].nb_subfr = 2;
|
||||
} else if( decControl->payloadSize_ms == 20 ) {
|
||||
channel_state[ n ].nFramesPerPacket = 1;
|
||||
channel_state[ n ].nb_subfr = 4;
|
||||
} else if( decControl->payloadSize_ms == 40 ) {
|
||||
channel_state[ n ].nFramesPerPacket = 2;
|
||||
channel_state[ n ].nb_subfr = 4;
|
||||
} else if( decControl->payloadSize_ms == 60 ) {
|
||||
channel_state[ n ].nFramesPerPacket = 3;
|
||||
channel_state[ n ].nb_subfr = 4;
|
||||
} else {
|
||||
silk_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_DEC_INVALID_FRAME_SIZE;
|
||||
}
|
||||
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
|
||||
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
|
||||
silk_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
|
||||
}
|
||||
ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate );
|
||||
}
|
||||
}
|
||||
|
||||
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) {
|
||||
silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) );
|
||||
silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) );
|
||||
silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
|
||||
}
|
||||
psDec->nChannelsAPI = decControl->nChannelsAPI;
|
||||
psDec->nChannelsInternal = decControl->nChannelsInternal;
|
||||
|
||||
if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) {
|
||||
ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;
|
||||
RESTORE_STACK;
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) {
|
||||
/* First decoder call for this payload */
|
||||
/* Decode VAD flags and LBRR flag */
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
|
||||
channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1);
|
||||
}
|
||||
channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1);
|
||||
}
|
||||
/* Decode LBRR flags */
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) );
|
||||
if( channel_state[ n ].LBRR_flag ) {
|
||||
if( channel_state[ n ].nFramesPerPacket == 1 ) {
|
||||
channel_state[ n ].LBRR_flags[ 0 ] = 1;
|
||||
} else {
|
||||
LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1;
|
||||
for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
|
||||
channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( lostFlag == FLAG_DECODE_NORMAL ) {
|
||||
/* Regular decoding: skip all LBRR data */
|
||||
for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) {
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
if( channel_state[ n ].LBRR_flags[ i ] ) {
|
||||
opus_int pulses[ MAX_FRAME_LENGTH ];
|
||||
opus_int condCoding;
|
||||
|
||||
if( decControl->nChannelsInternal == 2 && n == 0 ) {
|
||||
silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
|
||||
if( channel_state[ 1 ].LBRR_flags[ i ] == 0 ) {
|
||||
silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
|
||||
}
|
||||
}
|
||||
/* Use conditional coding if previous frame available */
|
||||
if( i > 0 && channel_state[ n ].LBRR_flags[ i - 1 ] ) {
|
||||
condCoding = CODE_CONDITIONALLY;
|
||||
} else {
|
||||
condCoding = CODE_INDEPENDENTLY;
|
||||
}
|
||||
silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1, condCoding );
|
||||
silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType,
|
||||
channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get MS predictor index */
|
||||
if( decControl->nChannelsInternal == 2 ) {
|
||||
if( lostFlag == FLAG_DECODE_NORMAL ||
|
||||
( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) )
|
||||
{
|
||||
silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
|
||||
/* For LBRR data, decode mid-only flag only if side-channel's LBRR flag is false */
|
||||
if( ( lostFlag == FLAG_DECODE_NORMAL && channel_state[ 1 ].VAD_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) ||
|
||||
( lostFlag == FLAG_DECODE_LBRR && channel_state[ 1 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) )
|
||||
{
|
||||
silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
|
||||
} else {
|
||||
decode_only_middle = 0;
|
||||
}
|
||||
} else {
|
||||
for( n = 0; n < 2; n++ ) {
|
||||
MS_pred_Q13[ n ] = psDec->sStereo.pred_prev_Q13[ n ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset side channel decoder prediction memory for first frame with side coding */
|
||||
if( decControl->nChannelsInternal == 2 && decode_only_middle == 0 && psDec->prev_decode_only_middle == 1 ) {
|
||||
silk_memset( psDec->channel_state[ 1 ].outBuf, 0, sizeof(psDec->channel_state[ 1 ].outBuf) );
|
||||
silk_memset( psDec->channel_state[ 1 ].sLPC_Q14_buf, 0, sizeof(psDec->channel_state[ 1 ].sLPC_Q14_buf) );
|
||||
psDec->channel_state[ 1 ].lagPrev = 100;
|
||||
psDec->channel_state[ 1 ].LastGainIndex = 10;
|
||||
psDec->channel_state[ 1 ].prevSignalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
psDec->channel_state[ 1 ].first_frame_after_reset = 1;
|
||||
}
|
||||
|
||||
ALLOC( samplesOut1_tmp_storage,
|
||||
decControl->nChannelsInternal*(
|
||||
channel_state[ 0 ].frame_length + 2 ),
|
||||
opus_int16 );
|
||||
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage;
|
||||
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage
|
||||
+ channel_state[ 0 ].frame_length + 2;
|
||||
|
||||
if( lostFlag == FLAG_DECODE_NORMAL ) {
|
||||
has_side = !decode_only_middle;
|
||||
} else {
|
||||
has_side = !psDec->prev_decode_only_middle
|
||||
|| (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 );
|
||||
}
|
||||
/* Call decoder for one frame */
|
||||
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
|
||||
if( n == 0 || has_side ) {
|
||||
opus_int FrameIndex;
|
||||
opus_int condCoding;
|
||||
|
||||
FrameIndex = channel_state[ 0 ].nFramesDecoded - n;
|
||||
/* Use independent coding if no previous frame available */
|
||||
if( FrameIndex <= 0 ) {
|
||||
condCoding = CODE_INDEPENDENTLY;
|
||||
} else if( lostFlag == FLAG_DECODE_LBRR ) {
|
||||
condCoding = channel_state[ n ].LBRR_flags[ FrameIndex - 1 ] ? CODE_CONDITIONALLY : CODE_INDEPENDENTLY;
|
||||
} else if( n > 0 && psDec->prev_decode_only_middle ) {
|
||||
/* If we skipped a side frame in this packet, we don't
|
||||
need LTP scaling; the LTP state is well-defined. */
|
||||
condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING;
|
||||
} else {
|
||||
condCoding = CODE_CONDITIONALLY;
|
||||
}
|
||||
ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding);
|
||||
} else {
|
||||
silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
|
||||
}
|
||||
channel_state[ n ].nFramesDecoded++;
|
||||
}
|
||||
|
||||
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
|
||||
/* Convert Mid/Side to Left/Right */
|
||||
silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec );
|
||||
} else {
|
||||
/* Buffering */
|
||||
silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
|
||||
silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
|
||||
}
|
||||
|
||||
/* Number of output samples */
|
||||
*nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
|
||||
|
||||
/* Set up pointers to temp buffers */
|
||||
ALLOC( samplesOut2_tmp,
|
||||
decControl->nChannelsAPI == 2 ? *nSamplesOut : 0, opus_int16 );
|
||||
if( decControl->nChannelsAPI == 2 ) {
|
||||
resample_out_ptr = samplesOut2_tmp;
|
||||
} else {
|
||||
resample_out_ptr = samplesOut;
|
||||
}
|
||||
|
||||
for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
|
||||
|
||||
/* Resample decoded signal to API_sampleRate */
|
||||
ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
|
||||
|
||||
/* Interleave if stereo output and stereo stream */
|
||||
if( decControl->nChannelsAPI == 2 ) {
|
||||
for( i = 0; i < *nSamplesOut; i++ ) {
|
||||
samplesOut[ n + 2 * i ] = resample_out_ptr[ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create two channel output from mono stream */
|
||||
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) {
|
||||
if ( stereo_to_mono ){
|
||||
/* Resample right channel for newly collapsed stereo just in case
|
||||
we weren't doing collapsing when switching to mono */
|
||||
ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec );
|
||||
|
||||
for( i = 0; i < *nSamplesOut; i++ ) {
|
||||
samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ];
|
||||
}
|
||||
} else {
|
||||
for( i = 0; i < *nSamplesOut; i++ ) {
|
||||
samplesOut[ 1 + 2 * i ] = samplesOut[ 0 + 2 * i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Export pitch lag, measured at 48 kHz sampling rate */
|
||||
if( channel_state[ 0 ].prevSignalType == TYPE_VOICED ) {
|
||||
int mult_tab[ 3 ] = { 6, 4, 3 };
|
||||
decControl->prevPitchLag = channel_state[ 0 ].lagPrev * mult_tab[ ( channel_state[ 0 ].fs_kHz - 8 ) >> 2 ];
|
||||
} else {
|
||||
decControl->prevPitchLag = 0;
|
||||
}
|
||||
|
||||
if( lostFlag == FLAG_PACKET_LOST ) {
|
||||
/* On packet loss, remove the gain clamping to prevent having the energy "bounce back"
|
||||
if we lose packets when the energy is going down */
|
||||
for ( i = 0; i < psDec->nChannelsInternal; i++ )
|
||||
psDec->channel_state[ i ].LastGainIndex = 10;
|
||||
} else {
|
||||
psDec->prev_decode_only_middle = decode_only_middle;
|
||||
}
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Getting table of contents for a packet */
|
||||
opus_int silk_get_TOC(
|
||||
const opus_uint8 *payload, /* I Payload data */
|
||||
const opus_int nBytesIn, /* I Number of input bytes */
|
||||
const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
|
||||
silk_TOC_struct *Silk_TOC /* O Type of content */
|
||||
)
|
||||
{
|
||||
opus_int i, flags, ret = SILK_NO_ERROR;
|
||||
|
||||
if( nBytesIn < 1 ) {
|
||||
return -1;
|
||||
}
|
||||
if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
silk_memset( Silk_TOC, 0, sizeof( *Silk_TOC ) );
|
||||
|
||||
/* For stereo, extract the flags for the mid channel */
|
||||
flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 );
|
||||
|
||||
Silk_TOC->inbandFECFlag = flags & 1;
|
||||
for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) {
|
||||
flags = silk_RSHIFT( flags, 1 );
|
||||
Silk_TOC->VADFlags[ i ] = flags & 1;
|
||||
Silk_TOC->VADFlag |= flags & 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,238 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
/**********************************************************/
|
||||
/* Core decoder. Performs inverse NSQ operation LTP + LPC */
|
||||
/**********************************************************/
|
||||
void silk_decode_core(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state */
|
||||
silk_decoder_control *psDecCtrl, /* I Decoder control */
|
||||
opus_int16 xq[], /* O Decoded speech */
|
||||
const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */
|
||||
)
|
||||
{
|
||||
opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
|
||||
opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
|
||||
VARDECL( opus_int16, sLTP );
|
||||
VARDECL( opus_int32, sLTP_Q15 );
|
||||
opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
|
||||
opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14;
|
||||
VARDECL( opus_int32, res_Q14 );
|
||||
VARDECL( opus_int32, sLPC_Q14 );
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( psDec->prev_gain_Q16 != 0 );
|
||||
|
||||
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
|
||||
ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
|
||||
ALLOC( res_Q14, psDec->subfr_length, opus_int32 );
|
||||
ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 );
|
||||
|
||||
offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
|
||||
|
||||
if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
|
||||
NLSF_interpolation_flag = 1;
|
||||
} else {
|
||||
NLSF_interpolation_flag = 0;
|
||||
}
|
||||
|
||||
/* Decode excitation */
|
||||
rand_seed = psDec->indices.Seed;
|
||||
for( i = 0; i < psDec->frame_length; i++ ) {
|
||||
rand_seed = silk_RAND( rand_seed );
|
||||
psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 );
|
||||
if( psDec->exc_Q14[ i ] > 0 ) {
|
||||
psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4;
|
||||
} else
|
||||
if( psDec->exc_Q14[ i ] < 0 ) {
|
||||
psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
|
||||
}
|
||||
psDec->exc_Q14[ i ] += offset_Q10 << 4;
|
||||
if( rand_seed < 0 ) {
|
||||
psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
|
||||
}
|
||||
|
||||
rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
|
||||
}
|
||||
|
||||
/* Copy LPC state */
|
||||
silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
|
||||
pexc_Q14 = psDec->exc_Q14;
|
||||
pxq = xq;
|
||||
sLTP_buf_idx = psDec->ltp_mem_length;
|
||||
/* Loop over subframes */
|
||||
for( k = 0; k < psDec->nb_subfr; k++ ) {
|
||||
pres_Q14 = res_Q14;
|
||||
A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
|
||||
|
||||
/* Preload LPC coeficients to array on stack. Gives small performance gain */
|
||||
silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
|
||||
signalType = psDec->indices.signalType;
|
||||
|
||||
Gain_Q10 = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
|
||||
inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 );
|
||||
|
||||
/* Calculate gain adjustment factor */
|
||||
if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 );
|
||||
|
||||
/* Scale short term state */
|
||||
for( i = 0; i < MAX_LPC_ORDER; i++ ) {
|
||||
sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] );
|
||||
}
|
||||
} else {
|
||||
gain_adj_Q16 = (opus_int32)1 << 16;
|
||||
}
|
||||
|
||||
/* Save inv_gain */
|
||||
silk_assert( inv_gain_Q31 != 0 );
|
||||
psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ];
|
||||
|
||||
/* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
|
||||
if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
|
||||
psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
|
||||
|
||||
silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
|
||||
B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
|
||||
|
||||
signalType = TYPE_VOICED;
|
||||
psDecCtrl->pitchL[ k ] = psDec->lagPrev;
|
||||
}
|
||||
|
||||
if( signalType == TYPE_VOICED ) {
|
||||
/* Voiced */
|
||||
lag = psDecCtrl->pitchL[ k ];
|
||||
|
||||
/* Re-whitening */
|
||||
if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
|
||||
if( k == 2 ) {
|
||||
silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
|
||||
}
|
||||
|
||||
silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
|
||||
A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order );
|
||||
|
||||
/* After rewhitening the LTP state is unscaled */
|
||||
if( k == 0 ) {
|
||||
/* Do LTP downscaling to reduce inter-packet dependency */
|
||||
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
|
||||
}
|
||||
for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
|
||||
sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
|
||||
}
|
||||
} else {
|
||||
/* Update LTP state when Gain changes */
|
||||
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
|
||||
for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
|
||||
sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Long-term prediction */
|
||||
if( signalType == TYPE_VOICED ) {
|
||||
/* Set up pointer */
|
||||
pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
for( i = 0; i < psDec->subfr_length; i++ ) {
|
||||
/* Unrolled loop */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LTP_pred_Q13 = 2;
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
|
||||
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
|
||||
pred_lag_ptr++;
|
||||
|
||||
/* Generate LPC excitation */
|
||||
pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 );
|
||||
|
||||
/* Update states */
|
||||
sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 );
|
||||
sLTP_buf_idx++;
|
||||
}
|
||||
} else {
|
||||
pres_Q14 = pexc_Q14;
|
||||
}
|
||||
|
||||
for( i = 0; i < psDec->subfr_length; i++ ) {
|
||||
/* Short-term prediction */
|
||||
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
|
||||
if( psDec->LPC_order == 16 ) {
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
|
||||
}
|
||||
|
||||
/* Add prediction to LPC excitation */
|
||||
sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( pres_Q14[ i ], LPC_pred_Q10, 4 );
|
||||
|
||||
/* Scale with gain */
|
||||
pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
|
||||
}
|
||||
|
||||
/* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
|
||||
|
||||
/* Update LPC filter state */
|
||||
silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
pexc_Q14 += psDec->subfr_length;
|
||||
pxq += psDec->subfr_length;
|
||||
}
|
||||
|
||||
/* Save LPC state */
|
||||
silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
RESTORE_STACK;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "PLC.h"
|
||||
|
||||
/****************/
|
||||
/* Decode frame */
|
||||
/****************/
|
||||
opus_int silk_decode_frame(
|
||||
silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int16 pOut[], /* O Pointer to output speech frame */
|
||||
opus_int32 *pN, /* O Pointer to size of output frame */
|
||||
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
|
||||
opus_int condCoding /* I The type of conditional coding to use */
|
||||
)
|
||||
{
|
||||
VARDECL( silk_decoder_control, psDecCtrl );
|
||||
opus_int L, mv_len, ret = 0;
|
||||
VARDECL( opus_int, pulses );
|
||||
SAVE_STACK;
|
||||
|
||||
L = psDec->frame_length;
|
||||
ALLOC( psDecCtrl, 1, silk_decoder_control );
|
||||
ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
|
||||
~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int );
|
||||
psDecCtrl->LTP_scale_Q14 = 0;
|
||||
|
||||
/* Safety checks */
|
||||
silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
|
||||
|
||||
if( lostFlag == FLAG_DECODE_NORMAL ||
|
||||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
|
||||
{
|
||||
/*********************************************/
|
||||
/* Decode quantization indices of side info */
|
||||
/*********************************************/
|
||||
silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding );
|
||||
|
||||
/*********************************************/
|
||||
/* Decode quantization indices of excitation */
|
||||
/*********************************************/
|
||||
silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType,
|
||||
psDec->indices.quantOffsetType, psDec->frame_length );
|
||||
|
||||
/********************************************/
|
||||
/* Decode parameters and pulse signal */
|
||||
/********************************************/
|
||||
silk_decode_parameters( psDec, psDecCtrl, condCoding );
|
||||
|
||||
/********************************************************/
|
||||
/* Run inverse NSQ */
|
||||
/********************************************************/
|
||||
silk_decode_core( psDec, psDecCtrl, pOut, pulses );
|
||||
|
||||
/********************************************************/
|
||||
/* Update PLC state */
|
||||
/********************************************************/
|
||||
silk_PLC( psDec, psDecCtrl, pOut, 0 );
|
||||
|
||||
psDec->lossCnt = 0;
|
||||
psDec->prevSignalType = psDec->indices.signalType;
|
||||
silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
|
||||
|
||||
/* A frame has been decoded without errors */
|
||||
psDec->first_frame_after_reset = 0;
|
||||
} else {
|
||||
/* Handle packet loss by extrapolation */
|
||||
silk_PLC( psDec, psDecCtrl, pOut, 1 );
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* Update output buffer. */
|
||||
/*************************/
|
||||
silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
|
||||
mv_len = psDec->ltp_mem_length - psDec->frame_length;
|
||||
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
|
||||
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
|
||||
|
||||
/****************************************************************/
|
||||
/* Ensure smooth connection of extrapolated and good frames */
|
||||
/****************************************************************/
|
||||
silk_PLC_glue_frames( psDec, pOut, L );
|
||||
|
||||
/************************************************/
|
||||
/* Comfort noise generation / estimation */
|
||||
/************************************************/
|
||||
silk_CNG( psDec, psDecCtrl, pOut, L );
|
||||
|
||||
/* Update some decoder state variables */
|
||||
psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];
|
||||
|
||||
/* Set output frame length */
|
||||
*pN = L;
|
||||
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Decode side-information parameters from payload */
|
||||
void silk_decode_indices(
|
||||
silk_decoder_state *psDec, /* I/O State */
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int FrameIndex, /* I Frame number */
|
||||
opus_int decode_LBRR, /* I Flag indicating LBRR data is being decoded */
|
||||
opus_int condCoding /* I The type of conditional coding to use */
|
||||
)
|
||||
{
|
||||
opus_int i, k, Ix;
|
||||
opus_int decode_absolute_lagIndex, delta_lagIndex;
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
|
||||
/*******************************************/
|
||||
/* Decode signal type and quantizer offset */
|
||||
/*******************************************/
|
||||
if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) {
|
||||
Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2;
|
||||
} else {
|
||||
Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 );
|
||||
}
|
||||
psDec->indices.signalType = (opus_int8)silk_RSHIFT( Ix, 1 );
|
||||
psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 );
|
||||
|
||||
/****************/
|
||||
/* Decode gains */
|
||||
/****************/
|
||||
/* First subframe */
|
||||
if( condCoding == CODE_CONDITIONALLY ) {
|
||||
/* Conditional coding */
|
||||
psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
|
||||
} else {
|
||||
/* Independent coding, in two stages: MSB bits followed by 3 LSBs */
|
||||
psDec->indices.GainsIndices[ 0 ] = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 );
|
||||
psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 );
|
||||
}
|
||||
|
||||
/* Remaining subframes */
|
||||
for( i = 1; i < psDec->nb_subfr; i++ ) {
|
||||
psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Decode LSF Indices */
|
||||
/**********************/
|
||||
psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
|
||||
silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
|
||||
for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
|
||||
Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
if( Ix == 0 ) {
|
||||
Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
|
||||
} else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
|
||||
}
|
||||
psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE );
|
||||
}
|
||||
|
||||
/* Decode LSF interpolation factor */
|
||||
if( psDec->nb_subfr == MAX_NB_SUBFR ) {
|
||||
psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 );
|
||||
} else {
|
||||
psDec->indices.NLSFInterpCoef_Q2 = 4;
|
||||
}
|
||||
|
||||
if( psDec->indices.signalType == TYPE_VOICED )
|
||||
{
|
||||
/*********************/
|
||||
/* Decode pitch lags */
|
||||
/*********************/
|
||||
/* Get lag index */
|
||||
decode_absolute_lagIndex = 1;
|
||||
if( condCoding == CODE_CONDITIONALLY && psDec->ec_prevSignalType == TYPE_VOICED ) {
|
||||
/* Decode Delta index */
|
||||
delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 );
|
||||
if( delta_lagIndex > 0 ) {
|
||||
delta_lagIndex = delta_lagIndex - 9;
|
||||
psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex );
|
||||
decode_absolute_lagIndex = 0;
|
||||
}
|
||||
}
|
||||
if( decode_absolute_lagIndex ) {
|
||||
/* Absolute decoding */
|
||||
psDec->indices.lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * silk_RSHIFT( psDec->fs_kHz, 1 );
|
||||
psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 );
|
||||
}
|
||||
psDec->ec_prevLagIndex = psDec->indices.lagIndex;
|
||||
|
||||
/* Get countour index */
|
||||
psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 );
|
||||
|
||||
/********************/
|
||||
/* Decode LTP gains */
|
||||
/********************/
|
||||
/* Decode PERIndex value */
|
||||
psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 );
|
||||
|
||||
for( k = 0; k < psDec->nb_subfr; k++ ) {
|
||||
psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 );
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Decode LTP scaling */
|
||||
/**********************/
|
||||
if( condCoding == CODE_INDEPENDENTLY ) {
|
||||
psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 );
|
||||
} else {
|
||||
psDec->indices.LTP_scaleIndex = 0;
|
||||
}
|
||||
}
|
||||
psDec->ec_prevSignalType = psDec->indices.signalType;
|
||||
|
||||
/***************/
|
||||
/* Decode seed */
|
||||
/***************/
|
||||
psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 );
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Decode parameters from payload */
|
||||
void silk_decode_parameters(
|
||||
silk_decoder_state *psDec, /* I/O State */
|
||||
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||
opus_int condCoding /* I The type of conditional coding to use */
|
||||
)
|
||||
{
|
||||
opus_int i, k, Ix;
|
||||
opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ];
|
||||
const opus_int8 *cbk_ptr_Q7;
|
||||
|
||||
/* Dequant Gains */
|
||||
silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices,
|
||||
&psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr );
|
||||
|
||||
/****************/
|
||||
/* Decode NLSFs */
|
||||
/****************/
|
||||
silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
|
||||
|
||||
/* Convert NLSF parameters to AR prediction filter coefficients */
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
|
||||
|
||||
/* If just reset, e.g., because internal Fs changed, do not allow interpolation */
|
||||
/* improves the case of packet loss in the first frame after a switch */
|
||||
if( psDec->first_frame_after_reset == 1 ) {
|
||||
psDec->indices.NLSFInterpCoef_Q2 = 4;
|
||||
}
|
||||
|
||||
if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) {
|
||||
/* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
|
||||
/* the previous NLSF1, and the current NLSF1 */
|
||||
for( i = 0; i < psDec->LPC_order; i++ ) {
|
||||
pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + silk_RSHIFT( silk_MUL( psDec->indices.NLSFInterpCoef_Q2,
|
||||
pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 );
|
||||
}
|
||||
|
||||
/* Convert NLSF parameters to AR prediction filter coefficients */
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
|
||||
} else {
|
||||
/* Copy LPC coefficients for first half from second half */
|
||||
silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
}
|
||||
|
||||
silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
|
||||
/* After a packet loss do BWE of LPC coefs */
|
||||
if( psDec->lossCnt ) {
|
||||
silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
|
||||
silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
|
||||
}
|
||||
|
||||
if( psDec->indices.signalType == TYPE_VOICED ) {
|
||||
/*********************/
|
||||
/* Decode pitch lags */
|
||||
/*********************/
|
||||
|
||||
/* Decode pitch values */
|
||||
silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr );
|
||||
|
||||
/* Decode Codebook Index */
|
||||
cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */
|
||||
|
||||
for( k = 0; k < psDec->nb_subfr; k++ ) {
|
||||
Ix = psDec->indices.LTPIndex[ k ];
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = silk_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 );
|
||||
}
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Decode LTP scaling */
|
||||
/**********************/
|
||||
Ix = psDec->indices.LTP_scaleIndex;
|
||||
psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ];
|
||||
} else {
|
||||
silk_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( opus_int ) );
|
||||
silk_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) );
|
||||
psDec->indices.PERIndex = 0;
|
||||
psDecCtrl->LTP_scale_Q14 = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/***********************************************************
|
||||
* Pitch analyser function
|
||||
********************************************************** */
|
||||
#include "SigProc_FIX.h"
|
||||
#include "pitch_est_defines.h"
|
||||
|
||||
void silk_decode_pitch(
|
||||
opus_int16 lagIndex, /* I */
|
||||
opus_int8 contourIndex, /* O */
|
||||
opus_int pitch_lags[], /* O 4 pitch values */
|
||||
const opus_int Fs_kHz, /* I sampling frequency (kHz) */
|
||||
const opus_int nb_subfr /* I number of sub frames */
|
||||
)
|
||||
{
|
||||
opus_int lag, k, min_lag, max_lag, cbk_size;
|
||||
const opus_int8 *Lag_CB_ptr;
|
||||
|
||||
if( Fs_kHz == 8 ) {
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE2_EXT;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE2_10MS;
|
||||
}
|
||||
} else {
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_10MS;
|
||||
}
|
||||
}
|
||||
|
||||
min_lag = silk_SMULBB( PE_MIN_LAG_MS, Fs_kHz );
|
||||
max_lag = silk_SMULBB( PE_MAX_LAG_MS, Fs_kHz );
|
||||
lag = min_lag + lagIndex;
|
||||
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size );
|
||||
pitch_lags[ k ] = silk_LIMIT( pitch_lags[ k ], min_lag, max_lag );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Decode quantization indices of excitation */
|
||||
/*********************************************/
|
||||
void silk_decode_pulses(
|
||||
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
||||
opus_int pulses[], /* O Excitation signal */
|
||||
const opus_int signalType, /* I Sigtype */
|
||||
const opus_int quantOffsetType, /* I quantOffsetType */
|
||||
const opus_int frame_length /* I Frame length */
|
||||
)
|
||||
{
|
||||
opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex;
|
||||
opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
|
||||
opus_int *pulses_ptr;
|
||||
const opus_uint8 *cdf_ptr;
|
||||
|
||||
/*********************/
|
||||
/* Decode rate level */
|
||||
/*********************/
|
||||
RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
|
||||
|
||||
/* Calculate number of shell blocks */
|
||||
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
|
||||
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
|
||||
silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
iter++;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
/* Sum-Weighted-Pulses Decoding */
|
||||
/***************************************************/
|
||||
cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
nLshifts[ i ] = 0;
|
||||
sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
|
||||
|
||||
/* LSB indication */
|
||||
while( sum_pulses[ i ] == MAX_PULSES + 1 ) {
|
||||
nLshifts[ i ]++;
|
||||
/* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */
|
||||
sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
|
||||
silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + ( nLshifts[ i ] == 10 ), 8 );
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
/* Shell decoding */
|
||||
/***************************************************/
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( sum_pulses[ i ] > 0 ) {
|
||||
silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
|
||||
} else {
|
||||
silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) );
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
/* LSB Decoding */
|
||||
/***************************************************/
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( nLshifts[ i ] > 0 ) {
|
||||
nLS = nLshifts[ i ];
|
||||
pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
|
||||
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
|
||||
abs_q = pulses_ptr[ k ];
|
||||
for( j = 0; j < nLS; j++ ) {
|
||||
abs_q = silk_LSHIFT( abs_q, 1 );
|
||||
abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 );
|
||||
}
|
||||
pulses_ptr[ k ] = abs_q;
|
||||
}
|
||||
/* Mark the number of pulses non-zero for sign decoding. */
|
||||
sum_pulses[ i ] |= nLS << 5;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
/* Decode and add signs to pulse signal */
|
||||
/****************************************/
|
||||
silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Set decoder sampling rate */
|
||||
opus_int silk_decoder_set_fs(
|
||||
silk_decoder_state *psDec, /* I/O Decoder state pointer */
|
||||
opus_int fs_kHz, /* I Sampling frequency (kHz) */
|
||||
opus_int32 fs_API_Hz /* I API Sampling frequency (Hz) */
|
||||
)
|
||||
{
|
||||
opus_int frame_length, ret = 0;
|
||||
|
||||
silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
|
||||
|
||||
/* New (sub)frame length */
|
||||
psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
|
||||
frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length );
|
||||
|
||||
/* Initialize resampler when switching internal or external sampling frequency */
|
||||
if( psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz ) {
|
||||
/* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */
|
||||
ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 );
|
||||
|
||||
psDec->fs_API_hz = fs_API_Hz;
|
||||
}
|
||||
|
||||
if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) {
|
||||
if( fs_kHz == 8 ) {
|
||||
if( psDec->nb_subfr == MAX_NB_SUBFR ) {
|
||||
psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
|
||||
} else {
|
||||
psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
|
||||
}
|
||||
} else {
|
||||
if( psDec->nb_subfr == MAX_NB_SUBFR ) {
|
||||
psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF;
|
||||
} else {
|
||||
psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
|
||||
}
|
||||
}
|
||||
if( psDec->fs_kHz != fs_kHz ) {
|
||||
psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
|
||||
if( fs_kHz == 8 || fs_kHz == 12 ) {
|
||||
psDec->LPC_order = MIN_LPC_ORDER;
|
||||
psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB;
|
||||
} else {
|
||||
psDec->LPC_order = MAX_LPC_ORDER;
|
||||
psDec->psNLSF_CB = &silk_NLSF_CB_WB;
|
||||
}
|
||||
if( fs_kHz == 16 ) {
|
||||
psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
|
||||
} else if( fs_kHz == 12 ) {
|
||||
psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
|
||||
} else if( fs_kHz == 8 ) {
|
||||
psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
|
||||
} else {
|
||||
/* unsupported sampling rate */
|
||||
silk_assert( 0 );
|
||||
}
|
||||
psDec->first_frame_after_reset = 1;
|
||||
psDec->lagPrev = 100;
|
||||
psDec->LastGainIndex = 10;
|
||||
psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
silk_memset( psDec->outBuf, 0, sizeof(psDec->outBuf));
|
||||
silk_memset( psDec->sLPC_Q14_buf, 0, sizeof(psDec->sLPC_Q14_buf) );
|
||||
}
|
||||
|
||||
psDec->fs_kHz = fs_kHz;
|
||||
psDec->frame_length = frame_length;
|
||||
}
|
||||
|
||||
/* Check that settings are valid */
|
||||
silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_DEFINE_H
|
||||
#define SILK_DEFINE_H
|
||||
|
||||
#include "errors.h"
|
||||
#include "typedef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Max number of encoder channels (1/2) */
|
||||
#define ENCODER_NUM_CHANNELS 2
|
||||
/* Number of decoder channels (1/2) */
|
||||
#define DECODER_NUM_CHANNELS 2
|
||||
|
||||
#define MAX_FRAMES_PER_PACKET 3
|
||||
|
||||
/* Limits on bitrate */
|
||||
#define MIN_TARGET_RATE_BPS 5000
|
||||
#define MAX_TARGET_RATE_BPS 80000
|
||||
#define TARGET_RATE_TAB_SZ 8
|
||||
|
||||
/* LBRR thresholds */
|
||||
#define LBRR_NB_MIN_RATE_BPS 12000
|
||||
#define LBRR_MB_MIN_RATE_BPS 14000
|
||||
#define LBRR_WB_MIN_RATE_BPS 16000
|
||||
|
||||
/* DTX settings */
|
||||
#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */
|
||||
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
|
||||
|
||||
/* Maximum sampling frequency */
|
||||
#define MAX_FS_KHZ 16
|
||||
#define MAX_API_FS_KHZ 48
|
||||
|
||||
/* Signal types */
|
||||
#define TYPE_NO_VOICE_ACTIVITY 0
|
||||
#define TYPE_UNVOICED 1
|
||||
#define TYPE_VOICED 2
|
||||
|
||||
/* Conditional coding types */
|
||||
#define CODE_INDEPENDENTLY 0
|
||||
#define CODE_INDEPENDENTLY_NO_LTP_SCALING 1
|
||||
#define CODE_CONDITIONALLY 2
|
||||
|
||||
/* Settings for stereo processing */
|
||||
#define STEREO_QUANT_TAB_SIZE 16
|
||||
#define STEREO_QUANT_SUB_STEPS 5
|
||||
#define STEREO_INTERP_LEN_MS 8 /* must be even */
|
||||
#define STEREO_RATIO_SMOOTH_COEF 0.01 /* smoothing coef for signal norms and stereo width */
|
||||
|
||||
/* Range of pitch lag estimates */
|
||||
#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */
|
||||
#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */
|
||||
|
||||
/* Maximum number of subframes */
|
||||
#define MAX_NB_SUBFR 4
|
||||
|
||||
/* Number of samples per frame */
|
||||
#define LTP_MEM_LENGTH_MS 20
|
||||
#define SUB_FRAME_LENGTH_MS 5
|
||||
#define MAX_SUB_FRAME_LENGTH ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ )
|
||||
#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR )
|
||||
#define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ )
|
||||
|
||||
/* Milliseconds of lookahead for pitch analysis */
|
||||
#define LA_PITCH_MS 2
|
||||
#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ )
|
||||
|
||||
/* Order of LPC used in find pitch */
|
||||
#define MAX_FIND_PITCH_LPC_ORDER 16
|
||||
|
||||
/* Length of LPC window used in find pitch */
|
||||
#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) )
|
||||
#define FIND_PITCH_LPC_WIN_MS_2_SF ( 10 + (LA_PITCH_MS << 1) )
|
||||
#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ )
|
||||
|
||||
/* Milliseconds of lookahead for noise shape analysis */
|
||||
#define LA_SHAPE_MS 5
|
||||
#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ )
|
||||
|
||||
/* Maximum length of LPC window used in noise shape analysis */
|
||||
#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ )
|
||||
|
||||
/* dB level of lowest gain quantization level */
|
||||
#define MIN_QGAIN_DB 2
|
||||
/* dB level of highest gain quantization level */
|
||||
#define MAX_QGAIN_DB 88
|
||||
/* Number of gain quantization levels */
|
||||
#define N_LEVELS_QGAIN 64
|
||||
/* Max increase in gain quantization index */
|
||||
#define MAX_DELTA_GAIN_QUANT 36
|
||||
/* Max decrease in gain quantization index */
|
||||
#define MIN_DELTA_GAIN_QUANT -4
|
||||
|
||||
/* Quantization offsets (multiples of 4) */
|
||||
#define OFFSET_VL_Q10 32
|
||||
#define OFFSET_VH_Q10 100
|
||||
#define OFFSET_UVL_Q10 100
|
||||
#define OFFSET_UVH_Q10 240
|
||||
|
||||
#define QUANT_LEVEL_ADJUST_Q10 80
|
||||
|
||||
/* Maximum numbers of iterations used to stabilize an LPC vector */
|
||||
#define MAX_LPC_STABILIZE_ITERATIONS 16
|
||||
#define MAX_PREDICTION_POWER_GAIN 1e4f
|
||||
#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET 1e2f
|
||||
|
||||
#define MAX_LPC_ORDER 16
|
||||
#define MIN_LPC_ORDER 10
|
||||
|
||||
/* Find Pred Coef defines */
|
||||
#define LTP_ORDER 5
|
||||
|
||||
/* LTP quantization settings */
|
||||
#define NB_LTP_CBKS 3
|
||||
|
||||
/* Flag to use harmonic noise shaping */
|
||||
#define USE_HARM_SHAPING 1
|
||||
|
||||
/* Max LPC order of noise shaping filters */
|
||||
#define MAX_SHAPE_LPC_ORDER 16
|
||||
|
||||
#define HARM_SHAPE_FIR_TAPS 3
|
||||
|
||||
/* Maximum number of delayed decision states */
|
||||
#define MAX_DEL_DEC_STATES 4
|
||||
|
||||
#define LTP_BUF_LENGTH 512
|
||||
#define LTP_MASK ( LTP_BUF_LENGTH - 1 )
|
||||
|
||||
#define DECISION_DELAY 32
|
||||
#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 )
|
||||
|
||||
/* Number of subframes for excitation entropy coding */
|
||||
#define SHELL_CODEC_FRAME_LENGTH 16
|
||||
#define LOG2_SHELL_CODEC_FRAME_LENGTH 4
|
||||
#define MAX_NB_SHELL_BLOCKS ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH )
|
||||
|
||||
/* Number of rate levels, for entropy coding of excitation */
|
||||
#define N_RATE_LEVELS 10
|
||||
|
||||
/* Maximum sum of pulses per shell coding frame */
|
||||
#define MAX_PULSES 16
|
||||
|
||||
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
|
||||
|
||||
#if( MAX_LPC_ORDER > DECISION_DELAY )
|
||||
# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
|
||||
#else
|
||||
# define NSQ_LPC_BUF_LENGTH DECISION_DELAY
|
||||
#endif
|
||||
|
||||
/***************************/
|
||||
/* Voice activity detector */
|
||||
/***************************/
|
||||
#define VAD_N_BANDS 4
|
||||
|
||||
#define VAD_INTERNAL_SUBFRAMES_LOG2 2
|
||||
#define VAD_INTERNAL_SUBFRAMES ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 )
|
||||
|
||||
#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */
|
||||
#define VAD_NOISE_LEVELS_BIAS 50
|
||||
|
||||
/* Sigmoid settings */
|
||||
#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */
|
||||
#define VAD_SNR_FACTOR_Q16 45000
|
||||
|
||||
/* smoothing for SNR measurement */
|
||||
#define VAD_SNR_SMOOTH_COEF_Q18 4096
|
||||
|
||||
/* Size of the piecewise linear cosine approximation table for the LSFs */
|
||||
#define LSF_COS_TAB_SZ_FIX 128
|
||||
|
||||
/******************/
|
||||
/* NLSF quantizer */
|
||||
/******************/
|
||||
#define NLSF_W_Q 2
|
||||
#define NLSF_VQ_MAX_VECTORS 32
|
||||
#define NLSF_VQ_MAX_SURVIVORS 32
|
||||
#define NLSF_QUANT_MAX_AMPLITUDE 4
|
||||
#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10
|
||||
#define NLSF_QUANT_LEVEL_ADJ 0.1
|
||||
#define NLSF_QUANT_DEL_DEC_STATES_LOG2 2
|
||||
#define NLSF_QUANT_DEL_DEC_STATES ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 )
|
||||
|
||||
/* Transition filtering for mode switching */
|
||||
#define TRANSITION_TIME_MS 5120 /* 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)*/
|
||||
#define TRANSITION_NB 3 /* Hardcoded in tables */
|
||||
#define TRANSITION_NA 2 /* Hardcoded in tables */
|
||||
#define TRANSITION_INT_NUM 5 /* Hardcoded in tables */
|
||||
#define TRANSITION_FRAMES ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS )
|
||||
#define TRANSITION_INT_STEPS ( TRANSITION_FRAMES / ( TRANSITION_INT_NUM - 1 ) )
|
||||
|
||||
/* BWE factors to apply after packet loss */
|
||||
#define BWE_AFTER_LOSS_Q16 63570
|
||||
|
||||
/* Defines for CN generation */
|
||||
#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */
|
||||
#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */
|
||||
#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,538 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "define.h"
|
||||
#include "API.h"
|
||||
#include "control.h"
|
||||
#include "typedef.h"
|
||||
#include "structs.h"
|
||||
#include "tuning_parameters.h"
|
||||
#ifdef FIXED_POINT
|
||||
#include "main_FIX.h"
|
||||
#else
|
||||
#include "main_FLP.h"
|
||||
#endif
|
||||
|
||||
/***************************************/
|
||||
/* Read control structure from encoder */
|
||||
/***************************************/
|
||||
static opus_int silk_QueryEncoder( /* O Returns error code */
|
||||
const void *encState, /* I State */
|
||||
silk_EncControlStruct *encStatus /* O Encoder Status */
|
||||
);
|
||||
|
||||
/****************************************/
|
||||
/* Encoder functions */
|
||||
/****************************************/
|
||||
|
||||
opus_int silk_Get_Encoder_Size( /* O Returns error code */
|
||||
opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
|
||||
*encSizeBytes = sizeof( silk_encoder );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* Init or Reset encoder */
|
||||
/*************************/
|
||||
opus_int silk_InitEncoder( /* O Returns error code */
|
||||
void *encState, /* I/O State */
|
||||
silk_EncControlStruct *encStatus /* O Encoder Status */
|
||||
)
|
||||
{
|
||||
silk_encoder *psEnc;
|
||||
opus_int n, ret = SILK_NO_ERROR;
|
||||
|
||||
psEnc = (silk_encoder *)encState;
|
||||
|
||||
/* Reset encoder */
|
||||
silk_memset( psEnc, 0, sizeof( silk_encoder ) );
|
||||
for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) {
|
||||
if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) {
|
||||
silk_assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
psEnc->nChannelsAPI = 1;
|
||||
psEnc->nChannelsInternal = 1;
|
||||
|
||||
/* Read control structure */
|
||||
if( ret += silk_QueryEncoder( encState, encStatus ) ) {
|
||||
silk_assert( 0 );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
/* Read control structure from encoder */
|
||||
/***************************************/
|
||||
static opus_int silk_QueryEncoder( /* O Returns error code */
|
||||
const void *encState, /* I State */
|
||||
silk_EncControlStruct *encStatus /* O Encoder Status */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
silk_encoder_state_Fxx *state_Fxx;
|
||||
silk_encoder *psEnc = (silk_encoder *)encState;
|
||||
|
||||
state_Fxx = psEnc->state_Fxx;
|
||||
|
||||
encStatus->nChannelsAPI = psEnc->nChannelsAPI;
|
||||
encStatus->nChannelsInternal = psEnc->nChannelsInternal;
|
||||
encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz;
|
||||
encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz;
|
||||
encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz;
|
||||
encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz;
|
||||
encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms;
|
||||
encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps;
|
||||
encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc;
|
||||
encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity;
|
||||
encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC;
|
||||
encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX;
|
||||
encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR;
|
||||
encStatus->internalSampleRate = silk_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 );
|
||||
encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch;
|
||||
encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************/
|
||||
/* Encode frame with Silk */
|
||||
/**************************/
|
||||
/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */
|
||||
/* encControl->payloadSize_ms is set to */
|
||||
opus_int silk_Encode( /* O Returns error code */
|
||||
void *encState, /* I/O State */
|
||||
silk_EncControlStruct *encControl, /* I Control status */
|
||||
const opus_int16 *samplesIn, /* I Speech sample input vector */
|
||||
opus_int nSamplesIn, /* I Number of samples in input vector */
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
|
||||
const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
|
||||
)
|
||||
{
|
||||
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
|
||||
opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;
|
||||
opus_int speech_act_thr_for_switch_Q8;
|
||||
opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum;
|
||||
silk_encoder *psEnc = ( silk_encoder * )encState;
|
||||
opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
|
||||
opus_int transition, curr_block, tot_blocks;
|
||||
|
||||
psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
|
||||
|
||||
/* Check values in encoder control structure */
|
||||
if( ( ret = check_control_input( encControl ) != 0 ) ) {
|
||||
silk_assert( 0 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
encControl->switchReady = 0;
|
||||
|
||||
if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) {
|
||||
/* Mono -> Stereo transition: init state of second channel and stereo state */
|
||||
ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ] );
|
||||
silk_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) );
|
||||
silk_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) );
|
||||
psEnc->sStereo.mid_side_amp_Q0[ 0 ] = 0;
|
||||
psEnc->sStereo.mid_side_amp_Q0[ 1 ] = 1;
|
||||
psEnc->sStereo.mid_side_amp_Q0[ 2 ] = 0;
|
||||
psEnc->sStereo.mid_side_amp_Q0[ 3 ] = 1;
|
||||
psEnc->sStereo.width_prev_Q14 = 0;
|
||||
psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 );
|
||||
if( psEnc->nChannelsAPI == 2 ) {
|
||||
silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) );
|
||||
silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) );
|
||||
}
|
||||
}
|
||||
|
||||
transition = (encControl->payloadSize_ms != psEnc->state_Fxx[ 0 ].sCmn.PacketSize_ms) || (psEnc->nChannelsInternal != encControl->nChannelsInternal);
|
||||
|
||||
psEnc->nChannelsAPI = encControl->nChannelsAPI;
|
||||
psEnc->nChannelsInternal = encControl->nChannelsInternal;
|
||||
|
||||
nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate );
|
||||
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
|
||||
curr_block = 0;
|
||||
if( prefillFlag ) {
|
||||
/* Only accept input length of 10 ms */
|
||||
if( nBlocksOf10ms != 1 ) {
|
||||
ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
silk_assert( 0 );
|
||||
return ret;
|
||||
}
|
||||
/* Reset Encoder */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
if( (ret = silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
}
|
||||
}
|
||||
tmp_payloadSize_ms = encControl->payloadSize_ms;
|
||||
encControl->payloadSize_ms = 10;
|
||||
tmp_complexity = encControl->complexity;
|
||||
encControl->complexity = 0;
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0;
|
||||
psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1;
|
||||
}
|
||||
} else {
|
||||
/* Only accept input lengths that are a multiple of 10 ms */
|
||||
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
|
||||
ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
silk_assert( 0 );
|
||||
return ret;
|
||||
}
|
||||
/* Make sure no more than one packet can be produced */
|
||||
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
|
||||
ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
silk_assert( 0 );
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
/* Force the side channel to the same rate as the mid */
|
||||
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
return ret;
|
||||
}
|
||||
if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) {
|
||||
for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) {
|
||||
psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0;
|
||||
}
|
||||
}
|
||||
psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX;
|
||||
}
|
||||
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
|
||||
|
||||
/* Input buffering/resampling and encoding */
|
||||
while( 1 ) {
|
||||
nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx;
|
||||
nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz );
|
||||
nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 );
|
||||
/* Resample and write to buffer */
|
||||
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
|
||||
opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
|
||||
for( n = 0; n < nSamplesFromInput; n++ ) {
|
||||
buf[ n ] = samplesIn[ 2 * n ];
|
||||
}
|
||||
/* Making sure to start both resamplers from the same state when switching from mono to stereo */
|
||||
if( psEnc->nPrevChannelsInternal == 1 && id==0 ) {
|
||||
silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state));
|
||||
}
|
||||
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
|
||||
|
||||
nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx;
|
||||
nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
|
||||
for( n = 0; n < nSamplesFromInput; n++ ) {
|
||||
buf[ n ] = samplesIn[ 2 * n + 1 ];
|
||||
}
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
|
||||
psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer;
|
||||
} else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) {
|
||||
/* Combine left and right channels before resampling */
|
||||
for( n = 0; n < nSamplesFromInput; n++ ) {
|
||||
sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ];
|
||||
buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 );
|
||||
}
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
/* On the first mono frame, average the results for the two resampler states */
|
||||
if( psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 ) {
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
for( n = 0; n < psEnc->state_Fxx[ 0 ].sCmn.frame_length; n++ ) {
|
||||
psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] =
|
||||
silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ]
|
||||
+ psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1);
|
||||
}
|
||||
}
|
||||
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
|
||||
} else {
|
||||
silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
|
||||
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
|
||||
}
|
||||
|
||||
samplesIn += nSamplesFromInput * encControl->nChannelsAPI;
|
||||
nSamplesIn -= nSamplesFromInput;
|
||||
|
||||
/* Default */
|
||||
psEnc->allowBandwidthSwitch = 0;
|
||||
|
||||
/* Silk encoder */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {
|
||||
/* Enough data in input buffer, so encode */
|
||||
silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
|
||||
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
|
||||
|
||||
/* Deal with LBRR data */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) {
|
||||
/* Create space at start of payload for VAD and FEC flags */
|
||||
opus_uint8 iCDF[ 2 ] = { 0, 0 };
|
||||
iCDF[ 0 ] = 256 - silk_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal );
|
||||
ec_enc_icdf( psRangeEnc, 0, iCDF, 8 );
|
||||
|
||||
/* Encode any LBRR data from previous packet */
|
||||
/* Encode LBRR flags */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
LBRR_symbol = 0;
|
||||
for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) {
|
||||
LBRR_symbol |= silk_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i );
|
||||
}
|
||||
psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0;
|
||||
if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) {
|
||||
ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Code LBRR indices and excitation signals */
|
||||
for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) {
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) {
|
||||
opus_int condCoding;
|
||||
|
||||
if( encControl->nChannelsInternal == 2 && n == 0 ) {
|
||||
silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ i ] );
|
||||
/* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */
|
||||
if( psEnc->state_Fxx[ 1 ].sCmn.LBRR_flags[ i ] == 0 ) {
|
||||
silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ i ] );
|
||||
}
|
||||
}
|
||||
/* Use conditional coding if previous frame available */
|
||||
if( i > 0 && psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i - 1 ] ) {
|
||||
condCoding = CODE_CONDITIONALLY;
|
||||
} else {
|
||||
condCoding = CODE_INDEPENDENTLY;
|
||||
}
|
||||
silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1, condCoding );
|
||||
silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType,
|
||||
psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset LBRR flags */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) );
|
||||
}
|
||||
}
|
||||
|
||||
silk_HP_variable_cutoff( psEnc->state_Fxx );
|
||||
|
||||
/* Total target bits for packet */
|
||||
nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 );
|
||||
/* Subtract half of the bits already used */
|
||||
if( !prefillFlag ) {
|
||||
nBits -= ec_tell( psRangeEnc ) >> 1;
|
||||
}
|
||||
/* Divide by number of uncoded frames left in packet */
|
||||
nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded );
|
||||
/* Convert to bits/second */
|
||||
if( encControl->payloadSize_ms == 10 ) {
|
||||
TargetRate_bps = silk_SMULBB( nBits, 100 );
|
||||
} else {
|
||||
TargetRate_bps = silk_SMULBB( nBits, 50 );
|
||||
}
|
||||
/* Subtract fraction of bits in excess of target in previous packets */
|
||||
TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS );
|
||||
/* Never exceed input bitrate */
|
||||
TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 );
|
||||
|
||||
/* Convert Left/Right to Mid/Side */
|
||||
if( encControl->nChannelsInternal == 2 ) {
|
||||
silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ],
|
||||
psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ],
|
||||
MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono,
|
||||
psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length );
|
||||
if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) {
|
||||
/* Reset side channel encoder memory for first frame with side coding */
|
||||
if( psEnc->prev_decode_only_middle == 1 ) {
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) );
|
||||
silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) );
|
||||
psEnc->state_Fxx[ 1 ].sCmn.prevLag = 100;
|
||||
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev = 100;
|
||||
psEnc->state_Fxx[ 1 ].sShape.LastGainIndex = 10;
|
||||
psEnc->state_Fxx[ 1 ].sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536;
|
||||
psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1;
|
||||
}
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] );
|
||||
} else {
|
||||
psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0;
|
||||
}
|
||||
if( !prefillFlag ) {
|
||||
silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] );
|
||||
if( psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) {
|
||||
silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Buffering */
|
||||
silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) );
|
||||
silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) );
|
||||
}
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] );
|
||||
|
||||
/* Encode */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
opus_int maxBits, useCBR;
|
||||
|
||||
/* Handling rate constraints */
|
||||
maxBits = encControl->maxBits;
|
||||
if( tot_blocks == 2 && curr_block == 0 ) {
|
||||
maxBits = maxBits * 3 / 5;
|
||||
} else if( tot_blocks == 3 ) {
|
||||
if( curr_block == 0 ) {
|
||||
maxBits = maxBits * 2 / 5;
|
||||
} else if( curr_block == 1 ) {
|
||||
maxBits = maxBits * 3 / 4;
|
||||
}
|
||||
}
|
||||
useCBR = encControl->useCBR && curr_block == tot_blocks - 1;
|
||||
|
||||
if( encControl->nChannelsInternal == 1 ) {
|
||||
channelRate_bps = TargetRate_bps;
|
||||
} else {
|
||||
channelRate_bps = MStargetRates_bps[ n ];
|
||||
if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) {
|
||||
useCBR = 0;
|
||||
/* Give mid up to 1/2 of the max bits for that frame */
|
||||
maxBits -= encControl->maxBits / ( tot_blocks * 2 );
|
||||
}
|
||||
}
|
||||
|
||||
if( channelRate_bps > 0 ) {
|
||||
opus_int condCoding;
|
||||
|
||||
silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps );
|
||||
|
||||
/* Use independent coding if no previous frame available */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - n <= 0 ) {
|
||||
condCoding = CODE_INDEPENDENTLY;
|
||||
} else if( n > 0 && psEnc->prev_decode_only_middle ) {
|
||||
/* If we skipped a side frame in this packet, we don't
|
||||
need LTP scaling; the LTP state is well-defined. */
|
||||
condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING;
|
||||
} else {
|
||||
condCoding = CODE_CONDITIONALLY;
|
||||
}
|
||||
if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
}
|
||||
}
|
||||
psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0;
|
||||
psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0;
|
||||
psEnc->state_Fxx[ n ].sCmn.nFramesEncoded++;
|
||||
}
|
||||
psEnc->prev_decode_only_middle = psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - 1 ];
|
||||
|
||||
/* Insert VAD and FEC flags at beginning of bitstream */
|
||||
if( *nBytesOut > 0 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket) {
|
||||
flags = 0;
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) {
|
||||
flags = silk_LSHIFT( flags, 1 );
|
||||
flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ];
|
||||
}
|
||||
flags = silk_LSHIFT( flags, 1 );
|
||||
flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag;
|
||||
}
|
||||
if( !prefillFlag ) {
|
||||
ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal );
|
||||
}
|
||||
|
||||
/* Return zero bytes if all channels DTXed */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) {
|
||||
*nBytesOut = 0;
|
||||
}
|
||||
|
||||
psEnc->nBitsExceeded += *nBytesOut * 8;
|
||||
psEnc->nBitsExceeded -= silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 );
|
||||
psEnc->nBitsExceeded = silk_LIMIT( psEnc->nBitsExceeded, 0, 10000 );
|
||||
|
||||
/* Update flag indicating if bandwidth switching is allowed */
|
||||
speech_act_thr_for_switch_Q8 = silk_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ),
|
||||
SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms );
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) {
|
||||
psEnc->allowBandwidthSwitch = 1;
|
||||
psEnc->timeSinceSwitchAllowed_ms = 0;
|
||||
} else {
|
||||
psEnc->allowBandwidthSwitch = 0;
|
||||
psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms;
|
||||
}
|
||||
}
|
||||
|
||||
if( nSamplesIn == 0 ) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
curr_block++;
|
||||
}
|
||||
|
||||
psEnc->nPrevChannelsInternal = encControl->nChannelsInternal;
|
||||
|
||||
encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch;
|
||||
encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0;
|
||||
encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 );
|
||||
encControl->stereoWidth_Q14 = encControl->toMono ? 0 : psEnc->sStereo.smth_width_Q14;
|
||||
if( prefillFlag ) {
|
||||
encControl->payloadSize_ms = tmp_payloadSize_ms;
|
||||
encControl->complexity = tmp_complexity;
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0;
|
||||
psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Encode side-information parameters to payload */
|
||||
void silk_encode_indices(
|
||||
silk_encoder_state *psEncC, /* I/O Encoder state */
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
opus_int FrameIndex, /* I Frame number */
|
||||
opus_int encode_LBRR, /* I Flag indicating LBRR data is being encoded */
|
||||
opus_int condCoding /* I The type of conditional coding to use */
|
||||
)
|
||||
{
|
||||
opus_int i, k, typeOffset;
|
||||
opus_int encode_absolute_lagIndex, delta_lagIndex;
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
const SideInfoIndices *psIndices;
|
||||
|
||||
if( encode_LBRR ) {
|
||||
psIndices = &psEncC->indices_LBRR[ FrameIndex ];
|
||||
} else {
|
||||
psIndices = &psEncC->indices;
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
/* Encode signal type and quantizer offset */
|
||||
/*******************************************/
|
||||
typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType;
|
||||
silk_assert( typeOffset >= 0 && typeOffset < 6 );
|
||||
silk_assert( encode_LBRR == 0 || typeOffset >= 2 );
|
||||
if( encode_LBRR || typeOffset >= 2 ) {
|
||||
ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 );
|
||||
} else {
|
||||
ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 );
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* Encode gains */
|
||||
/****************/
|
||||
/* first subframe */
|
||||
if( condCoding == CODE_CONDITIONALLY ) {
|
||||
/* conditional coding */
|
||||
silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 );
|
||||
} else {
|
||||
/* independent coding, in two stages: MSB bits followed by 3 LSBs */
|
||||
silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN );
|
||||
ec_enc_icdf( psRangeEnc, silk_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 );
|
||||
}
|
||||
|
||||
/* remaining subframes */
|
||||
for( i = 1; i < psEncC->nb_subfr; i++ ) {
|
||||
silk_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 );
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* Encode NLSFs */
|
||||
/****************/
|
||||
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 );
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] );
|
||||
silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
|
||||
for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) {
|
||||
if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 );
|
||||
} else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 );
|
||||
} else {
|
||||
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode NLSF interpolation factor */
|
||||
if( psEncC->nb_subfr == MAX_NB_SUBFR ) {
|
||||
silk_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 );
|
||||
}
|
||||
|
||||
if( psIndices->signalType == TYPE_VOICED )
|
||||
{
|
||||
/*********************/
|
||||
/* Encode pitch lags */
|
||||
/*********************/
|
||||
/* lag index */
|
||||
encode_absolute_lagIndex = 1;
|
||||
if( condCoding == CODE_CONDITIONALLY && psEncC->ec_prevSignalType == TYPE_VOICED ) {
|
||||
/* Delta Encoding */
|
||||
delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex;
|
||||
if( delta_lagIndex < -8 || delta_lagIndex > 11 ) {
|
||||
delta_lagIndex = 0;
|
||||
} else {
|
||||
delta_lagIndex = delta_lagIndex + 9;
|
||||
encode_absolute_lagIndex = 0; /* Only use delta */
|
||||
}
|
||||
silk_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 );
|
||||
ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 );
|
||||
}
|
||||
if( encode_absolute_lagIndex ) {
|
||||
/* Absolute encoding */
|
||||
opus_int32 pitch_high_bits, pitch_low_bits;
|
||||
pitch_high_bits = silk_DIV32_16( psIndices->lagIndex, silk_RSHIFT( psEncC->fs_kHz, 1 ) );
|
||||
pitch_low_bits = psIndices->lagIndex - silk_SMULBB( pitch_high_bits, silk_RSHIFT( psEncC->fs_kHz, 1 ) );
|
||||
silk_assert( pitch_low_bits < psEncC->fs_kHz / 2 );
|
||||
silk_assert( pitch_high_bits < 32 );
|
||||
ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 );
|
||||
ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 );
|
||||
}
|
||||
psEncC->ec_prevLagIndex = psIndices->lagIndex;
|
||||
|
||||
/* Countour index */
|
||||
silk_assert( psIndices->contourIndex >= 0 );
|
||||
silk_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) ||
|
||||
( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) ||
|
||||
( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) ||
|
||||
( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 );
|
||||
|
||||
/********************/
|
||||
/* Encode LTP gains */
|
||||
/********************/
|
||||
/* PERIndex value */
|
||||
silk_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 );
|
||||
|
||||
/* Codebook Indices */
|
||||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
silk_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 );
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Encode LTP scaling */
|
||||
/**********************/
|
||||
if( condCoding == CODE_INDEPENDENTLY ) {
|
||||
silk_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 );
|
||||
}
|
||||
silk_assert( !condCoding || psIndices->LTP_scaleIndex == 0 );
|
||||
}
|
||||
|
||||
psEncC->ec_prevSignalType = psIndices->signalType;
|
||||
|
||||
/***************/
|
||||
/* Encode seed */
|
||||
/***************/
|
||||
silk_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 );
|
||||
ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 );
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Encode quantization indices of excitation */
|
||||
/*********************************************/
|
||||
|
||||
static inline opus_int combine_and_check( /* return ok */
|
||||
opus_int *pulses_comb, /* O */
|
||||
const opus_int *pulses_in, /* I */
|
||||
opus_int max_pulses, /* I max value for sum of pulses */
|
||||
opus_int len /* I number of output values */
|
||||
)
|
||||
{
|
||||
opus_int k, sum;
|
||||
|
||||
for( k = 0; k < len; k++ ) {
|
||||
sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ];
|
||||
if( sum > max_pulses ) {
|
||||
return 1;
|
||||
}
|
||||
pulses_comb[ k ] = sum;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encode quantization indices of excitation */
|
||||
void silk_encode_pulses(
|
||||
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
||||
const opus_int signalType, /* I Signal type */
|
||||
const opus_int quantOffsetType, /* I quantOffsetType */
|
||||
opus_int8 pulses[], /* I quantization indices */
|
||||
const opus_int frame_length /* I Frame length */
|
||||
)
|
||||
{
|
||||
opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
|
||||
opus_int32 abs_q, minSumBits_Q5, sumBits_Q5;
|
||||
opus_int abs_pulses[ MAX_FRAME_LENGTH ];
|
||||
opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ];
|
||||
opus_int nRshifts[ MAX_NB_SHELL_BLOCKS ];
|
||||
opus_int pulses_comb[ 8 ];
|
||||
opus_int *abs_pulses_ptr;
|
||||
const opus_int8 *pulses_ptr;
|
||||
const opus_uint8 *cdf_ptr;
|
||||
const opus_uint8 *nBits_ptr;
|
||||
|
||||
silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/
|
||||
|
||||
/****************************/
|
||||
/* Prepare for shell coding */
|
||||
/****************************/
|
||||
/* Calculate number of shell blocks */
|
||||
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
|
||||
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
|
||||
silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
iter++;
|
||||
silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8));
|
||||
}
|
||||
|
||||
/* Take the absolute value of the pulses */
|
||||
for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) {
|
||||
abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] );
|
||||
abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] );
|
||||
abs_pulses[i+2] = ( opus_int )silk_abs( pulses[ i + 2 ] );
|
||||
abs_pulses[i+3] = ( opus_int )silk_abs( pulses[ i + 3 ] );
|
||||
}
|
||||
|
||||
/* Calc sum pulses per shell code frame */
|
||||
abs_pulses_ptr = abs_pulses;
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
nRshifts[ i ] = 0;
|
||||
|
||||
while( 1 ) {
|
||||
/* 1+1 -> 2 */
|
||||
scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 );
|
||||
/* 2+2 -> 4 */
|
||||
scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 );
|
||||
/* 4+4 -> 8 */
|
||||
scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 );
|
||||
/* 8+8 -> 16 */
|
||||
scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 );
|
||||
|
||||
if( scale_down ) {
|
||||
/* We need to downscale the quantization signal */
|
||||
nRshifts[ i ]++;
|
||||
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
|
||||
abs_pulses_ptr[ k ] = silk_RSHIFT( abs_pulses_ptr[ k ], 1 );
|
||||
}
|
||||
} else {
|
||||
/* Jump out of while(1) loop and go to next shell coding frame */
|
||||
break;
|
||||
}
|
||||
}
|
||||
abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH;
|
||||
}
|
||||
|
||||
/**************/
|
||||
/* Rate level */
|
||||
/**************/
|
||||
/* find rate level that leads to fewest bits for coding of pulses per block info */
|
||||
minSumBits_Q5 = silk_int32_MAX;
|
||||
for( k = 0; k < N_RATE_LEVELS - 1; k++ ) {
|
||||
nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ];
|
||||
sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ];
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( nRshifts[ i ] > 0 ) {
|
||||
sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ];
|
||||
} else {
|
||||
sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ];
|
||||
}
|
||||
}
|
||||
if( sumBits_Q5 < minSumBits_Q5 ) {
|
||||
minSumBits_Q5 = sumBits_Q5;
|
||||
RateLevelIndex = k;
|
||||
}
|
||||
}
|
||||
ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
|
||||
|
||||
/***************************************************/
|
||||
/* Sum-Weighted-Pulses Encoding */
|
||||
/***************************************************/
|
||||
cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( nRshifts[ i ] == 0 ) {
|
||||
ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 );
|
||||
} else {
|
||||
ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 );
|
||||
for( k = 0; k < nRshifts[ i ] - 1; k++ ) {
|
||||
ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 );
|
||||
}
|
||||
ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 );
|
||||
}
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Shell Encoding */
|
||||
/******************/
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( sum_pulses[ i ] > 0 ) {
|
||||
silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] );
|
||||
}
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* LSB Encoding */
|
||||
/****************/
|
||||
for( i = 0; i < iter; i++ ) {
|
||||
if( nRshifts[ i ] > 0 ) {
|
||||
pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ];
|
||||
nLS = nRshifts[ i ] - 1;
|
||||
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
|
||||
abs_q = (opus_int8)silk_abs( pulses_ptr[ k ] );
|
||||
for( j = nLS; j > 0; j-- ) {
|
||||
bit = silk_RSHIFT( abs_q, j ) & 1;
|
||||
ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 );
|
||||
}
|
||||
bit = abs_q & 1;
|
||||
ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* Encode signs */
|
||||
/****************/
|
||||
silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_ERRORS_H
|
||||
#define SILK_ERRORS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/******************/
|
||||
/* Error messages */
|
||||
/******************/
|
||||
#define SILK_NO_ERROR 0
|
||||
|
||||
/**************************/
|
||||
/* Encoder error messages */
|
||||
/**************************/
|
||||
|
||||
/* Input length is not a multiple of 10 ms, or length is longer than the packet length */
|
||||
#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -101
|
||||
|
||||
/* Sampling frequency not 8000, 12000 or 16000 Hertz */
|
||||
#define SILK_ENC_FS_NOT_SUPPORTED -102
|
||||
|
||||
/* Packet size not 10, 20, 40, or 60 ms */
|
||||
#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -103
|
||||
|
||||
/* Allocated payload buffer too short */
|
||||
#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT -104
|
||||
|
||||
/* Loss rate not between 0 and 100 percent */
|
||||
#define SILK_ENC_INVALID_LOSS_RATE -105
|
||||
|
||||
/* Complexity setting not valid, use 0...10 */
|
||||
#define SILK_ENC_INVALID_COMPLEXITY_SETTING -106
|
||||
|
||||
/* Inband FEC setting not valid, use 0 or 1 */
|
||||
#define SILK_ENC_INVALID_INBAND_FEC_SETTING -107
|
||||
|
||||
/* DTX setting not valid, use 0 or 1 */
|
||||
#define SILK_ENC_INVALID_DTX_SETTING -108
|
||||
|
||||
/* CBR setting not valid, use 0 or 1 */
|
||||
#define SILK_ENC_INVALID_CBR_SETTING -109
|
||||
|
||||
/* Internal encoder error */
|
||||
#define SILK_ENC_INTERNAL_ERROR -110
|
||||
|
||||
/* Internal encoder error */
|
||||
#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR -111
|
||||
|
||||
/**************************/
|
||||
/* Decoder error messages */
|
||||
/**************************/
|
||||
|
||||
/* Output sampling frequency lower than internal decoded sampling frequency */
|
||||
#define SILK_DEC_INVALID_SAMPLING_FREQUENCY -200
|
||||
|
||||
/* Payload size exceeded the maximum allowed 1024 bytes */
|
||||
#define SILK_DEC_PAYLOAD_TOO_LARGE -201
|
||||
|
||||
/* Payload has bit errors */
|
||||
#define SILK_DEC_PAYLOAD_ERROR -202
|
||||
|
||||
/* Payload has bit errors */
|
||||
#define SILK_DEC_INVALID_FRAME_SIZE -203
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main_FIX.h"
|
||||
|
||||
void silk_LTP_analysis_filter_FIX(
|
||||
opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */
|
||||
const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */
|
||||
const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */
|
||||
const opus_int subfr_length, /* I Length of each subframe */
|
||||
const opus_int nb_subfr, /* I Number of subframes */
|
||||
const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */
|
||||
)
|
||||
{
|
||||
const opus_int16 *x_ptr, *x_lag_ptr;
|
||||
opus_int16 Btmp_Q14[ LTP_ORDER ];
|
||||
opus_int16 *LTP_res_ptr;
|
||||
opus_int k, i, j;
|
||||
opus_int32 LTP_est;
|
||||
|
||||
x_ptr = x;
|
||||
LTP_res_ptr = LTP_res;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
|
||||
x_lag_ptr = x_ptr - pitchL[ k ];
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
Btmp_Q14[ i ] = LTPCoef_Q14[ k * LTP_ORDER + i ];
|
||||
}
|
||||
|
||||
/* LTP analysis FIR filter */
|
||||
for( i = 0; i < subfr_length + pre_length; i++ ) {
|
||||
LTP_res_ptr[ i ] = x_ptr[ i ];
|
||||
|
||||
/* Long-term prediction */
|
||||
LTP_est = silk_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] );
|
||||
for( j = 1; j < LTP_ORDER; j++ ) {
|
||||
LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] );
|
||||
}
|
||||
LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/
|
||||
|
||||
/* Subtract long-term prediction */
|
||||
LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est );
|
||||
|
||||
/* Scale residual */
|
||||
LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] );
|
||||
|
||||
x_lag_ptr++;
|
||||
}
|
||||
|
||||
/* Update pointers */
|
||||
LTP_res_ptr += subfr_length + pre_length;
|
||||
x_ptr += subfr_length;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue